funifier-mcp 0.2.0 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/.cursor/rules/funifier.mdc +91 -0
  2. package/.github/copilot-instructions.md +83 -0
  3. package/AGENTS.md +97 -0
  4. package/README.md +247 -78
  5. package/datasource-funifier-docs/knowledge/guides/aggregates.md +152 -152
  6. package/datasource-funifier-docs/knowledge/guides/database-access.md +132 -132
  7. package/datasource-funifier-docs/knowledge/guides/java-entities.md +373 -373
  8. package/datasource-funifier-docs/knowledge/guides/java-libraries.md +330 -330
  9. package/datasource-funifier-docs/knowledge/guides/java-managers.md +509 -509
  10. package/datasource-funifier-docs/knowledge/guides/triggers-guide.md +271 -271
  11. package/datasource-funifier-docs/knowledge/index.md +121 -121
  12. package/datasource-funifier-docs/knowledge/modules/achievement.md +46 -46
  13. package/datasource-funifier-docs/knowledge/modules/action-log.md +88 -88
  14. package/datasource-funifier-docs/knowledge/modules/action.md +80 -80
  15. package/datasource-funifier-docs/knowledge/modules/auth.md +104 -104
  16. package/datasource-funifier-docs/knowledge/modules/avatar.md +28 -28
  17. package/datasource-funifier-docs/knowledge/modules/backup.md +40 -40
  18. package/datasource-funifier-docs/knowledge/modules/challenge.md +91 -91
  19. package/datasource-funifier-docs/knowledge/modules/compact.md +40 -40
  20. package/datasource-funifier-docs/knowledge/modules/competition.md +149 -149
  21. package/datasource-funifier-docs/knowledge/modules/crossword.md +41 -41
  22. package/datasource-funifier-docs/knowledge/modules/csv-data.md +30 -30
  23. package/datasource-funifier-docs/knowledge/modules/custom-object.md +53 -53
  24. package/datasource-funifier-docs/knowledge/modules/database.md +241 -241
  25. package/datasource-funifier-docs/knowledge/modules/folder.md +111 -111
  26. package/datasource-funifier-docs/knowledge/modules/kpi-formulas.md +23 -23
  27. package/datasource-funifier-docs/knowledge/modules/lastmile.md +45 -45
  28. package/datasource-funifier-docs/knowledge/modules/leaderboard.md +98 -98
  29. package/datasource-funifier-docs/knowledge/modules/level.md +83 -83
  30. package/datasource-funifier-docs/knowledge/modules/lottery.md +112 -112
  31. package/datasource-funifier-docs/knowledge/modules/marketplace.md +27 -27
  32. package/datasource-funifier-docs/knowledge/modules/mystery.md +82 -82
  33. package/datasource-funifier-docs/knowledge/modules/notification.md +40 -40
  34. package/datasource-funifier-docs/knowledge/modules/patterns.md +1096 -1096
  35. package/datasource-funifier-docs/knowledge/modules/player.md +101 -101
  36. package/datasource-funifier-docs/knowledge/modules/point.md +67 -67
  37. package/datasource-funifier-docs/knowledge/modules/public.md +253 -253
  38. package/datasource-funifier-docs/knowledge/modules/question.md +136 -136
  39. package/datasource-funifier-docs/knowledge/modules/quiz.md +163 -163
  40. package/datasource-funifier-docs/knowledge/modules/scheduler.md +58 -58
  41. package/datasource-funifier-docs/knowledge/modules/security.md +169 -169
  42. package/datasource-funifier-docs/knowledge/modules/staging.md +28 -28
  43. package/datasource-funifier-docs/knowledge/modules/static-repo.md +41 -41
  44. package/datasource-funifier-docs/knowledge/modules/story.md +42 -42
  45. package/datasource-funifier-docs/knowledge/modules/studio-page.md +180 -180
  46. package/datasource-funifier-docs/knowledge/modules/swap.md +132 -132
  47. package/datasource-funifier-docs/knowledge/modules/team.md +75 -75
  48. package/datasource-funifier-docs/knowledge/modules/trigger.md +189 -189
  49. package/datasource-funifier-docs/knowledge/modules/upload.md +155 -155
  50. package/datasource-funifier-docs/knowledge/modules/virtual-good.md +99 -99
  51. package/datasource-funifier-docs/knowledge/modules/webhook.md +41 -41
  52. package/datasource-funifier-docs/knowledge/modules/websocket.md +41 -41
  53. package/datasource-funifier-docs/knowledge/modules/widget.md +42 -42
  54. package/datasource-funifier-docs/process-gtm-saas.md +143 -143
  55. package/datasource-funifier-docs/process-instagram.md +88 -88
  56. package/datasource-funifier-docs/process.md +1826 -1826
  57. package/datasource-funifier-docs/readme.md +132 -132
  58. package/dist/cli/config-writers.js +11 -11
  59. package/dist/mcp/bundle.js +82 -77
  60. package/package.json +70 -67
  61. package/skills/funifier-create-aggregate/SKILL.md +126 -126
  62. package/skills/funifier-create-custom-page/SKILL.md +126 -126
  63. package/skills/funifier-create-scheduler/SKILL.md +126 -126
  64. package/skills/funifier-create-trigger/SKILL.md +127 -127
@@ -1,189 +1,189 @@
1
- # Trigger (Trigger)
2
-
3
- **Acesso Studio:** `/studio/trigger`
4
- **API Endpoint:** `/v3/trigger`
5
-
6
- ## O que é
7
-
8
- Execução automática de códigos JAVA quando eventos específicos acontecem na gamificação. Permite programar ações customizadas disparadas por eventos, como o cadastro de um jogador ou a realização de uma compra. As triggers dão liberdade para alterar o comportamento padrão dos módulos, integrar com sistemas externos ou implementar automações em tempo real.
9
-
10
- ## Quando usar
11
-
12
- - Para enviar emails automáticos (ex: boas-vindas)
13
- - Para integrar com APIs externas (Zapier, CRM, etc.)
14
- - Para alterar pontuação com regras especiais
15
- - Para executar lógica de negócio personalizada
16
- - **Importante:** usar apenas quando as configurações padrão não atendem
17
-
18
- ## Checklist de Configuração no Studio
19
-
20
- - [ ] Definir nome e descrição da trigger
21
- - [ ] Definir entidade observada (player, challenge, action, achievement, etc.)
22
- - [ ] Definir evento (before_create, after_create, before_win, after_win, etc.)
23
- - [ ] Escrever script Java com método `void trigger(event, entity, player, database)`
24
- - [ ] Testar trigger em ambiente de homologação
25
-
26
- ## Eventos Disponíveis
27
-
28
- | Prefixo | Sufixo | Descrição |
29
- |---------|--------|-----------|
30
- | before_ | create | Antes de criar |
31
- | after_ | create | Depois de criar |
32
- | before_ | update | Antes de atualizar |
33
- | after_ | delete | Depois de deletar |
34
- | before_ | win | Antes de conquistar |
35
- | after_ | win | Depois de conquistar |
36
-
37
- ## Entidades Disponíveis
38
-
39
- - `player`, `action`, `challenge`, `achievement`, `level`, `catalog_item`, `lottery`, `mystery_box`, `competition`, `question_log`, `<custom>__c`
40
-
41
- ## API Endpoints
42
-
43
- ### Listar Triggers
44
- **Método:** GET
45
- **Endpoint:** `/v3/trigger`
46
-
47
- ### Criar Trigger
48
- **Método:** POST
49
- **Endpoint:** `/v3/trigger`
50
-
51
- **Exemplo de Body:**
52
- ```json
53
- {
54
- "name": "Make the player's name uppercase",
55
- "_id": "DTv7uHc",
56
- "description": "Before creating the player, change the letters of the name to uppercase",
57
- "entity": "player",
58
- "event": "before_create",
59
- "script": "void trigger(event, entity, player, database){ entity.name = entity.name.toUpperCase(); }"
60
- }
61
- ```
62
-
63
- ### Deletar Trigger
64
- **Método:** DELETE
65
- **Endpoint:** `/v3/trigger/:id`
66
-
67
- ## Script Runtime Environment (Wrapper Class)
68
-
69
- O script da trigger **não é standalone** — ele é inserido dentro de uma classe Java wrapper gerada pelo Funifier, idêntica à do Public Endpoint (ver `public.md` para a lista completa de imports).
70
-
71
- ### Regras
72
-
73
- 1. **NÃO use `import`** — todos os imports já estão no wrapper (Unirest, Groovy JSON, Funifier entities/utils, Apache HTTP, Simple Java Mail, etc.)
74
- 2. Se precisar de uma classe não importada, use o nome completo: `com.example.MinhaClasse`
75
- 3. **`manager`** (ManagerFactory) está disponível como campo da classe
76
- 4. **Timeout padrão de 10 segundos** — pode ser customizado via campo `timeout` (em **segundos**) na API: `POST /v3/trigger` com `{"_id": "trigger_id", "timeout": 30}`. Este campo não aparece no Studio.
77
- 5. Scripts rodam em **Groovy** — cuidado com `$` em GStrings (usar `String.valueOf((char)0x24)` para operadores MongoDB)
78
- 6. Use apenas **ASCII em comentários** — UTF-8 especial pode causar parse errors
79
-
80
- > 📖 Ver `public.md` → **Script Runtime Environment** para a lista completa de imports e bibliotecas disponíveis.
81
-
82
- ## Parâmetros do Script
83
-
84
- - `event` (String): evento acionado
85
- - `entity` (Object): objeto sendo manipulado (Player, ActionLog, Achievement, etc.)
86
- - `player` (String): ID do jogador
87
- - `database` (Object): utilitário para acessar o banco de dados
88
-
89
- ### ⚠️ CRITICAL: `entity` Type Depends on the Trigger Entity
90
-
91
- O tipo do parâmetro `entity` varia conforme a entidade da trigger:
92
-
93
- | Trigger Entity | Tipo de `entity` | Como acessar campos |
94
- |---|---|---|
95
- | `player` | `com.funifier.engine.player.Player` (objeto Java) | `entity.id`, `entity.name`, `entity.email`, `entity.extra` |
96
- | `<custom>__c` | `java.util.Map` (documento MongoDB) | `entity.get("campo")`, `entity.put("campo", valor)` |
97
- | `action` | `com.funifier.engine.action.ActionLog` | `entity.userId`, `entity.actionId`, `entity.attributes` |
98
- | `achievement` | `com.funifier.engine.achievement.Achievement` | `entity.achievementId`, `entity.userId` |
99
-
100
- **Erros comuns:**
101
- - ❌ `entity.get("_id")` em trigger de `player` → `MissingMethodException: No signature of method: Player.get()`
102
- - ✅ `entity.id` em trigger de `player`
103
- - ❌ `entity.id` em trigger de `signup__c` → campo não existe no Map
104
- - ✅ `entity.get("_id")` em trigger de `signup__c`
105
-
106
- **Player fields (via `PlayerManager.java`):**
107
- ```
108
- entity.id → String (_id do player)
109
- entity.name → String
110
- entity.email → String
111
- entity.password → String (hash BCrypt)
112
- entity.extra → Map<String, Object> (campos customizados)
113
- entity.image → Image object
114
- entity.business → boolean
115
- entity.developer → boolean
116
- ```
117
-
118
- **Fonte:** `PlayerManager.delete()` chama `TriggerRunner.run()` com `new Object[] { event, playerObject, playerId, gameDao }` — logo `entity` é o objeto `Player` completo, não um Map.
119
-
120
- ## Verificando Logs de Trigger (Studio)
121
-
122
- Para ver se uma trigger executou com sucesso ou com erro:
123
-
124
- 1. Acessar **Studio** → menu lateral → **Triggers**
125
- 2. Na lista de triggers, cada uma tem um botão **🔥 Logs** na coluna OPERAÇÕES
126
- 3. Clicar em **Logs** abre um modal com:
127
- - **Log Id**: identificador da trigger
128
- - **Executou em**: data/hora da última execução
129
- - **Tempo de resposta**: tempo de execução em ms
130
- - **Erros**: se houve erro, mostra a exception completa em vermelho
131
- 4. Se não houver seção "Erros", a trigger executou com sucesso
132
-
133
- **Dica:** Após alterar uma trigger via API (`POST /v3/trigger`), teste-a e verifique o log no Studio para confirmar que não há erros de compilação ou runtime.
134
-
135
- ## Utilitários Disponíveis no Contexto
136
-
137
- | Classe/Método | Descrição |
138
- |---|---|
139
- | `Guid.newShortGuid()` | Gera um ID curto único (7 chars, ex: `FnwjKEY`) |
140
- | `Guid.newGuid()` | Gera um GUID completo |
141
- | `newShortGuid()` | ❌ **NÃO FUNCIONA** — precisa do prefixo `Guid.` |
142
- | `com.funifier.engine.util.BCrypt.hashpw(pwd, BCrypt.gensalt())` | Hash de senha BCrypt |
143
- | `new Date().getTime()` | Timestamp atual em milissegundos |
144
- | `manager` | ManagerFactory — acesso a todos os managers |
145
-
146
- > ⚠️ `System.currentTimeMillis()` é BLOQUEADO pelo SecureASTCustomizer. Usar `new Date().getTime()`.
147
-
148
- ## Managers Disponíveis
149
-
150
- - `manager.getPlayerManager()` - findById, insert, delete
151
- - `manager.getActionManager()` - findActionById, track, trackSynchronous
152
- - `manager.getCatalogManager()` - findItemById, purchase, undoPurchase
153
- - `manager.getLotteryManager()` - find, insertTicket, execute
154
- - `manager.getAchievementManager()` - addAchievement
155
- - `manager.getJongoConnection()` - acesso direto ao MongoDB
156
-
157
- ## Envio de Email
158
-
159
- As triggers podem enviar emails usando o servidor SMTP configurado na gamificação. As classes do Simple Java Mail e utilitários Funifier já estão disponíveis no contexto (não precisa importar).
160
-
161
- ### Classes disponíveis
162
- - `EmailBuilder` / `MailerBuilder` — Simple Java Mail (construir e enviar)
163
- - `com.funifier.engine.mail.MailContext` — config SMTP da gamificação
164
- - `com.funifier.controller.Configuration` — acesso à configuração atual
165
- - `com.funifier.engine.util.MustacheUtils` — parse de templates com variáveis `{{campo}}`
166
-
167
- ### Exemplo básico
168
- ```java
169
- Email email = EmailBuilder.startingBlank()
170
- .from("App", "noreply@funifier.com")
171
- .to(nome, emailDestinatario)
172
- .withSubject("Assunto")
173
- .withHTMLText("<h1>Olá</h1>")
174
- .buildEmail();
175
-
176
- com.funifier.engine.mail.MailContext ctx = com.funifier.controller.Configuration.getCurrentConfiguration().getMailContext();
177
- MailerBuilder.withSMTPServer(ctx.hostName, ctx.smtpPort, ctx.authUser, ctx.authPassword)
178
- .buildMailer()
179
- .sendMail(email);
180
- ```
181
-
182
- > 📖 Para o pattern completo com templates editáveis e Mustache, ver `patterns.md` → **Email Template Pattern**
183
-
184
- ## Validações e Testes
185
-
186
- - [ ] Trigger aparece na lista GET /v3/trigger
187
- - [ ] Evento é disparado corretamente
188
- - [ ] Script executa sem erros
189
- - [ ] Testar em staging antes de produção
1
+ # Trigger (Trigger)
2
+
3
+ **Acesso Studio:** `/studio/trigger`
4
+ **API Endpoint:** `/v3/trigger`
5
+
6
+ ## O que é
7
+
8
+ Execução automática de códigos JAVA quando eventos específicos acontecem na gamificação. Permite programar ações customizadas disparadas por eventos, como o cadastro de um jogador ou a realização de uma compra. As triggers dão liberdade para alterar o comportamento padrão dos módulos, integrar com sistemas externos ou implementar automações em tempo real.
9
+
10
+ ## Quando usar
11
+
12
+ - Para enviar emails automáticos (ex: boas-vindas)
13
+ - Para integrar com APIs externas (Zapier, CRM, etc.)
14
+ - Para alterar pontuação com regras especiais
15
+ - Para executar lógica de negócio personalizada
16
+ - **Importante:** usar apenas quando as configurações padrão não atendem
17
+
18
+ ## Checklist de Configuração no Studio
19
+
20
+ - [ ] Definir nome e descrição da trigger
21
+ - [ ] Definir entidade observada (player, challenge, action, achievement, etc.)
22
+ - [ ] Definir evento (before_create, after_create, before_win, after_win, etc.)
23
+ - [ ] Escrever script Java com método `void trigger(event, entity, player, database)`
24
+ - [ ] Testar trigger em ambiente de homologação
25
+
26
+ ## Eventos Disponíveis
27
+
28
+ | Prefixo | Sufixo | Descrição |
29
+ |---------|--------|-----------|
30
+ | before_ | create | Antes de criar |
31
+ | after_ | create | Depois de criar |
32
+ | before_ | update | Antes de atualizar |
33
+ | after_ | delete | Depois de deletar |
34
+ | before_ | win | Antes de conquistar |
35
+ | after_ | win | Depois de conquistar |
36
+
37
+ ## Entidades Disponíveis
38
+
39
+ - `player`, `action`, `challenge`, `achievement`, `level`, `catalog_item`, `lottery`, `mystery_box`, `competition`, `question_log`, `<custom>__c`
40
+
41
+ ## API Endpoints
42
+
43
+ ### Listar Triggers
44
+ **Método:** GET
45
+ **Endpoint:** `/v3/trigger`
46
+
47
+ ### Criar Trigger
48
+ **Método:** POST
49
+ **Endpoint:** `/v3/trigger`
50
+
51
+ **Exemplo de Body:**
52
+ ```json
53
+ {
54
+ "name": "Make the player's name uppercase",
55
+ "_id": "DTv7uHc",
56
+ "description": "Before creating the player, change the letters of the name to uppercase",
57
+ "entity": "player",
58
+ "event": "before_create",
59
+ "script": "void trigger(event, entity, player, database){ entity.name = entity.name.toUpperCase(); }"
60
+ }
61
+ ```
62
+
63
+ ### Deletar Trigger
64
+ **Método:** DELETE
65
+ **Endpoint:** `/v3/trigger/:id`
66
+
67
+ ## Script Runtime Environment (Wrapper Class)
68
+
69
+ O script da trigger **não é standalone** — ele é inserido dentro de uma classe Java wrapper gerada pelo Funifier, idêntica à do Public Endpoint (ver `public.md` para a lista completa de imports).
70
+
71
+ ### Regras
72
+
73
+ 1. **NÃO use `import`** — todos os imports já estão no wrapper (Unirest, Groovy JSON, Funifier entities/utils, Apache HTTP, Simple Java Mail, etc.)
74
+ 2. Se precisar de uma classe não importada, use o nome completo: `com.example.MinhaClasse`
75
+ 3. **`manager`** (ManagerFactory) está disponível como campo da classe
76
+ 4. **Timeout padrão de 10 segundos** — pode ser customizado via campo `timeout` (em **segundos**) na API: `POST /v3/trigger` com `{"_id": "trigger_id", "timeout": 30}`. Este campo não aparece no Studio.
77
+ 5. Scripts rodam em **Groovy** — cuidado com `$` em GStrings (usar `String.valueOf((char)0x24)` para operadores MongoDB)
78
+ 6. Use apenas **ASCII em comentários** — UTF-8 especial pode causar parse errors
79
+
80
+ > 📖 Ver `public.md` → **Script Runtime Environment** para a lista completa de imports e bibliotecas disponíveis.
81
+
82
+ ## Parâmetros do Script
83
+
84
+ - `event` (String): evento acionado
85
+ - `entity` (Object): objeto sendo manipulado (Player, ActionLog, Achievement, etc.)
86
+ - `player` (String): ID do jogador
87
+ - `database` (Object): utilitário para acessar o banco de dados
88
+
89
+ ### ⚠️ CRITICAL: `entity` Type Depends on the Trigger Entity
90
+
91
+ O tipo do parâmetro `entity` varia conforme a entidade da trigger:
92
+
93
+ | Trigger Entity | Tipo de `entity` | Como acessar campos |
94
+ |---|---|---|
95
+ | `player` | `com.funifier.engine.player.Player` (objeto Java) | `entity.id`, `entity.name`, `entity.email`, `entity.extra` |
96
+ | `<custom>__c` | `java.util.Map` (documento MongoDB) | `entity.get("campo")`, `entity.put("campo", valor)` |
97
+ | `action` | `com.funifier.engine.action.ActionLog` | `entity.userId`, `entity.actionId`, `entity.attributes` |
98
+ | `achievement` | `com.funifier.engine.achievement.Achievement` | `entity.achievementId`, `entity.userId` |
99
+
100
+ **Erros comuns:**
101
+ - ❌ `entity.get("_id")` em trigger de `player` → `MissingMethodException: No signature of method: Player.get()`
102
+ - ✅ `entity.id` em trigger de `player`
103
+ - ❌ `entity.id` em trigger de `signup__c` → campo não existe no Map
104
+ - ✅ `entity.get("_id")` em trigger de `signup__c`
105
+
106
+ **Player fields (via `PlayerManager.java`):**
107
+ ```
108
+ entity.id → String (_id do player)
109
+ entity.name → String
110
+ entity.email → String
111
+ entity.password → String (hash BCrypt)
112
+ entity.extra → Map<String, Object> (campos customizados)
113
+ entity.image → Image object
114
+ entity.business → boolean
115
+ entity.developer → boolean
116
+ ```
117
+
118
+ **Fonte:** `PlayerManager.delete()` chama `TriggerRunner.run()` com `new Object[] { event, playerObject, playerId, gameDao }` — logo `entity` é o objeto `Player` completo, não um Map.
119
+
120
+ ## Verificando Logs de Trigger (Studio)
121
+
122
+ Para ver se uma trigger executou com sucesso ou com erro:
123
+
124
+ 1. Acessar **Studio** → menu lateral → **Triggers**
125
+ 2. Na lista de triggers, cada uma tem um botão **🔥 Logs** na coluna OPERAÇÕES
126
+ 3. Clicar em **Logs** abre um modal com:
127
+ - **Log Id**: identificador da trigger
128
+ - **Executou em**: data/hora da última execução
129
+ - **Tempo de resposta**: tempo de execução em ms
130
+ - **Erros**: se houve erro, mostra a exception completa em vermelho
131
+ 4. Se não houver seção "Erros", a trigger executou com sucesso
132
+
133
+ **Dica:** Após alterar uma trigger via API (`POST /v3/trigger`), teste-a e verifique o log no Studio para confirmar que não há erros de compilação ou runtime.
134
+
135
+ ## Utilitários Disponíveis no Contexto
136
+
137
+ | Classe/Método | Descrição |
138
+ |---|---|
139
+ | `Guid.newShortGuid()` | Gera um ID curto único (7 chars, ex: `FnwjKEY`) |
140
+ | `Guid.newGuid()` | Gera um GUID completo |
141
+ | `newShortGuid()` | ❌ **NÃO FUNCIONA** — precisa do prefixo `Guid.` |
142
+ | `com.funifier.engine.util.BCrypt.hashpw(pwd, BCrypt.gensalt())` | Hash de senha BCrypt |
143
+ | `new Date().getTime()` | Timestamp atual em milissegundos |
144
+ | `manager` | ManagerFactory — acesso a todos os managers |
145
+
146
+ > ⚠️ `System.currentTimeMillis()` é BLOQUEADO pelo SecureASTCustomizer. Usar `new Date().getTime()`.
147
+
148
+ ## Managers Disponíveis
149
+
150
+ - `manager.getPlayerManager()` - findById, insert, delete
151
+ - `manager.getActionManager()` - findActionById, track, trackSynchronous
152
+ - `manager.getCatalogManager()` - findItemById, purchase, undoPurchase
153
+ - `manager.getLotteryManager()` - find, insertTicket, execute
154
+ - `manager.getAchievementManager()` - addAchievement
155
+ - `manager.getJongoConnection()` - acesso direto ao MongoDB
156
+
157
+ ## Envio de Email
158
+
159
+ As triggers podem enviar emails usando o servidor SMTP configurado na gamificação. As classes do Simple Java Mail e utilitários Funifier já estão disponíveis no contexto (não precisa importar).
160
+
161
+ ### Classes disponíveis
162
+ - `EmailBuilder` / `MailerBuilder` — Simple Java Mail (construir e enviar)
163
+ - `com.funifier.engine.mail.MailContext` — config SMTP da gamificação
164
+ - `com.funifier.controller.Configuration` — acesso à configuração atual
165
+ - `com.funifier.engine.util.MustacheUtils` — parse de templates com variáveis `{{campo}}`
166
+
167
+ ### Exemplo básico
168
+ ```java
169
+ Email email = EmailBuilder.startingBlank()
170
+ .from("App", "noreply@funifier.com")
171
+ .to(nome, emailDestinatario)
172
+ .withSubject("Assunto")
173
+ .withHTMLText("<h1>Olá</h1>")
174
+ .buildEmail();
175
+
176
+ com.funifier.engine.mail.MailContext ctx = com.funifier.controller.Configuration.getCurrentConfiguration().getMailContext();
177
+ MailerBuilder.withSMTPServer(ctx.hostName, ctx.smtpPort, ctx.authUser, ctx.authPassword)
178
+ .buildMailer()
179
+ .sendMail(email);
180
+ ```
181
+
182
+ > 📖 Para o pattern completo com templates editáveis e Mustache, ver `patterns.md` → **Email Template Pattern**
183
+
184
+ ## Validações e Testes
185
+
186
+ - [ ] Trigger aparece na lista GET /v3/trigger
187
+ - [ ] Evento é disparado corretamente
188
+ - [ ] Script executa sem erros
189
+ - [ ] Testar em staging antes de produção