funifier-mcp 0.3.20 → 0.3.22
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.
- package/.cursor/rules/funifier.mdc +1 -0
- package/.github/copilot-instructions.md +1 -0
- package/AGENTS.md +1 -0
- package/CHANGELOG.md +31 -0
- package/datasource-funifier-docs/.coverage.json +22 -6
- package/datasource-funifier-docs/.validation.json +87 -11
- package/datasource-funifier-docs/knowledge/guides/database-access.md +3 -0
- package/datasource-funifier-docs/knowledge/guides/explain-diagnostics.md +170 -0
- package/datasource-funifier-docs/knowledge/guides/server-utils.md +718 -0
- package/datasource-funifier-docs/knowledge/index.md +4 -0
- package/datasource-funifier-docs/knowledge/modules/custom-object.md +12 -7
- package/datasource-funifier-docs/knowledge/modules/database.md +48 -5
- package/dist/mcp/bundle.js +131 -108
- package/dist/mcp/tools/database.d.ts.map +1 -1
- package/dist/mcp/tools/database.js +14 -2
- package/dist/mcp/tools/database.js.map +1 -1
- package/dist/mcp/tools/database.test.js +16 -0
- package/dist/mcp/tools/database.test.js.map +1 -1
- package/dist/mcp/tools/db-explain.d.ts +4 -0
- package/dist/mcp/tools/db-explain.d.ts.map +1 -0
- package/dist/mcp/tools/db-explain.js +187 -0
- package/dist/mcp/tools/db-explain.js.map +1 -0
- package/dist/mcp/tools/db-explain.test.d.ts +2 -0
- package/dist/mcp/tools/db-explain.test.d.ts.map +1 -0
- package/dist/mcp/tools/db-explain.test.js +142 -0
- package/dist/mcp/tools/db-explain.test.js.map +1 -0
- package/dist/mcp/tools/index.d.ts.map +1 -1
- package/dist/mcp/tools/index.js +2 -0
- package/dist/mcp/tools/index.js.map +1 -1
- package/dist/mcp/tools/list-tools.d.ts.map +1 -1
- package/dist/mcp/tools/list-tools.js +8 -0
- package/dist/mcp/tools/list-tools.js.map +1 -1
- package/package.json +1 -1
- package/skills/funifier/SKILL.md +1 -0
- package/skills/funifier/references/create-aggregate.md +10 -5
- package/skills/funifier/references/create-audit.md +0 -8
- package/skills/funifier/references/create-custom-object.md +0 -6
- package/skills/funifier/references/date-handling.md +0 -6
- package/skills/funifier/references/debug.md +2 -1
- package/skills/funifier/references/help.md +0 -6
- package/skills/funifier/references/manage-indexes.md +0 -6
- package/skills/funifier/references/query-aggregate.md +2 -6
- package/skills/funifier/references/server-utils.md +94 -0
- package/datasource-funifier-docs/.search-index.json +0 -59689
- package/datasource-funifier-docs/.skills-map.json +0 -150
|
@@ -0,0 +1,718 @@
|
|
|
1
|
+
# Server-side Utils — Referência
|
|
2
|
+
|
|
3
|
+
## 1. Visão Geral
|
|
4
|
+
|
|
5
|
+
### 1.1 O que é este documento
|
|
6
|
+
|
|
7
|
+
Este documento descreve as classes utilitárias do pacote `com.funifier.engine.util` do `funifier-service` disponíveis em código server-side — triggers, schedulers e public endpoints. São classes **puramente estáticas**: todos os métodos são chamados pelo nome totalmente qualificado (ou nome curto, quando pré-importado pelo runtime) sem instanciação.
|
|
8
|
+
|
|
9
|
+
### 1.2 Como referenciar no código
|
|
10
|
+
|
|
11
|
+
Em triggers e schedulers, as classes do pacote `com.funifier.engine.util` são pré-importadas pelo runner. Use o **nome curto** diretamente:
|
|
12
|
+
|
|
13
|
+
```groovy
|
|
14
|
+
void trigger(event, entity, player, database) {
|
|
15
|
+
String json = JsonUtil.toJson(entity) // OK — nome curto
|
|
16
|
+
boolean ok = CpfUtil.isValid(entity.cpf) // OK — nome curto
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Se por algum motivo um nome curto não funcionar (Public Endpoint tem sandbox mais restrito), use o FQN:
|
|
21
|
+
|
|
22
|
+
```groovy
|
|
23
|
+
String json = com.funifier.engine.util.JsonUtil.toJson(entity)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
> ⚠️ No **Public Endpoint**, o sandbox bloqueia `BCrypt` e `HttpUtil` com nome qualificado `com.*`. Use somente `JsonUtil` e `StringUtil` por nome curto nesse contexto. Para os demais, prefira Trigger ou Scheduler. Consulte `guides/java-libraries.md` §1.5 para a tabela completa do sandbox.
|
|
27
|
+
|
|
28
|
+
### 1.3 Índice de decisão
|
|
29
|
+
|
|
30
|
+
| Necessidade | Classe | Seção |
|
|
31
|
+
|---|---|---|
|
|
32
|
+
| Serializar/parsear JSON | `JsonUtil` | §2 |
|
|
33
|
+
| Verificar string nula/vazia/em branco | `StringUtil` | §3 |
|
|
34
|
+
| Validar CPF (formato String ou número) | `CpfUtil` | §4 |
|
|
35
|
+
| Formatar número como moeda | `FormatterUtil` | §5 |
|
|
36
|
+
| Parsear inteiros/doubles com segurança | `ParserUtil` | §6 |
|
|
37
|
+
| Avaliar expressão inline `{{= ... }}` | `ExpressionUtils` | §7 |
|
|
38
|
+
| Renderizar template Mustache `{{var}}` | `MustacheUtils` | §8 |
|
|
39
|
+
| Comparar objetos e gerar changelog | `DiffUtil` | §9 |
|
|
40
|
+
| Criptografar campo com chave simétrica (AES) | `AesCrypt` | §10 |
|
|
41
|
+
| Hash/verificar senha (Blowfish) | `BCrypt` | §11 |
|
|
42
|
+
| Criptografar bloco de dados com PGP/RSA | `PgpCrypt` | §12 |
|
|
43
|
+
| Gerar QR code para TOTP / 2FA | `OtpAuthUtil` | §13 |
|
|
44
|
+
| Fazer requisição HTTP externa (GET/POST) | `HttpUtil` | §14 |
|
|
45
|
+
| Ler URL como string / limpar parâmetros Funifier | `UrlUtil` | §15 |
|
|
46
|
+
| Gerar arquivo Excel (XLSX) a partir de lista | `ExcelUtil` | §16 |
|
|
47
|
+
| Paginar resultado de aggregate Jongo | `PaginationUtil` | §17 |
|
|
48
|
+
| Converter InputStream em arquivo temporário | `FileUtil` | §18 |
|
|
49
|
+
| Datas e cálculo de períodos | `DateUtil` | §19 |
|
|
50
|
+
| Internos do motor (não usar diretamente) | — | §20 |
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## 2. JsonUtil
|
|
55
|
+
|
|
56
|
+
**FQN:** `com.funifier.engine.util.JsonUtil`
|
|
57
|
+
|
|
58
|
+
Serialização e desserialização JSON baseada em Jackson. Pré-importada pelo runner — disponível em todos os runtimes incluindo Public Endpoint.
|
|
59
|
+
|
|
60
|
+
> `guides/java-libraries.md` §2 cobre os métodos básicos com mais exemplos contextuais (triggers, Public Endpoint). Este documento consolida a API completa.
|
|
61
|
+
|
|
62
|
+
### Métodos públicos
|
|
63
|
+
|
|
64
|
+
| Método | Retorno | Descrição |
|
|
65
|
+
|--------|---------|-----------|
|
|
66
|
+
| `toJson(Object obj)` | `String` | Objeto → JSON indentado; campos null incluídos |
|
|
67
|
+
| `toJsonRemoveNullFields(Object obj)` | `String` | Objeto → JSON sem campos null |
|
|
68
|
+
| `toBsonStrictMode(Object obj)` | `String` | Objeto → BSON strict mode (null map values incluídos) |
|
|
69
|
+
| `toBsonStrictModeList(List<Object> list)` | `String` | Lista → BSON strict mode |
|
|
70
|
+
| `fromJson(String json, Class<T> valueType)` | `T` | JSON → objeto tipado |
|
|
71
|
+
| `fromJson(String json, Class<T> valueType, boolean showError)` | `T` | JSON → objeto tipado; controla log de erros |
|
|
72
|
+
| `fromJson(String json)` | `DBObject` | JSON → `DBObject` MongoDB |
|
|
73
|
+
| `fromJsonToMap(String json)` | `Map<String, Object>` | JSON → Map |
|
|
74
|
+
| `fromFunifierBson(String json)` | `Object` | Parseia BSON Funifier (com suporte a `$date`, `$oid`) |
|
|
75
|
+
| `fromFunifierBsonWithParams(String json, HashMap<String, Object> params)` | `Object` | Parseia BSON Funifier substituindo `$param` |
|
|
76
|
+
|
|
77
|
+
### Exemplos
|
|
78
|
+
|
|
79
|
+
```groovy
|
|
80
|
+
// Serializar entity para string
|
|
81
|
+
String json = JsonUtil.toJson(entity)
|
|
82
|
+
|
|
83
|
+
// Parsear JSON recebido
|
|
84
|
+
Map<String, Object> data = JsonUtil.fromJsonToMap('{"name":"João","age":30}')
|
|
85
|
+
|
|
86
|
+
// Converter para tipo específico
|
|
87
|
+
Player p = JsonUtil.fromJson(jsonStr, Player.class)
|
|
88
|
+
|
|
89
|
+
// Sem campos null (útil para salvar no banco)
|
|
90
|
+
String compact = JsonUtil.toJsonRemoveNullFields(entity)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## 3. StringUtil
|
|
96
|
+
|
|
97
|
+
**FQN:** `com.funifier.engine.util.StringUtil`
|
|
98
|
+
|
|
99
|
+
Verificações simples de string nula/vazia/em branco. Útil como guarda antes de processar campos textuais.
|
|
100
|
+
|
|
101
|
+
### Métodos públicos
|
|
102
|
+
|
|
103
|
+
| Método | Retorno | Descrição |
|
|
104
|
+
|--------|---------|-----------|
|
|
105
|
+
| `isEmpty(String s)` | `boolean` | `true` se `null` ou `length < 1` |
|
|
106
|
+
| `isBlank(String s)` | `boolean` | `true` se `null`, vazio ou apenas espaços |
|
|
107
|
+
|
|
108
|
+
### Exemplos
|
|
109
|
+
|
|
110
|
+
```groovy
|
|
111
|
+
void trigger(event, entity, player, database) {
|
|
112
|
+
if (StringUtil.isBlank(entity.email)) {
|
|
113
|
+
throw new RuntimeException("E-mail obrigatório")
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## 4. CpfUtil
|
|
121
|
+
|
|
122
|
+
**FQN:** `com.funifier.engine.util.CpfUtil`
|
|
123
|
+
|
|
124
|
+
Validação e conversão de CPF brasileiro. Aceita string formatada (`"123.456.789-09"`), string pura (`"12345678909"`) ou número (`Long`).
|
|
125
|
+
|
|
126
|
+
> ⚠️ **CNPJ:** o método `isValidCNPJ` está comentado na fonte atual — **não disponível**. Use validação própria para CNPJ.
|
|
127
|
+
|
|
128
|
+
### Métodos públicos
|
|
129
|
+
|
|
130
|
+
| Método | Retorno | Descrição |
|
|
131
|
+
|--------|---------|-----------|
|
|
132
|
+
| `isValid(Object cpf)` | `boolean` | Valida CPF (`String` ou `Number`); `false` se null |
|
|
133
|
+
| `toLong(Object cpf)` | `long` | Converte CPF para `long` (remove `.` e `-`); `0L` se null |
|
|
134
|
+
|
|
135
|
+
### Exemplos
|
|
136
|
+
|
|
137
|
+
```groovy
|
|
138
|
+
void trigger(event, entity, player, database) {
|
|
139
|
+
def cpf = entity.cpf
|
|
140
|
+
if (!CpfUtil.isValid(cpf)) {
|
|
141
|
+
throw new RuntimeException("CPF inválido: " + cpf)
|
|
142
|
+
}
|
|
143
|
+
long cpfNumerico = CpfUtil.toLong(cpf) // 12345678909L
|
|
144
|
+
entity.cpfLong = cpfNumerico
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
```groovy
|
|
149
|
+
// Funciona com string formatada
|
|
150
|
+
CpfUtil.isValid("695.494.861-68") // true
|
|
151
|
+
CpfUtil.toLong("695.494.861-68") // 69549486168L
|
|
152
|
+
|
|
153
|
+
// Funciona com long
|
|
154
|
+
CpfUtil.isValid(69549486168L) // true
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## 5. FormatterUtil
|
|
160
|
+
|
|
161
|
+
**FQN:** `com.funifier.engine.util.FormatterUtil`
|
|
162
|
+
|
|
163
|
+
Formatação de número como moeda com suporte a locale e padrão de formato.
|
|
164
|
+
|
|
165
|
+
### Métodos públicos
|
|
166
|
+
|
|
167
|
+
| Método | Retorno | Descrição |
|
|
168
|
+
|--------|---------|-----------|
|
|
169
|
+
| `numberCurrency(Object input, String currency, String locale, String format)` | `String` | Formata `input` como moeda |
|
|
170
|
+
|
|
171
|
+
- **`currency`**: código ISO 4217 — ex. `"BRL"`, `"USD"`, `"EUR"`
|
|
172
|
+
- **`locale`**: código de país — ex. `"BR"`, `"US"`, `"DE"`
|
|
173
|
+
- **`format`**: padrão `DecimalFormat` — ex. `"#,##0.00"` (ou `""` para usar o padrão da moeda/locale)
|
|
174
|
+
|
|
175
|
+
### Exemplos
|
|
176
|
+
|
|
177
|
+
```groovy
|
|
178
|
+
// R$ 1.234,56
|
|
179
|
+
String valor = FormatterUtil.numberCurrency(1234.56, "BRL", "BR", "#,##0.00")
|
|
180
|
+
|
|
181
|
+
// $1,234.56
|
|
182
|
+
String usd = FormatterUtil.numberCurrency(1234.56, "USD", "US", "#,##0.00")
|
|
183
|
+
|
|
184
|
+
// Usando padrão padrão da moeda
|
|
185
|
+
String padrao = FormatterUtil.numberCurrency(entity.preco, "BRL", "BR", "")
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## 6. ParserUtil
|
|
191
|
+
|
|
192
|
+
**FQN:** `com.funifier.engine.util.ParserUtil`
|
|
193
|
+
|
|
194
|
+
Conversão e arredondamento de números com proteção contra exceções.
|
|
195
|
+
|
|
196
|
+
### Métodos públicos
|
|
197
|
+
|
|
198
|
+
| Método | Retorno | Descrição |
|
|
199
|
+
|--------|---------|-----------|
|
|
200
|
+
| `parseInt(String i)` | `int` | Converte string para int; retorna `0` se inválido |
|
|
201
|
+
| `formatDouble(double precoDouble, String format)` | `Double` | Formata double com padrão `DecimalFormat`; retorna `null` se erro |
|
|
202
|
+
| `setDoubleDecimalScale(double value, int scale)` | `double` | Arredonda para N casas decimais (HALF_UP); retorna original se erro |
|
|
203
|
+
|
|
204
|
+
### Exemplos
|
|
205
|
+
|
|
206
|
+
```groovy
|
|
207
|
+
int qty = ParserUtil.parseInt(entity.quantity) // "3" → 3; "abc" → 0
|
|
208
|
+
|
|
209
|
+
double preco = ParserUtil.setDoubleDecimalScale(10.56789, 2) // → 10.57
|
|
210
|
+
|
|
211
|
+
Double formatted = ParserUtil.formatDouble(1234.5678, "#,##0.00") // → 1234.57
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## 7. ExpressionUtils
|
|
217
|
+
|
|
218
|
+
**FQN:** `com.funifier.engine.util.ExpressionUtils`
|
|
219
|
+
|
|
220
|
+
Avalia blocos de expressão `{{= expr }}` em templates, com sandbox Groovy. Os blocos `{{var}}` comuns (Mustache) são deixados intactos. Útil para mensagens dinâmicas com cálculos.
|
|
221
|
+
|
|
222
|
+
### Métodos públicos
|
|
223
|
+
|
|
224
|
+
| Método | Retorno | Descrição |
|
|
225
|
+
|--------|---------|-----------|
|
|
226
|
+
| `evaluateInline(String template, Map<String, Object> params, List<String> exceptions)` | `String` | Substitui cada `{{= expr }}` pelo resultado; erros vão para `exceptions` |
|
|
227
|
+
|
|
228
|
+
**Funções disponíveis dentro das expressões:**
|
|
229
|
+
|
|
230
|
+
| Função | Comportamento |
|
|
231
|
+
|--------|--------------|
|
|
232
|
+
| `round(x)` | Arredonda para inteiro mais próximo |
|
|
233
|
+
| `round(x, places)` | Arredonda para N casas (HALF_UP) |
|
|
234
|
+
| `ceil(x)` | Teto (inteiro) |
|
|
235
|
+
| `floor(x)` | Piso (inteiro) |
|
|
236
|
+
| `abs(x)` | Valor absoluto |
|
|
237
|
+
| `add(a, b)` | Soma |
|
|
238
|
+
| `subtract(a, b)` | Subtração |
|
|
239
|
+
| `dateFormat(d, pattern)` | Formata Date com `SimpleDateFormat` |
|
|
240
|
+
|
|
241
|
+
> ⚠️ O sandbox não permite `import`, acesso a `System`, `File`, etc. Apenas aritmética, comparação e as funções acima.
|
|
242
|
+
|
|
243
|
+
### Exemplos
|
|
244
|
+
|
|
245
|
+
```groovy
|
|
246
|
+
Map params = [progress: [percent_completed: 75.6, time: [total: 10, spent: 6]]]
|
|
247
|
+
List errors = []
|
|
248
|
+
|
|
249
|
+
String msg = ExpressionUtils.evaluateInline(
|
|
250
|
+
"Você completou {{= round(progress.percent_completed) }}% — faltam {{= progress.time.total - progress.time.spent }} dias",
|
|
251
|
+
params,
|
|
252
|
+
errors
|
|
253
|
+
)
|
|
254
|
+
// → "Você completou 76% — faltam 4 dias"
|
|
255
|
+
|
|
256
|
+
if (!errors.isEmpty()) {
|
|
257
|
+
println("Erros: " + errors)
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## 8. MustacheUtils
|
|
264
|
+
|
|
265
|
+
**FQN:** `com.funifier.engine.util.MustacheUtils`
|
|
266
|
+
|
|
267
|
+
Renderização de templates Mustache (`{{variavel}}`). Para expressões matemáticas use `ExpressionUtils` (§7). Ambos podem ser combinados: `ExpressionUtils` processa `{{= ... }}` primeiro, depois `MustacheUtils` resolve `{{var}}`.
|
|
268
|
+
|
|
269
|
+
### Métodos públicos
|
|
270
|
+
|
|
271
|
+
| Método | Retorno | Descrição |
|
|
272
|
+
|--------|---------|-----------|
|
|
273
|
+
| `parse(String template, T values)` | `String` | Renderiza template Mustache com `values` (Map ou objeto) |
|
|
274
|
+
|
|
275
|
+
### Exemplos
|
|
276
|
+
|
|
277
|
+
```groovy
|
|
278
|
+
Map data = [name: "João", points: 150, badge: "Ouro"]
|
|
279
|
+
String html = MustacheUtils.parse("Olá {{name}}, você tem {{points}} pontos e conquistou o badge {{badge}}!", data)
|
|
280
|
+
// → "Olá João, você tem 150 pontos e conquistou o badge Ouro!"
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
```groovy
|
|
284
|
+
// Combinando com ExpressionUtils para mensagens ricas
|
|
285
|
+
String template = "Parabéns {{name}}! Você chegou a {{= round(progress) }}% da meta."
|
|
286
|
+
Map params = [name: "Maria", progress: 87.3]
|
|
287
|
+
List errors = []
|
|
288
|
+
String result = MustacheUtils.parse(ExpressionUtils.evaluateInline(template, params, errors), params)
|
|
289
|
+
// → "Parabéns Maria! Você chegou a 87% da meta."
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## 9. DiffUtil
|
|
295
|
+
|
|
296
|
+
**FQN:** `com.funifier.engine.util.DiffUtil`
|
|
297
|
+
|
|
298
|
+
Compara dois objetos (Maps, POJOs, listas) e retorna as diferenças em vários formatos. Útil para gerar changelogs de auditoria ou rastrear alterações em documentos customizados.
|
|
299
|
+
|
|
300
|
+
### Métodos públicos
|
|
301
|
+
|
|
302
|
+
| Método | Retorno | Descrição |
|
|
303
|
+
|--------|---------|-----------|
|
|
304
|
+
| `diff(Object old, Object new)` | `List<Difference>` | Diferenças com config padrão |
|
|
305
|
+
| `diff(Object old, Object new, Config config)` | `List<Difference>` | Diferenças com config customizada |
|
|
306
|
+
| `diffAsMap(Object old, Object new, Config config)` | `Map<String, Map<String, Object>>` | `{path: {old: ..., new: ...}}` |
|
|
307
|
+
| `diffAsJson(Object old, Object new, Config config)` | `String` | JSON compacto do map |
|
|
308
|
+
| `diffAsJsonPretty(Object old, Object new, Config config)` | `String` | JSON indentado do map |
|
|
309
|
+
| `diffAsList(Object old, Object new, Config config)` | `List<Map<String, Object>>` | `[{path:, old:, new:}]` |
|
|
310
|
+
| `diffAsListJson(Object old, Object new, Config config)` | `String` | JSON compacto da lista |
|
|
311
|
+
| `diffAsListJsonPretty(Object old, Object new, Config config)` | `String` | JSON indentado da lista |
|
|
312
|
+
| `buildChangelogFromSequence(List<?> data)` | `List<Map<String, Object>>` | Changelog de sequência de versões |
|
|
313
|
+
| `buildChangelogFromSequence(List<?> data, String sortBy)` | `List<Map<String, Object>>` | Com ordenação por campo |
|
|
314
|
+
| `buildChangelogFromSequence(List<?> data, Config config)` | `List<Map<String, Object>>` | Com config |
|
|
315
|
+
| `buildChangelogFromSequence(List<?> data, String sortBy, Config config)` | `List<Map<String, Object>>` | Com ordenação e config |
|
|
316
|
+
|
|
317
|
+
**`Config` — construtor fluente:**
|
|
318
|
+
|
|
319
|
+
```groovy
|
|
320
|
+
DiffUtil.Config config = DiffUtil.Config.defaultConfig()
|
|
321
|
+
.ignoreCase(true)
|
|
322
|
+
.ignoreWhitespace(true)
|
|
323
|
+
.ignoreNulls(true)
|
|
324
|
+
.ignoreOrder(false)
|
|
325
|
+
.maxDepth(10)
|
|
326
|
+
.ignoreFields(["updatedAt", "_id"] as Set)
|
|
327
|
+
.ignoreChangesInPaths(["metadata"] as Set)
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
**`Difference` — campos:**
|
|
331
|
+
- `getPath()` — caminho do campo alterado (ex. `"address.city"`, `"tags[0]"`)
|
|
332
|
+
- `getOldValue()` — valor anterior
|
|
333
|
+
- `getNewValue()` — valor novo
|
|
334
|
+
|
|
335
|
+
### Exemplos
|
|
336
|
+
|
|
337
|
+
```groovy
|
|
338
|
+
void trigger(event, entity, player, database) {
|
|
339
|
+
// Recuperar versão anterior do banco
|
|
340
|
+
def oldDoc = database.get(entity._id, "order__c")
|
|
341
|
+
|
|
342
|
+
// Gerar diff entre versão antiga e nova
|
|
343
|
+
DiffUtil.Config cfg = DiffUtil.Config.defaultConfig().ignoreFields(["_id", "updatedAt"] as Set)
|
|
344
|
+
String changes = DiffUtil.diffAsJson(oldDoc, entity, cfg)
|
|
345
|
+
|
|
346
|
+
// Guardar no log de auditoria
|
|
347
|
+
def auditEntry = [orderId: entity._id, changedAt: new Date(), changes: changes]
|
|
348
|
+
database.insert(auditEntry, "order_audit__c")
|
|
349
|
+
}
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
```groovy
|
|
353
|
+
// Changelog de uma sequência de versões
|
|
354
|
+
List versions = database.query("{}", "product_history__c")
|
|
355
|
+
List changelog = DiffUtil.buildChangelogFromSequence(versions, "version")
|
|
356
|
+
// Cada item: {campos do objeto + "changes": {path: {old:, new:}}}
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
---
|
|
360
|
+
|
|
361
|
+
## 10. AesCrypt
|
|
362
|
+
|
|
363
|
+
**FQN:** `com.funifier.engine.util.AesCrypt`
|
|
364
|
+
|
|
365
|
+
Criptografia simétrica AES/ECB/PKCS5Padding. Deriva uma chave de 16 bytes via SHA-1 da senha fornecida. Útil para proteger campos sensíveis em coleções customizadas.
|
|
366
|
+
|
|
367
|
+
> 🔐 **Gestão de segredos:** **nunca** hardcode a chave (`secret`) no script versionado. Guarde-a em uma coleção de configuração protegida ou injete via variável de ambiente/configuração de instância. AES/ECB não é autenticado — para alta segurança considere PGP (§12).
|
|
368
|
+
|
|
369
|
+
### Métodos públicos
|
|
370
|
+
|
|
371
|
+
| Método | Retorno | Descrição |
|
|
372
|
+
|--------|---------|-----------|
|
|
373
|
+
| `encrypt(String strToEncrypt, String secret)` | `String` | Criptografa string e retorna Base64; `null` se erro |
|
|
374
|
+
| `decrypt(String strToDecrypt, String secret)` | `String` | Descriptografa Base64 e retorna string; `null` se erro |
|
|
375
|
+
| `encryptFields(Object object, List<String> fields, String secret)` | `Object` | Criptografa campos específicos (dot-notation JSONPath) no objeto |
|
|
376
|
+
| `decryptFields(Object object, List<String> fields, String secret)` | `Object` | Descriptografa campos específicos no objeto |
|
|
377
|
+
|
|
378
|
+
### Exemplos
|
|
379
|
+
|
|
380
|
+
```groovy
|
|
381
|
+
// Criptografar um campo ao salvar
|
|
382
|
+
void trigger(event, entity, player, database) {
|
|
383
|
+
// Ler chave de configuração (NUNCA hardcode aqui)
|
|
384
|
+
def config = database.get("enc_config", "app_config__c")
|
|
385
|
+
String secret = config.aesKey
|
|
386
|
+
|
|
387
|
+
String encrypted = AesCrypt.encrypt(entity.taxId, secret)
|
|
388
|
+
entity.taxId = encrypted
|
|
389
|
+
// entity é salvo pelo motor após o trigger
|
|
390
|
+
}
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
```groovy
|
|
394
|
+
// Criptografar múltiplos campos de um Map
|
|
395
|
+
Map payload = [cpf: "123.456.789-09", rg: "12.345.678-9", name: "João"]
|
|
396
|
+
String secret = config.secret
|
|
397
|
+
Map encrypted = AesCrypt.encryptFields(payload, ["cpf", "rg"], secret)
|
|
398
|
+
// encrypted.cpf e encrypted.rg são Base64; encrypted.name permanece em claro
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
---
|
|
402
|
+
|
|
403
|
+
## 11. BCrypt
|
|
404
|
+
|
|
405
|
+
**FQN:** `com.funifier.engine.util.BCrypt`
|
|
406
|
+
|
|
407
|
+
Hash Blowfish de senhas (OpenBSD bcrypt). Padrão para senhas de players na plataforma Funifier.
|
|
408
|
+
|
|
409
|
+
> 🔐 **Gestão de segredos:** `BCrypt` é para hash de senha, não para criptografia reversível. Use `AesCrypt` se precisar recuperar o valor original.
|
|
410
|
+
>
|
|
411
|
+
> ⚠️ `BCrypt` está bloqueado no sandbox do Public Endpoint. Use somente em Trigger ou Scheduler.
|
|
412
|
+
|
|
413
|
+
### Métodos públicos
|
|
414
|
+
|
|
415
|
+
| Método | Retorno | Descrição |
|
|
416
|
+
|--------|---------|-----------|
|
|
417
|
+
| `hashpw(String password, String salt)` | `String` | Hash da senha com salt; retorna hash no formato `$2a$...` |
|
|
418
|
+
| `gensalt()` | `String` | Gera salt com 10 rounds (padrão) |
|
|
419
|
+
| `gensalt(int log_rounds)` | `String` | Gera salt com N rounds (`4`–`31`); cada `+1` dobra o tempo |
|
|
420
|
+
| `gensalt(int log_rounds, SecureRandom random)` | `String` | Controle total de rounds e fonte aleatória |
|
|
421
|
+
| `checkpw(String plaintext, String hashed)` | `boolean` | Verifica senha em claro contra hash |
|
|
422
|
+
|
|
423
|
+
### Exemplos
|
|
424
|
+
|
|
425
|
+
```groovy
|
|
426
|
+
// Criar jogador com senha hasheada (trigger after_create)
|
|
427
|
+
void trigger(event, entity, player, database) {
|
|
428
|
+
if (entity.password != null) {
|
|
429
|
+
entity.password = BCrypt.hashpw(entity.password, BCrypt.gensalt())
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
```groovy
|
|
435
|
+
// Verificar senha em login customizado
|
|
436
|
+
boolean valid = BCrypt.checkpw(senhaInformada, hashArmazenado)
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
> Veja também `guides/java-libraries.md` §7 para mais contexto sobre uso de BCrypt com autenticação de players.
|
|
440
|
+
|
|
441
|
+
---
|
|
442
|
+
|
|
443
|
+
## 12. PgpCrypt
|
|
444
|
+
|
|
445
|
+
**FQN:** `com.funifier.engine.util.PgpCrypt`
|
|
446
|
+
|
|
447
|
+
Criptografia assimétrica PGP/RSA (BouncyCastle). Útil para criptografar dados que precisam ser descriptografados por um terceiro (ex: arquivo CSV com dados sensíveis para integração externa).
|
|
448
|
+
|
|
449
|
+
> 🔐 **Gestão de chaves:** as chaves ASCII armored (privada e pública) são strings longas — **nunca** armazene a chave privada em script versionado. Guarde em coleção de configuração restrita ou em variável de ambiente da instância. A chave privada deve ser protegida por passphrase.
|
|
450
|
+
|
|
451
|
+
### Métodos públicos
|
|
452
|
+
|
|
453
|
+
| Método | Retorno | Descrição |
|
|
454
|
+
|--------|---------|-----------|
|
|
455
|
+
| `encrypt(String publicKey, byte[] data)` | `byte[]` | Criptografa bytes com chave pública ASCII armored |
|
|
456
|
+
| `decrypt(String secretKey, String password, byte[] pgpEncryptedData)` | `byte[]` | Descriptografa com chave secreta ASCII armored e passphrase |
|
|
457
|
+
| `generateKeyPair()` | `KeyPair` | Gera par RSA 1024-bit |
|
|
458
|
+
| `exportKeyPair(OutputStream secretOut, OutputStream publicOut, KeyPair pair, String identity, char[] passPhrase, boolean armor)` | `void` | Exporta par para streams (ASCII armored ou binário) |
|
|
459
|
+
| `getPublicKey(String keydata)` | `PGPPublicKey` | Obtém chave pública de string ASCII armored |
|
|
460
|
+
| `getSecretKey(String keydata)` | `PGPSecretKey` | Obtém chave secreta de string ASCII armored |
|
|
461
|
+
| `getPrivateKey(PGPSecretKey secKey, char[] pass)` | `PGPPrivateKey` | Extrai chave privada de `PGPSecretKey` com passphrase |
|
|
462
|
+
|
|
463
|
+
### Exemplos
|
|
464
|
+
|
|
465
|
+
```groovy
|
|
466
|
+
// Gerar e exportar par de chaves (executar uma vez, guardar as strings)
|
|
467
|
+
KeyPair kp = PgpCrypt.generateKeyPair()
|
|
468
|
+
ByteArrayOutputStream sec = new ByteArrayOutputStream()
|
|
469
|
+
ByteArrayOutputStream pub = new ByteArrayOutputStream()
|
|
470
|
+
PgpCrypt.exportKeyPair(sec, pub, kp, "admin@empresa.com", "minha-passphrase".toCharArray(), true)
|
|
471
|
+
String secretKey = sec.toString() // guardar de forma segura
|
|
472
|
+
String publicKey = pub.toString() // pode ser compartilhada
|
|
473
|
+
|
|
474
|
+
// Criptografar dados para envio a integração externa
|
|
475
|
+
byte[] dados = FileUtil.stream2file(inputStream, "relatorio", "csv").bytes
|
|
476
|
+
byte[] encriptado = PgpCrypt.encrypt(publicKey, dados)
|
|
477
|
+
|
|
478
|
+
// Descriptografar (quem tem a chave privada)
|
|
479
|
+
byte[] original = PgpCrypt.decrypt(secretKey, "minha-passphrase", encriptado)
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
---
|
|
483
|
+
|
|
484
|
+
## 13. OtpAuthUtil
|
|
485
|
+
|
|
486
|
+
**FQN:** `com.funifier.engine.util.OtpAuthUtil`
|
|
487
|
+
|
|
488
|
+
Utilitário para autenticação de dois fatores (TOTP / Google Authenticator). Na versão atual do `funifier-service`, o único método ativo é a geração de QR code.
|
|
489
|
+
|
|
490
|
+
> ⚠️ **Métodos TOTP comentados:** `generateSecretKey()`, `getTOTPCode()`, `validateTOTPCode()` e `getGoogleAuthenticatorBarCode()` estão **comentados na fonte atual** e não podem ser chamados. A geração e validação de TOTP deve ser implementada pelo script do desenvolvedor ou via biblioteca externa disponível no classpath.
|
|
491
|
+
|
|
492
|
+
### Métodos públicos
|
|
493
|
+
|
|
494
|
+
| Método | Retorno | Descrição |
|
|
495
|
+
|--------|---------|-----------|
|
|
496
|
+
| `createQRCode(String barCodeData, OutputStream out, int height, int width)` | `void` | Gera QR code PNG a partir de uma string (ex: URL `otpauth://totp/...`) e escreve no `out` |
|
|
497
|
+
|
|
498
|
+
### Exemplos
|
|
499
|
+
|
|
500
|
+
```groovy
|
|
501
|
+
// Gerar QR code de uma URL TOTP (a URL deve ser construída manualmente)
|
|
502
|
+
String account = "usuario@empresa.com"
|
|
503
|
+
String issuer = "MinhaApp"
|
|
504
|
+
String secretKey = "QDWSM3OYBPGTEVSPB5FKVDM3CSNCWHVK" // base32, 20 bytes
|
|
505
|
+
|
|
506
|
+
String barCodeUrl = "otpauth://totp/"
|
|
507
|
+
+ java.net.URLEncoder.encode(account, "UTF-8").replace("+", "%20")
|
|
508
|
+
+ "?secret=" + java.net.URLEncoder.encode(secretKey, "UTF-8").replace("+", "%20")
|
|
509
|
+
+ "&issuer=" + java.net.URLEncoder.encode(issuer, "UTF-8").replace("+", "%20")
|
|
510
|
+
|
|
511
|
+
ByteArrayOutputStream out = new ByteArrayOutputStream()
|
|
512
|
+
OtpAuthUtil.createQRCode(barCodeUrl, out, 300, 300)
|
|
513
|
+
byte[] qrPng = out.toByteArray() // salvar ou servir via Public Endpoint
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
---
|
|
517
|
+
|
|
518
|
+
## 14. HttpUtil
|
|
519
|
+
|
|
520
|
+
**FQN:** `com.funifier.engine.util.HttpUtil`
|
|
521
|
+
|
|
522
|
+
Requisições HTTP síncronas com Apache HttpClient (timeout 5s). Útil para chamar APIs externas a partir de triggers ou schedulers.
|
|
523
|
+
|
|
524
|
+
> ⚠️ Bloqueado no sandbox do Public Endpoint. Use somente em Trigger ou Scheduler. Para o Public Endpoint, prefira `java.net.URL` (§15) ou `Unirest` (ver `guides/java-libraries.md`).
|
|
525
|
+
|
|
526
|
+
### Métodos públicos
|
|
527
|
+
|
|
528
|
+
| Método | Retorno | Descrição |
|
|
529
|
+
|--------|---------|-----------|
|
|
530
|
+
| `getClientIP(HttpServletRequest request)` | `String` | IP real do cliente (respeita cabeçalhos de proxy: `X-Forwarded-For`, etc.) |
|
|
531
|
+
| `get(String strUrl, String parameters)` | `HttpResponse` | GET com query string; lança `Exception` se falhar |
|
|
532
|
+
| `post(String strUrl, Object obj)` | `HttpResponse` | POST com body JSON serializado; timeout 5s |
|
|
533
|
+
|
|
534
|
+
### Exemplos
|
|
535
|
+
|
|
536
|
+
```groovy
|
|
537
|
+
// Chamar API externa em trigger
|
|
538
|
+
void trigger(event, entity, player, database) {
|
|
539
|
+
try {
|
|
540
|
+
def response = HttpUtil.get("https://api.externa.com/v1/dados", "id=" + entity._id)
|
|
541
|
+
int status = response.getStatusLine().getStatusCode()
|
|
542
|
+
if (status == 200) {
|
|
543
|
+
String body = org.apache.http.util.EntityUtils.toString(response.getEntity())
|
|
544
|
+
Map data = JsonUtil.fromJsonToMap(body)
|
|
545
|
+
entity.dadosExternos = data
|
|
546
|
+
}
|
|
547
|
+
} catch (Exception e) {
|
|
548
|
+
println("Erro HTTP: " + e.getMessage())
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
```groovy
|
|
554
|
+
// POST para webhook externo
|
|
555
|
+
Map payload = [event: "player_registered", playerId: entity._id]
|
|
556
|
+
HttpUtil.post("https://webhook.empresa.com/funifier", payload)
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
---
|
|
560
|
+
|
|
561
|
+
## 15. UrlUtil
|
|
562
|
+
|
|
563
|
+
**FQN:** `com.funifier.engine.util.UrlUtil`
|
|
564
|
+
|
|
565
|
+
Leitura de URL e limpeza de parâmetros internos Funifier.
|
|
566
|
+
|
|
567
|
+
### Métodos públicos
|
|
568
|
+
|
|
569
|
+
| Método | Retorno | Descrição |
|
|
570
|
+
|--------|---------|-----------|
|
|
571
|
+
| `readFromUrl(String url)` | `String` | Lê conteúdo da URL como string UTF-8; `null` se erro |
|
|
572
|
+
| `removeFunifierParameteres(String url)` | `String` | Remove parâmetros `funifier_*` da query string; recursivo |
|
|
573
|
+
|
|
574
|
+
### Exemplos
|
|
575
|
+
|
|
576
|
+
```groovy
|
|
577
|
+
// Ler arquivo de texto de URL pública
|
|
578
|
+
String csv = UrlUtil.readFromUrl("https://storage.empresa.com/dados.csv")
|
|
579
|
+
if (csv != null) {
|
|
580
|
+
// processar csv
|
|
581
|
+
}
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
```groovy
|
|
585
|
+
// Limpar URL de redirecionamento externo
|
|
586
|
+
String url = "https://app.com/page?id=123&funifier_token=abc&other=x"
|
|
587
|
+
String clean = UrlUtil.removeFunifierParameteres(url)
|
|
588
|
+
// → "https://app.com/page?id=123&other=x"
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
---
|
|
592
|
+
|
|
593
|
+
## 16. ExcelUtil
|
|
594
|
+
|
|
595
|
+
**FQN:** `com.funifier.engine.util.ExcelUtil`
|
|
596
|
+
|
|
597
|
+
Geração de arquivo XLSX (Excel) a partir de uma lista de Maps. Os cabeçalhos são extraídos das chaves do primeiro Map; as colunas são auto-dimensionadas.
|
|
598
|
+
|
|
599
|
+
### Métodos públicos
|
|
600
|
+
|
|
601
|
+
| Método | Retorno | Descrição |
|
|
602
|
+
|--------|---------|-----------|
|
|
603
|
+
| `generateExcelFromObjects(List<Map<String, Object>> listRows, String sheetName)` | `byte[]` | Gera XLSX; retorna `null` se lista vazia ou erro |
|
|
604
|
+
|
|
605
|
+
### Exemplos
|
|
606
|
+
|
|
607
|
+
```groovy
|
|
608
|
+
// Gerar Excel de relatório a partir de aggregate
|
|
609
|
+
void execute() {
|
|
610
|
+
def rows = manager.getJongoConnection()
|
|
611
|
+
.getCollection("achievement")
|
|
612
|
+
.aggregate("{$match: {type: 0}}")
|
|
613
|
+
.and("{$group: {_id: '$player', total: {$sum: '$total'}}}")
|
|
614
|
+
.as(HashMap.class)
|
|
615
|
+
.toList()
|
|
616
|
+
|
|
617
|
+
List<Map<String, Object>> data = rows.collect { row ->
|
|
618
|
+
[player: row._id, pontos: row.total]
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
byte[] xlsx = ExcelUtil.generateExcelFromObjects(data, "Pontuação")
|
|
622
|
+
|
|
623
|
+
// Salvar o arquivo via FileUtil para servir ou enviar
|
|
624
|
+
// (ou usar FileUtil + UrlUtil se precisar enviar externamente)
|
|
625
|
+
}
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
---
|
|
629
|
+
|
|
630
|
+
## 17. PaginationUtil
|
|
631
|
+
|
|
632
|
+
**FQN:** `com.funifier.engine.util.PaginationUtil`
|
|
633
|
+
|
|
634
|
+
Paginação de results de aggregate Jongo. Usa `$facet` internamente para calcular total e página de uma só vez.
|
|
635
|
+
|
|
636
|
+
### Métodos públicos
|
|
637
|
+
|
|
638
|
+
| Método | Retorno | Descrição |
|
|
639
|
+
|--------|---------|-----------|
|
|
640
|
+
| `getPageResult(Aggregate a, String range, long _skip, long _limit)` | `Map<String, Object>` | Pagina aggregate; swallows erros → retorna lista vazia |
|
|
641
|
+
| `getPageResultThrowsException(Aggregate a, String range, long _skip, long _limit)` | `Map<String, Object>` | Pagina aggregate; lança exceção em erros de sintaxe |
|
|
642
|
+
| `getRange(String rangeHeader, long skip, long limit)` | `long[]` | Parseia header `Range: items=skip-limit` → `[skip, limit]` |
|
|
643
|
+
|
|
644
|
+
**Constantes:** `PaginationUtil.RESULT_KEY = "result"`, `COUNT_KEY = "count"`, `RANGE_KEY = "range"`
|
|
645
|
+
|
|
646
|
+
**Map retornado por `getPageResult`:**
|
|
647
|
+
- `"result"` → `List<Object>` com os documentos da página
|
|
648
|
+
- `"count"` → total de documentos (antes da paginação)
|
|
649
|
+
- `"range"` → string no formato `"items skip-limit/count"`
|
|
650
|
+
|
|
651
|
+
### Exemplos
|
|
652
|
+
|
|
653
|
+
```groovy
|
|
654
|
+
// Paginar aggregate de players em um Public Endpoint
|
|
655
|
+
def agg = manager.getJongoConnection()
|
|
656
|
+
.getCollection("player")
|
|
657
|
+
.aggregate("{$match: {active: true}}")
|
|
658
|
+
|
|
659
|
+
String rangeHeader = request.getHeader("Range") // "items=0-24"
|
|
660
|
+
Map page = PaginationUtil.getPageResult(agg, rangeHeader, 0L, 25L)
|
|
661
|
+
|
|
662
|
+
List players = page[PaginationUtil.RESULT_KEY]
|
|
663
|
+
Object total = page[PaginationUtil.COUNT_KEY]
|
|
664
|
+
```
|
|
665
|
+
|
|
666
|
+
---
|
|
667
|
+
|
|
668
|
+
## 18. FileUtil
|
|
669
|
+
|
|
670
|
+
**FQN:** `com.funifier.engine.util.FileUtil`
|
|
671
|
+
|
|
672
|
+
Conversão de `InputStream` em arquivo temporário. O arquivo é marcado como `deleteOnExit`.
|
|
673
|
+
|
|
674
|
+
### Métodos públicos
|
|
675
|
+
|
|
676
|
+
| Método | Retorno | Descrição |
|
|
677
|
+
|--------|---------|-----------|
|
|
678
|
+
| `stream2file(InputStream inStream, String fileName, String extension)` | `File` | Cria arquivo temp `fileName-<uuid>.<extension>` com conteúdo do stream |
|
|
679
|
+
|
|
680
|
+
### Exemplos
|
|
681
|
+
|
|
682
|
+
```groovy
|
|
683
|
+
// Processar CSV recebido como stream
|
|
684
|
+
File tempFile = FileUtil.stream2file(csvInputStream, "import", "csv")
|
|
685
|
+
String content = tempFile.text // Groovy sugar — lê todo o arquivo
|
|
686
|
+
|
|
687
|
+
// Converter para byte[] para PgpCrypt ou ExcelUtil
|
|
688
|
+
byte[] bytes = tempFile.bytes
|
|
689
|
+
```
|
|
690
|
+
|
|
691
|
+
---
|
|
692
|
+
|
|
693
|
+
## 19. DateUtil — Cross-link
|
|
694
|
+
|
|
695
|
+
`DateUtil` (`com.funifier.engine.util.DateUtil`) pertence ao tema de **datas e períodos Funifier**. A API completa — `parse`, `fromKeyword`, `fromKeyword(String)`, formatação, aritmética de datas — está documentada em:
|
|
696
|
+
|
|
697
|
+
- **Skill:** `funifier-date-handling` (via skill router)
|
|
698
|
+
- **Guia Java:** `guides/java-libraries.md` §4
|
|
699
|
+
|
|
700
|
+
**Não** duplique a API de `DateUtil` aqui. Para uso de datas em triggers, schedulers e aggregates, consulte esses documentos.
|
|
701
|
+
|
|
702
|
+
---
|
|
703
|
+
|
|
704
|
+
## 20. Internos do Motor — OUT
|
|
705
|
+
|
|
706
|
+
As classes abaixo são usadas pelo próprio motor Funifier e **não devem ser instanciadas ou chamadas diretamente** pelo código do desenvolvedor. São listadas aqui apenas para referência — caso você as encontre em stack traces ou no classpath.
|
|
707
|
+
|
|
708
|
+
| Classe | Papel no motor |
|
|
709
|
+
|--------|----------------|
|
|
710
|
+
| `FunifierMarshaller` | Conversão BSON ↔ objetos; usado pelo motor nas queries e aggregates |
|
|
711
|
+
| `FunifierBSONCallback` | Parser BSON personalizado para o `fromFunifierBson` do `JsonUtil` |
|
|
712
|
+
| `FunifierBsonWithParamsCallback` | Parser BSON com substituição de `$param` |
|
|
713
|
+
| `Entity` | Superclasse de entidades do motor (PlayerStatus, etc.) |
|
|
714
|
+
| `OptionModel` | Modelo de opção genérico para campos de seleção |
|
|
715
|
+
| `SearchUtil` | Utilitário de busca textual interno do motor |
|
|
716
|
+
| `MysqlUtil` | Acesso a MySQL em integrações legadas (não usar) |
|
|
717
|
+
| `HttpClientFunifier` | Cliente HTTP interno do motor |
|
|
718
|
+
| `X509Util` | Utilitário de certificado X.509 para infraestrutura TLS interna |
|