funifier-mcp 0.2.25 → 0.2.27

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 (211) hide show
  1. package/.cursor/rules/funifier.mdc +38 -41
  2. package/.github/copilot-instructions.md +38 -41
  3. package/AGENTS.md +56 -49
  4. package/README.md +40 -22
  5. package/datasource-funifier-docs/.coverage.json +326 -0
  6. package/datasource-funifier-docs/.validation.json +593 -0
  7. package/datasource-funifier-docs/knowledge/guides/aggregates.md +182 -70
  8. package/datasource-funifier-docs/knowledge/guides/database-access.md +174 -88
  9. package/datasource-funifier-docs/knowledge/guides/java-entities.md +294 -204
  10. package/datasource-funifier-docs/knowledge/guides/java-libraries.md +202 -226
  11. package/datasource-funifier-docs/knowledge/guides/java-managers.md +343 -265
  12. package/datasource-funifier-docs/knowledge/guides/trigger-examples.md +180 -236
  13. package/datasource-funifier-docs/knowledge/guides/triggers-guide.md +273 -191
  14. package/datasource-funifier-docs/knowledge/index.md +5 -2
  15. package/datasource-funifier-docs/knowledge/modules/achievement.md +1126 -28
  16. package/datasource-funifier-docs/knowledge/modules/action-log.md +469 -62
  17. package/datasource-funifier-docs/knowledge/modules/action.md +522 -70
  18. package/datasource-funifier-docs/knowledge/modules/auth.md +718 -69
  19. package/datasource-funifier-docs/knowledge/modules/avatar.md +483 -18
  20. package/datasource-funifier-docs/knowledge/modules/backup.md +603 -25
  21. package/datasource-funifier-docs/knowledge/modules/challenge.md +1048 -220
  22. package/datasource-funifier-docs/knowledge/modules/compact.md +469 -26
  23. package/datasource-funifier-docs/knowledge/modules/competition.md +811 -109
  24. package/datasource-funifier-docs/knowledge/modules/crossword.md +504 -28
  25. package/datasource-funifier-docs/knowledge/modules/csv-data.md +645 -20
  26. package/datasource-funifier-docs/knowledge/modules/custom-object.md +701 -36
  27. package/datasource-funifier-docs/knowledge/modules/database.md +730 -164
  28. package/datasource-funifier-docs/knowledge/modules/folder.md +1011 -77
  29. package/datasource-funifier-docs/knowledge/modules/kpi-formulas.md +410 -15
  30. package/datasource-funifier-docs/knowledge/modules/lastmile.md +568 -29
  31. package/datasource-funifier-docs/knowledge/modules/leaderboard.md +595 -126
  32. package/datasource-funifier-docs/knowledge/modules/level.md +536 -54
  33. package/datasource-funifier-docs/knowledge/modules/lottery.md +809 -76
  34. package/datasource-funifier-docs/knowledge/modules/marketplace.md +688 -17
  35. package/datasource-funifier-docs/knowledge/modules/mystery.md +662 -52
  36. package/datasource-funifier-docs/knowledge/modules/notification.md +564 -26
  37. package/datasource-funifier-docs/knowledge/modules/patterns.md +519 -814
  38. package/datasource-funifier-docs/knowledge/modules/player.md +773 -73
  39. package/datasource-funifier-docs/knowledge/modules/point.md +380 -83
  40. package/datasource-funifier-docs/knowledge/modules/public.md +508 -178
  41. package/datasource-funifier-docs/knowledge/modules/question.md +619 -99
  42. package/datasource-funifier-docs/knowledge/modules/quiz.md +565 -120
  43. package/datasource-funifier-docs/knowledge/modules/scheduler.md +1092 -39
  44. package/datasource-funifier-docs/knowledge/modules/security.md +674 -112
  45. package/datasource-funifier-docs/knowledge/modules/staging.md +742 -19
  46. package/datasource-funifier-docs/knowledge/modules/story.md +565 -29
  47. package/datasource-funifier-docs/knowledge/modules/studio-page.md +470 -144
  48. package/datasource-funifier-docs/knowledge/modules/swap.md +552 -84
  49. package/datasource-funifier-docs/knowledge/modules/team.md +563 -45
  50. package/datasource-funifier-docs/knowledge/modules/trigger.md +876 -134
  51. package/datasource-funifier-docs/knowledge/modules/upload.md +468 -95
  52. package/datasource-funifier-docs/knowledge/modules/virtual-good.md +510 -63
  53. package/datasource-funifier-docs/knowledge/modules/webhook.md +375 -28
  54. package/datasource-funifier-docs/knowledge/modules/websocket.md +459 -26
  55. package/datasource-funifier-docs/knowledge/modules/widget.md +613 -27
  56. package/dist/cli/init.d.ts.map +1 -1
  57. package/dist/cli/init.js +42 -1
  58. package/dist/cli/init.js.map +1 -1
  59. package/dist/cli/init.test.js +74 -3
  60. package/dist/cli/init.test.js.map +1 -1
  61. package/dist/cli/persona.d.ts +3 -0
  62. package/dist/cli/persona.d.ts.map +1 -0
  63. package/dist/cli/persona.js +25 -0
  64. package/dist/cli/persona.js.map +1 -0
  65. package/dist/core/api-client.d.ts +21 -1
  66. package/dist/core/api-client.d.ts.map +1 -1
  67. package/dist/core/api-client.js +154 -1
  68. package/dist/core/api-client.js.map +1 -1
  69. package/dist/core/constants.d.ts +14 -0
  70. package/dist/core/constants.d.ts.map +1 -1
  71. package/dist/core/constants.js +14 -0
  72. package/dist/core/constants.js.map +1 -1
  73. package/dist/core/types/Folder.d.ts +16 -0
  74. package/dist/core/types/Folder.d.ts.map +1 -0
  75. package/dist/core/types/Folder.js +3 -0
  76. package/dist/core/types/Folder.js.map +1 -0
  77. package/dist/core/types/FolderContent.d.ts +10 -0
  78. package/dist/core/types/FolderContent.d.ts.map +1 -0
  79. package/dist/core/types/FolderContent.js +3 -0
  80. package/dist/core/types/FolderContent.js.map +1 -0
  81. package/dist/core/types/FolderContentType.d.ts +10 -0
  82. package/dist/core/types/FolderContentType.d.ts.map +1 -0
  83. package/dist/core/types/FolderContentType.js +3 -0
  84. package/dist/core/types/FolderContentType.js.map +1 -0
  85. package/dist/core/types/FolderLog.d.ts +11 -0
  86. package/dist/core/types/FolderLog.d.ts.map +1 -0
  87. package/dist/core/types/FolderLog.js +3 -0
  88. package/dist/core/types/FolderLog.js.map +1 -0
  89. package/dist/core/types/index.d.ts +4 -0
  90. package/dist/core/types/index.d.ts.map +1 -1
  91. package/dist/core/types/index.js +4 -0
  92. package/dist/core/types/index.js.map +1 -1
  93. package/dist/mcp/bundle.js +121 -87
  94. package/dist/mcp/check-update.d.ts +2 -0
  95. package/dist/mcp/check-update.d.ts.map +1 -0
  96. package/dist/mcp/check-update.js +44 -0
  97. package/dist/mcp/check-update.js.map +1 -0
  98. package/dist/mcp/index.js +5 -2
  99. package/dist/mcp/index.js.map +1 -1
  100. package/dist/mcp/resources/documentation.d.ts +1 -1
  101. package/dist/mcp/resources/documentation.d.ts.map +1 -1
  102. package/dist/mcp/resources/documentation.js +39 -3
  103. package/dist/mcp/resources/documentation.js.map +1 -1
  104. package/dist/mcp/tools/_char-guard.js +1 -1
  105. package/dist/mcp/tools/_char-guard.js.map +1 -1
  106. package/dist/mcp/tools/_fetch-current.d.ts +1 -1
  107. package/dist/mcp/tools/_fetch-current.d.ts.map +1 -1
  108. package/dist/mcp/tools/_fetch-current.js +12 -0
  109. package/dist/mcp/tools/_fetch-current.js.map +1 -1
  110. package/dist/mcp/tools/connect.d.ts.map +1 -1
  111. package/dist/mcp/tools/connect.js +18 -8
  112. package/dist/mcp/tools/connect.js.map +1 -1
  113. package/dist/mcp/tools/database.d.ts.map +1 -1
  114. package/dist/mcp/tools/database.js +59 -47
  115. package/dist/mcp/tools/database.js.map +1 -1
  116. package/dist/mcp/tools/database.test.js +2 -2
  117. package/dist/mcp/tools/database.test.js.map +1 -1
  118. package/dist/mcp/tools/delete.d.ts.map +1 -1
  119. package/dist/mcp/tools/delete.js +33 -3
  120. package/dist/mcp/tools/delete.js.map +1 -1
  121. package/dist/mcp/tools/execute.d.ts.map +1 -1
  122. package/dist/mcp/tools/execute.js +20 -9
  123. package/dist/mcp/tools/execute.js.map +1 -1
  124. package/dist/mcp/tools/folder.d.ts +4 -0
  125. package/dist/mcp/tools/folder.d.ts.map +1 -0
  126. package/dist/mcp/tools/folder.js +68 -0
  127. package/dist/mcp/tools/folder.js.map +1 -0
  128. package/dist/mcp/tools/get.d.ts.map +1 -1
  129. package/dist/mcp/tools/get.js +16 -6
  130. package/dist/mcp/tools/get.js.map +1 -1
  131. package/dist/mcp/tools/index.d.ts +1 -1
  132. package/dist/mcp/tools/index.d.ts.map +1 -1
  133. package/dist/mcp/tools/index.js +5 -1
  134. package/dist/mcp/tools/index.js.map +1 -1
  135. package/dist/mcp/tools/list.d.ts.map +1 -1
  136. package/dist/mcp/tools/list.js +38 -14
  137. package/dist/mcp/tools/list.js.map +1 -1
  138. package/dist/mcp/tools/logs.d.ts.map +1 -1
  139. package/dist/mcp/tools/logs.js +15 -5
  140. package/dist/mcp/tools/logs.js.map +1 -1
  141. package/dist/mcp/tools/save.d.ts.map +1 -1
  142. package/dist/mcp/tools/save.js +26 -4
  143. package/dist/mcp/tools/save.js.map +1 -1
  144. package/dist/mcp/tools/save.test.js +192 -1
  145. package/dist/mcp/tools/save.test.js.map +1 -1
  146. package/dist/mcp/tools/search-docs.d.ts +3 -0
  147. package/dist/mcp/tools/search-docs.d.ts.map +1 -0
  148. package/dist/mcp/tools/search-docs.js +102 -0
  149. package/dist/mcp/tools/search-docs.js.map +1 -0
  150. package/package.json +6 -2
  151. package/skills/acquire-funifier-knowledge/SKILL.md +132 -0
  152. package/skills/acquire-funifier-knowledge/assets/templates/CONCERNS.md +25 -0
  153. package/skills/acquire-funifier-knowledge/assets/templates/CUSTOM_ENDPOINTS.md +24 -0
  154. package/skills/acquire-funifier-knowledge/assets/templates/CUSTOM_PAGES.md +24 -0
  155. package/skills/acquire-funifier-knowledge/assets/templates/GAME_MECHANICS.md +35 -0
  156. package/skills/acquire-funifier-knowledge/assets/templates/INTEGRATIONS.md +35 -0
  157. package/skills/acquire-funifier-knowledge/assets/templates/LEADERBOARDS.md +24 -0
  158. package/skills/acquire-funifier-knowledge/assets/templates/OVERVIEW.md +47 -0
  159. package/skills/acquire-funifier-knowledge/assets/templates/PLAYER_MODEL.md +31 -0
  160. package/skills/acquire-funifier-knowledge/assets/templates/SCHEDULERS.md +25 -0
  161. package/skills/acquire-funifier-knowledge/assets/templates/TECHNIQUES_AND_PATTERNS.md +26 -0
  162. package/skills/acquire-funifier-knowledge/assets/templates/TRIGGERS.md +27 -0
  163. package/skills/acquire-funifier-knowledge/references/funifier-inventory-checklist.md +81 -0
  164. package/skills/acquire-funifier-knowledge/references/game-techniques-taxonomy.md +62 -0
  165. package/skills/acquire-funifier-knowledge/references/mcp-call-patterns.md +118 -0
  166. package/skills/funifier/SKILL.md +88 -0
  167. package/skills/funifier/references/configure-security.md +96 -0
  168. package/skills/{funifier-create-action/SKILL.md → funifier/references/create-action.md} +0 -33
  169. package/skills/funifier/references/create-aggregate.md +144 -0
  170. package/skills/funifier/references/create-challenge.md +116 -0
  171. package/skills/funifier/references/create-competition.md +98 -0
  172. package/skills/funifier/references/create-crossword.md +574 -0
  173. package/skills/funifier/references/create-custom-object.md +91 -0
  174. package/skills/funifier/references/create-custom-page.md +135 -0
  175. package/skills/funifier/references/create-folder.md +104 -0
  176. package/skills/funifier/references/create-lastmile.md +643 -0
  177. package/skills/{funifier-create-leaderboard/SKILL.md → funifier/references/create-leaderboard.md} +0 -33
  178. package/skills/funifier/references/create-level.md +94 -0
  179. package/skills/funifier/references/create-lottery.md +913 -0
  180. package/skills/funifier/references/create-mystery.md +769 -0
  181. package/skills/funifier/references/create-notification.md +75 -0
  182. package/skills/{funifier-create-point/SKILL.md → funifier/references/create-point.md} +0 -33
  183. package/skills/funifier/references/create-quiz.md +98 -0
  184. package/skills/funifier/references/create-scheduler.md +141 -0
  185. package/skills/funifier/references/create-story.md +636 -0
  186. package/skills/funifier/references/create-swap.md +95 -0
  187. package/skills/{funifier-create-trigger/SKILL.md → funifier/references/create-trigger.md} +0 -33
  188. package/skills/funifier/references/create-virtual-good.md +96 -0
  189. package/skills/funifier/references/create-webhook.md +72 -0
  190. package/skills/funifier/references/create-websocket.md +71 -0
  191. package/skills/funifier/references/create-widget.md +76 -0
  192. package/skills/funifier/references/debug.md +87 -0
  193. package/skills/funifier/references/help.md +81 -0
  194. package/skills/funifier/references/implement-frontend.md +106 -0
  195. package/skills/funifier/references/import-csv.md +75 -0
  196. package/skills/funifier/references/manage-player.md +82 -0
  197. package/skills/funifier/references/manage-team.md +76 -0
  198. package/skills/funifier/references/upload-file.md +91 -0
  199. package/datasource-funifier-docs/.search-index.json +0 -17318
  200. package/datasource-funifier-docs/.skills-map.json +0 -73
  201. package/skills/funifier-create-aggregate/SKILL.md +0 -127
  202. package/skills/funifier-create-challenge/SKILL.md +0 -88
  203. package/skills/funifier-create-custom-page/SKILL.md +0 -127
  204. package/skills/funifier-create-level/SKILL.md +0 -87
  205. package/skills/funifier-create-quiz/SKILL.md +0 -87
  206. package/skills/funifier-create-scheduler/SKILL.md +0 -127
  207. package/skills/funifier-create-virtual-good/SKILL.md +0 -87
  208. package/skills/funifier-debug/SKILL.md +0 -92
  209. package/skills/funifier-help/SKILL.md +0 -86
  210. package/skills/funifier-implement-frontend/SKILL.md +0 -90
  211. package/skills/funifier-index/SKILL.md +0 -58
@@ -1,52 +1,227 @@
1
- # Triggers Funifier
1
+ # Triggers Funifier — Guia de Conceitos
2
2
 
3
- Triggers são códigos JAVA executados dentro do FUNIFIER ENGINE quando um evento específico acontece na gamificação. Oferecem flexibilidade para manipular informações em tempo real, permitindo mudar o comportamento padrão das técnicas de jogos e funcionalidades da plataforma.
3
+ ## 1. Visão Geral
4
4
 
5
- **Acesso Studio:** `/studio/trigger`
6
- **API Endpoint:** `/v3/trigger`
5
+ ### 1.1 O que é este documento
7
6
 
8
- ## Configuração de uma Trigger
7
+ Este documento descreve os conceitos de triggers Funifier — assinatura do script, variáveis disponíveis, eventos, entidades, regra de persistência e cadeia de conquistas — para escrever código Java/Groovy que executa no Funifier Engine quando um evento acontece. É o hub dos triggers; catálogos de managers/entidades/bibliotecas e exemplos de produção vivem em arquivos próprios.
9
8
 
10
- Uma trigger é composta de três informações essenciais:
11
- 1. **Evento** (`event`): quando a trigger deve ser executada
12
- 2. **Entidade** (`entity`): que tipo de objeto está vinculado ao evento
13
- 3. **Script** (`script`): código Java a ser executado
9
+ **Acesso Studio:** `/studio/trigger` · **API:** `/v3/trigger`
10
+
11
+ ### 1.2 Quando consultar
12
+
13
+ - Consulte ao **criar uma trigger** e precisar entender `event`, `entity`, `script`.
14
+ - Consulte ao precisar saber **quais variáveis** o script recebe (`event`, `entity`, `player`, `database`, `manager`, `context`).
15
+ - Consulte ao escolher o **evento certo** (incl. eventos de bulk/CSV).
16
+ - Consulte ao precisar **rejeitar uma criação** ou entender por que `throw` não cancela.
17
+ - Consulte ao precisar ler a **origem de uma conquista** (`context.extra`).
18
+
19
+ ### 1.3 Quando NÃO consultar
20
+
21
+ - **NÃO** consulte para os **métodos dos managers** — use `datasource-funifier-docs/knowledge/guides/java-managers.md`.
22
+ - **NÃO** consulte para **campos das entidades** — use `datasource-funifier-docs/knowledge/guides/java-entities.md`.
23
+ - **NÃO** consulte para **bibliotecas** (JsonUtil, Guid, Unirest, Email) — use `datasource-funifier-docs/knowledge/guides/java-libraries.md`.
24
+ - **NÃO** consulte para **exemplos de produção prontos** — use `datasource-funifier-docs/knowledge/guides/trigger-examples.md`.
25
+
26
+ ### 1.4 Índice de decisão
27
+
28
+ | Problema / Situação | O que fazer | Seção |
29
+ |---|---|---|
30
+ | Montar o documento da trigger | Configuração (event/entity/script) | §2 |
31
+ | Saber o que o script recebe | Assinatura e variáveis implícitas | §3 |
32
+ | Escolher o evento | Eventos oficiais e estendidos | §4 |
33
+ | Escolher a entidade | Entidades disponíveis | §5 |
34
+ | Saber o tipo do `entity` para cada combinação | Combinações Evento × Entidade | §6 |
35
+ | Saber qual ação/conquista originou o evento | `context.extra` (cadeia de conquistas) | §7 |
36
+ | Rejeitar uma criação inválida | Regra de persistência + BusinessException | §8 |
37
+ | Processar import/insert em lote | `entity` como List (bulk) | §9 |
38
+
39
+ ### 1.5 Restrições globais críticas
40
+
41
+ > ⚠️ **`throw` NÃO cancela a persistência.** O Funifier persiste o documento; lançar exceção não faz rollback (`trigger-examples.md`). Consequência: tentativas de "bloquear" criação com `throw` falham silenciosamente. → `before_create` serve só para **enriquecer** (normalizar, defaults, metadados); para **rejeitar**, use `after_create` + `database.delete(...)` (§8).
42
+
43
+ > ⚠️ **Em Groovy, acesse o ID com `entity.id`, não `entity._id`.** Consequência: `_id` retorna `null` (`patterns.md` §10). → Use `.id` em código; `_id` só no JSON/documento. Vale para `entity`, `player`, `ActionLog`, `Achievement`.
44
+
45
+ > ⚠️ **O evento depende do método HTTP que originou a operação.** `PUT` → `before_update`/`after_update`; `POST` → `before_create`/`after_create` (`patterns.md` §1.5, `modules/trigger.md` §3.1). Consequência: a trigger esperada não roda. → Escolha o método no frontend conforme o evento da trigger (ex: Signup usa `PUT` para acionar `before_update`).
46
+
47
+ > ⚠️ **Nunca dispare `track`/`trackSynchonous` para a mesma ação que acionou a trigger.** Consequência: loop infinito (`java-managers.md` §1.5). → Filtre por `entity.actionId` antes ou use outra ação.
48
+
49
+ > ⚠️ **Timeout default de trigger: 5s** (configurável via campo `timeout` no `POST /v3/trigger`; não aparece no Studio). O teto independente do `@TimedInterrupt` é 200s. Tabela completa em `patterns.md` §1.5.
50
+
51
+ ### 1.6 Documentos relacionados
52
+
53
+ > 📄 `datasource-funifier-docs/knowledge/guides/trigger-examples.md` — exemplos de produção (JSON + Groovy)
54
+ > 📄 `datasource-funifier-docs/knowledge/guides/java-managers.md` — métodos de `manager.get*Manager()`
55
+ > 📄 `datasource-funifier-docs/knowledge/guides/java-entities.md` — campos do `entity` por tipo
56
+ > 📄 `datasource-funifier-docs/knowledge/guides/java-libraries.md` — JsonUtil, Guid, DateUtil, Unirest, Email
57
+ > 📄 `datasource-funifier-docs/knowledge/guides/database-access.md` — `database.getCollection(...)`
58
+ > 📄 `datasource-funifier-docs/knowledge/modules/patterns.md` §1.5 — sandbox, timeouts, eventos por método HTTP
59
+
60
+ ---
61
+
62
+ ## 2. Configuração de uma Trigger
63
+
64
+ Quando usar: ao criar/atualizar o documento da trigger.
65
+ Não usar quando: já tem o documento e precisa só do código → §3.
66
+ Depende de: `Trigger` (entidade — `java-entities.md` §10).
67
+ Disponível em: Trigger.
68
+
69
+ ### Descrição
70
+
71
+ Uma trigger é um documento com três informações essenciais: **evento** (quando roda), **entidade** (que objeto está vinculado) e **script** (código a executar).
72
+
73
+ ### Uso
14
74
 
15
75
  ```json
16
76
  {
17
77
  "name": "Make the player's name uppercase",
18
78
  "_id": "DTv7uHc",
19
- "description": "Before creating the player, change the letters of the name to uppercase",
79
+ "description": "Antes de criar o player, deixa o nome em maiúsculas",
20
80
  "entity": "player",
21
81
  "event": "before_create",
22
82
  "script": "void trigger(event, entity, player, database){ entity.name = entity.name.toUpperCase(); }"
23
83
  }
24
84
  ```
25
85
 
26
- ## Eventos e Entidades
86
+ O campo `timeout` (segundos) só é configurável via API (`patterns.md` §1.5).
87
+
88
+ ### Armadilhas conhecidas
89
+
90
+ - **Atualizar a trigger via `POST` parcial** → o `script` pode ser apagado (full replace; `patterns.md` §1.5). Correção: reenviar o documento completo.
91
+
92
+ ---
27
93
 
28
- ### Eventos
94
+ ## 3. Assinatura do Script e Variáveis Implícitas
95
+
96
+ Quando usar: ao escrever o corpo do script.
97
+ Não usar quando: —
98
+ Depende de: `manager` (managers), `context` (cadeia de conquistas §7), `database` (Jongo).
99
+ Disponível em: Trigger.
100
+
101
+ ### Descrição
102
+
103
+ O script define a função `trigger` com quatro parâmetros. Além deles, o runtime expõe variáveis **implícitas** (não declaradas na assinatura): `manager`, `context` e `println`.
104
+
105
+ ### Uso
106
+
107
+ ```java
108
+ void trigger(event, entity, player, database) {
109
+ // PARÂMETROS:
110
+ // event — String do evento (ex: "before_create")
111
+ // entity — objeto manipulado (Player, ActionLog, Achievement, HashMap de __c…)
112
+ // player — String com o ID do jogador
113
+ // database — conexão Jongo (database.getCollection(...) — ver database-access.md)
114
+
115
+ // IMPLÍCITOS (não na assinatura):
116
+ // manager — ManagerFactory: manager.getPlayerManager()… (java-managers.md)
117
+ // context — contexto da execução; context.extra traz a origem (§7)
118
+ // println — log para o trigger_log
119
+ }
120
+ ```
121
+
122
+ Exemplo mínimo (enriquecimento):
123
+ ```groovy
124
+ void trigger(event, entity, player, database) {
125
+ entity.name = entity.name.toUpperCase(); // mutação persiste (before_create)
126
+ println("normalizado: " + entity.id); // .id, não ._id (§1.5)
127
+ }
128
+ ```
129
+
130
+ ### Armadilhas conhecidas
131
+
132
+ - **Esperar `manager`/`context` na assinatura** → são implícitos; use-os direto.
133
+ - **Usar `entity._id`** → `null` em Groovy. Correção: `entity.id` (§1.5).
134
+
135
+ ---
136
+
137
+ ## 4. Eventos
138
+
139
+ Quando usar: ao definir `event` na trigger.
140
+ Não usar quando: —
141
+ Depende de: método HTTP da operação (§1.5).
142
+ Disponível em: Trigger.
143
+
144
+ ### Descrição
145
+
146
+ Eventos definem **quando** a trigger roda. Os oficiais aparecem no dropdown do Studio; os estendidos só por texto livre.
147
+
148
+ ### Uso
149
+
150
+ **Oficiais (dropdown):**
29
151
 
30
152
  | Evento | Quando é acionado |
31
153
  |--------|-------------------|
32
- | `before_create` | Antes de criar no banco |
33
- | `after_create` | Depois de criar no banco |
34
- | `before_update` | Antes de atualizar |
35
- | `after_delete` | Depois de deletar |
36
- | `before_win` | Antes de conquistar |
37
- | `after_win` | Depois de conquistar |
154
+ | `before_win` / `after_win` | Antes/depois de registrar uma conquista |
155
+ | `before_lose` / `after_lose` | Antes/depois de remover uma conquista |
156
+ | `before_create` / `after_create` | Antes/depois de persistir um novo documento |
157
+ | `before_update` / `after_update` | Antes/depois de atualizar |
158
+ | `before_delete` / `after_delete` | Antes/depois de deletar |
159
+
160
+ **Estendidos (free-text — não aparecem no dropdown):**
161
+
162
+ | Evento | Quando é acionado |
163
+ |--------|-------------------|
164
+ | `before_bulk` / `after_bulk` | Antes/depois de insert/update em lote via API |
165
+ | `csv_before_bulk` / `csv_after_bulk` | Antes/depois de processar um import CSV |
166
+
167
+ > Nos eventos de bulk/CSV, `entity` é uma **List**, não um único documento (§9).
168
+
169
+ ### Armadilhas conhecidas
170
+
171
+ - **`before_create` esperando bloquear via `throw`** → não cancela (§1.5/§8).
172
+ - **`POST` esperando acionar `before_update`** → `POST` dispara `before_create` (§1.5).
173
+
174
+ ---
175
+
176
+ ## 5. Entidades
177
+
178
+ Quando usar: ao definir `entity` na trigger.
179
+ Não usar quando: —
180
+ Depende de: `java-entities.md` (tipos resultantes).
181
+ Disponível em: Trigger.
182
+
183
+ ### Descrição
184
+
185
+ A entidade vincula a trigger a um tipo de objeto. O Studio oferece um dropdown fixo + entidades dinâmicas; texto livre aceita qualquer nome.
186
+
187
+ ### Uso
188
+
189
+ **Dropdown hardcoded:** `action`, `catalog`, `catalog_item`, `crown`, `leaderboard`, `level`, `player`, `team`, `challenge`, `point_category`, `character_star_stats_level`, `upload`, `mystery_box`, `lottery`
38
190
 
39
- ### Combinações Comuns
191
+ **Dinâmicas** (via `/v3/database/collections`): `achievement` e todas as coleções `__c` do projeto.
40
192
 
41
- | Evento | Entidade | Quando é acionado | Tipo do entity |
42
- |--------|----------|-------------------|----------------|
193
+ **Excluídas** (não aparecem; acesse por código): `action_log`, `challenge_progress`, `player_status`, `security`, `technique_field`, `join_log`.
194
+
195
+ **Free-text:** o formulário aceita qualquer nome de entidade/evento não listado.
196
+
197
+ ### Armadilhas conhecidas
198
+
199
+ - **Procurar `action_log` no dropdown** → não aparece (é excluída). Para reagir a logs, use `entity: action` com evento `before_win`/`after_win`.
200
+
201
+ ---
202
+
203
+ ## 6. Combinações Evento × Entidade
204
+
205
+ Quando usar: para saber o **tipo do `entity`** numa dada combinação.
206
+ Não usar quando: precisar dos campos desse tipo → `java-entities.md`.
207
+ Depende de: §4, §5, `java-entities.md`.
208
+ Disponível em: Trigger.
209
+
210
+ ### Descrição
211
+
212
+ Cada combinação evento+entidade entrega um `entity` de tipo específico. Os mais usados:
213
+
214
+ ### Uso
215
+
216
+ | Evento | Entidade | Quando | Tipo do `entity` |
217
+ |--------|----------|--------|----------------|
43
218
  | `before_create` | `player` | Antes de cadastrar jogador | Player |
44
219
  | `after_create` | `player` | Depois de cadastrar jogador | Player |
45
220
  | `before_update` | `player` | Antes de alterar jogador | Player |
46
221
  | `after_delete` | `player` | Depois de remover jogador | Player |
47
222
  | `after_create` | `challenge` | Depois de criar desafio | Challenge |
48
223
  | `after_win` | `challenge` | Depois de completar desafio | Achievement |
49
- | `before_create` | `action` | Antes de criar ação | Action |
224
+ | `before_create` | `action` | Antes de criar definição de ação | Action |
50
225
  | `before_win` | `action` | Antes de registrar action log | ActionLog |
51
226
  | `after_win` | `level` | Depois de subir de nível | Achievement |
52
227
  | `after_win` | `catalog_item` | Depois de comprar item | Achievement |
@@ -57,215 +232,122 @@ Uma trigger é composta de três informações essenciais:
57
232
  | `before_create` | `achievement` | Antes de registrar recompensa | Achievement |
58
233
  | `before_create` | `<custom>__c` | Antes de criar objeto customizado | HashMap |
59
234
 
60
- ## Parâmetros do Script
235
+ ### Armadilhas conhecidas
61
236
 
62
- ```java
63
- void trigger(event, entity, player, database) {
64
- // event: String com o evento (ex: "before_create")
65
- // entity: Objeto sendo manipulado (Player, ActionLog, Achievement, etc.)
66
- // player: String com o ID do jogador
67
- // database: Objeto para acessar o banco de dados
68
- }
69
- ```
237
+ - **Assumir que `before_win action` entrega um Action** → entrega um **ActionLog** (o registro de execução), não a definição.
238
+ - **Tratar `__c` como POJO** → é `HashMap`; use `entity.get("campo")` (`java-entities.md` §12).
70
239
 
71
- ## Tipos de Objetos (entity)
240
+ ---
72
241
 
73
- ### Player
74
- ```json
75
- {"_id": "john", "name": "John Travolta", "email": "john@funifier.com", "image": {"small": {"url": "..."}, "medium": {"url": "..."}, "original": {"url": "..."}}, "teams": ["sales"], "extra": {"country": "USA", "department": "IT"}}
76
- ```
242
+ ## 7. context.extra — Cadeia de Conquistas
77
243
 
78
- ### ActionLog
79
- ```json
80
- {"_id": "64a5d92", "actionId": "sell", "userId": "john", "time": {"$date": "2023-07-05T20:57:33.303Z"}, "attributes": {"product": "book", "price": 120}}
81
- ```
244
+ Quando usar: ao precisar saber qual ação/conquista originou o evento atual.
245
+ Não usar quando: o evento não vem de uma cadeia (`context.extra` pode ser `null`).
246
+ Depende de: `Achievement`, `ActionLog` (`java-entities.md`).
247
+ Disponível em: Trigger (eventos `before_win`, `before_create`, `after_create`).
82
248
 
83
- ### Achievement
84
- ```json
85
- {"_id": "64a5d2", "player": "john", "total": 25.0, "type": 0, "item": "xp", "time": {"$date": "2023-07-05T20:57:33.303Z"}}
86
- ```
87
- Tipos: `TYPE_POINT=0`, `TYPE_CHALLENGE=1`, `TYPE_VIRTUAL_GOOD=2`, `TYPE_LEVEL=3`
88
-
89
- ### Challenge
90
- ```json
91
- {"challenge": "Watch Video", "active": true, "_id": "DTo8dS3", "rules": [{"actionId": "watch_video", "operator": 5, "total": 0}], "points": [{"total": 10.0, "category": "xp", "operation": 0}]}
92
- ```
249
+ ### Descrição
93
250
 
94
- ### Action
95
- ```json
96
- {"_id": "sell", "action": "Sell", "attributes": [{"name": "product", "type": "String"}, {"name": "price", "type": "Number"}], "active": true}
97
- ```
251
+ Quando uma conquista é gerada por uma cadeia (uma ação dispara um desafio, que concede pontos…), `context.extra` expõe a origem. Disponível nos eventos acima quando há cadeia.
98
252
 
99
- ## Managers Disponíveis
253
+ ### Uso
100
254
 
101
- ### PlayerManager
102
255
  ```java
103
- Player p = manager.getPlayerManager().findById("john");
104
- manager.getPlayerManager().insert(player);
105
- manager.getPlayerManager().delete("john");
256
+ context.extra.parentAchievement // Achievement que gerou este evento
257
+ context.extra.parentAchievement.id // String
258
+ context.extra.parentAchievement.type // int (constantes em java-entities.md §3)
259
+ context.extra.parentAchievement.item // String
260
+ context.extra.parentAchievement.player // String
261
+ context.extra.parentAchievement.total // double
262
+
263
+ context.extra.parentActionLog // ActionLog que originou a cadeia
264
+ context.extra.parentActionLog.id // String
265
+ context.extra.parentActionLog.actionId // String
266
+ context.extra.parentActionLog.userId // String
267
+ context.extra.parentActionLog.attributes // Map
268
+
269
+ context.extra.originActionLog // ActionLog raiz (ponta da cadeia)
106
270
  ```
107
271
 
108
- ### ActionManager
109
- ```java
110
- Action a = manager.getActionManager().findActionById("sell");
111
- manager.getActionManager().track(actionLog);
112
- List<Achievement> results = manager.getActionManager().trackSynchonous(actionLog);
113
- ```
272
+ Exemplo de uso em `trigger-examples.md` (Exemplo 2 — taggear conquista com origem).
114
273
 
115
- ### CatalogManager
116
- ```java
117
- CatalogItem item = manager.getCatalogManager().findItemById("DTj7lVn");
118
- manager.getCatalogManager().purchase(achievement, true);
119
- manager.getCatalogManager().undoPurchase("id");
120
- ```
274
+ ### Armadilhas conhecidas
121
275
 
122
- ### LotteryManager
123
- ```java
124
- Lottery l = manager.getLotteryManager().find("DTj0x5z");
125
- manager.getLotteryManager().insertTicket(ticket);
126
- manager.getLotteryManager().execute("DTj0x5z");
127
- ```
276
+ - **Acessar `context.extra.parentAchievement` sem checar null** → NPE. Correção: `if (context.extra == null) return;` e checar cada campo.
128
277
 
129
- ### AchievementManager
130
- ```java
131
- Achievement a = new Achievement();
132
- a.player = "john"; a.total = 10; a.type = 0; a.item = "xp";
133
- a.time = new Date(); a._id = Guid.newShortGuid();
134
- manager.getAchievementManager().addAchievement(a);
135
- ```
278
+ ---
136
279
 
137
- ### Acesso ao Banco de Dados (Jongo)
138
- ```java
139
- // Salvar
140
- manager.getJongoConnection().getCollection("email__c").save(payload);
280
+ ## 8. Regra de Persistência e Rejeição de Criação
141
281
 
142
- // Buscar
143
- Object result = manager.getJongoConnection().getCollection("player").findOne("{_id: 'john'}").as(Object.class);
282
+ Quando usar: ao precisar validar e **rejeitar** uma criação inválida.
283
+ Não usar quando: só precisa enriquecer/normalizar → use `before_create` (mutação direta).
284
+ Depende de: `database.delete(...)`, BusinessException (definida no próprio script).
285
+ Disponível em: Trigger.
144
286
 
145
- // Deletar
146
- manager.getJongoConnection().getCollection("car__c").remove("{_id: 'car001'}");
147
- ```
287
+ ### Descrição
148
288
 
149
- ## Exemplos de Código
289
+ O Funifier persiste o documento; `throw` não cancela (§1.5). Portanto: `before_create` enriquece; **rejeição** se faz em `after_create`, deletando o documento já salvo e devolvendo a mensagem no `entity`.
150
290
 
151
- ### Exemplo 1: Duplicar pontos para jogadores de TI
291
+ ### Uso
152
292
 
153
- ```java
154
- /* "event": "before_create", "entity": "achievement" */
293
+ ```groovy
155
294
  void trigger(event, entity, player, database) {
156
- if(entity.type == Achievement.TYPE_POINT) {
157
- Player currentPlayer = manager.getPlayerManager().findById(player);
158
- if("IT".equals(currentPlayer.extra.department)) {
159
- entity.total = entity.total * 2;
160
- }
295
+ try {
296
+ if (condicaoInvalida) throw new BusinessException("Motivo da rejeição");
297
+ // ... mais validações ...
298
+ } catch (BusinessException e) {
299
+ // a exceção é capturada DENTRO do trigger — não propaga para a plataforma
300
+ database.delete(entity.id, "collection__c");
301
+ entity.clear();
302
+ entity.put("message", e.getMessage());
303
+ return;
161
304
  }
162
305
  }
163
- ```
164
306
 
165
- ### Exemplo 2: Dar ponto para todos os amigos
166
-
167
- ```java
168
- /* "event": "before_create", "entity": "achievement" */
169
- void trigger(event, entity, player, database) {
170
- if(entity.type == Achievement.TYPE_POINT && entity.total >= 100) {
171
- Player p = manager.getPlayerManager().findById(player);
172
- for(String friend : p.friends) {
173
- Achievement a = new Achievement();
174
- a.player = friend; a.total = 1; a.type = 0;
175
- a.item = entity.item; a.time = new Date();
176
- a._id = Guid.newShortGuid();
177
- manager.getAchievementManager().addAchievement(a);
178
- }
179
- }
307
+ public class BusinessException extends Exception {
308
+ private String message;
309
+ public BusinessException(String msg) { super(msg); this.message = msg; }
310
+ public String getMessage() { return this.message; }
180
311
  }
181
312
  ```
182
313
 
183
- ### Exemplo 3: Enviar email de boas-vindas
314
+ `BusinessException` centraliza o cleanup quando múltiplas validações. Para uma validação simples, o `database.delete` + `entity.clear()` + `entity.put("message", ...)` direto basta.
184
315
 
185
- ```java
186
- /* "event": "after_create", "entity": "player" */
187
- void trigger(event, entity, player, database) {
188
- long total = manager.getPlayerManager().findTotal();
189
- Email email = EmailBuilder
190
- .startingBlank()
191
- .from("Company", "your@company.com")
192
- .to(entity.getName(), entity.email)
193
- .withSubject("Welcome!")
194
- .withPlainText("Welcome " + entity.name + ", you are member number " + total)
195
- .buildEmail();
196
- MailerBuilder.withSMTPServer("host", 587, "login", "password")
197
- .buildMailer().sendMail(email);
198
- }
199
- ```
316
+ ### Armadilhas conhecidas
200
317
 
201
- ### Exemplo 4: Requisição HTTP com Unirest
318
+ - **Usar `before_create` + `throw` para rejeitar** → o documento persiste mesmo assim. Correção: `after_create` + delete (`trigger-examples.md` Exemplo 5b).
319
+ - **Esquecer `entity.clear()`** → o documento rejeitado retém dados (sensíveis, no caso de signup). Correção: limpar e devolver só `message`.
202
320
 
203
- ```java
204
- /* "event": "after_win", "entity": "catalog_item" */
205
- void trigger(event, entity, player, database) {
206
- Player buyer = manager.getPlayerManager().findById(entity.player);
207
- CatalogItem item = manager.getCatalogManager().findItemById(entity.item);
208
- HashMap zap = new HashMap();
209
- zap.put("purchase", entity);
210
- zap.put("buyer", buyer);
211
- zap.put("item", item);
212
- HttpResponse<String> response = Unirest.post("https://hooks.zapier.com/hooks/catch/80/b6/")
213
- .header("Content-Type", "application/json")
214
- .body(JsonUtil.toJson(zap))
215
- .asString();
216
- }
217
- ```
321
+ ---
218
322
 
219
- ### Exemplo 5: Criar código de convite
323
+ ## 9. `entity` como List (Eventos de Bulk)
220
324
 
221
- ```java
222
- /* "event": "before_create", "entity": "player" */
223
- void trigger(event, entity, player, database) {
224
- String code = Guid.shortTimeMillis();
225
- entity.extra.put("code", code);
226
- }
227
- ```
325
+ Quando usar: ao reagir a `before_bulk`/`after_bulk`/`csv_*` (§4).
326
+ Não usar quando: o evento é de documento único (`entity` é um objeto).
327
+ Depende de: §4 (eventos estendidos).
328
+ Disponível em: Trigger.
228
329
 
229
- ### Exemplo 6: Consultar objeto no banco
330
+ ### Descrição
230
331
 
231
- ```java
232
- /* "event": "before_win", "entity": "action" */
233
- void trigger(event, entity, player, database) {
234
- String id = entity.attributes.product;
235
- Object product = database.getCollection("product__c").findOne("{_id:#}", id).as(Object.class);
236
- entity.attributes.put("price", product.price);
237
- }
238
- ```
332
+ Nos eventos de lote, `entity` é uma **List** de documentos, não um único. Itere e processe cada item.
239
333
 
240
- ### Exemplo 7: Executar aggregate no banco
334
+ ### Uso
241
335
 
242
- ```java
243
- /* "event": "before_win", "entity": "action" */
336
+ ```groovy
244
337
  void trigger(event, entity, player, database) {
245
- org.jongo.MongoCollection collection = database.getCollection("achievement");
246
- List<Object> highest = Arrays.asList(
247
- collection.aggregate("{\"$match\": {\"type\": 0, \"item\": \"xp\"}}")
248
- .and("{\"$group\": {\"_id\": \"$player\", \"total\": {\"$sum\": \"$total\"}}}")
249
- .and("{\"$sort\": {\"total\": -1}}")
250
- .and("{\"$limit\":1}")
251
- .as(Object.class));
252
- if(highest != null && highest.size() > 0) {
253
- Object highestPointsPlayer = highest.get(0);
254
- entity.attributes.put("highest", highestPointsPlayer.total);
338
+ if (entity == null || entity.isEmpty()) return;
339
+ for (Object raw : entity) {
340
+ HashMap<String, Object> item = (HashMap<String, Object>) raw;
341
+ if (item == null) continue;
342
+ // processar item...
255
343
  }
344
+ println("bulk processado: " + entity.size());
256
345
  }
257
346
  ```
258
347
 
259
- ## Bibliotecas Disponíveis
348
+ Exemplo completo em `trigger-examples.md` (Exemplo 6).
260
349
 
261
- - **org.simplejavamail** - Envio de emails
262
- - **com.mashape.unirest** - Requisições HTTP
263
- - **org.jongo** - Acesso ao MongoDB
264
- - **JsonUtil** - Conversão JSON
265
- - **Guid** - Geração de IDs únicos
266
- - **DateUtil** - Cálculos e expressões de data
350
+ ### Armadilhas conhecidas
267
351
 
268
- > **Referência completa:** Para detalhes de todos os managers, entidades e bibliotecas disponíveis em Java, consulte:
269
- > - `guides/java-managers.md` Todos os managers e seus métodos
270
- > - `guides/java-entities.md` — Entidades, campos e coleções MongoDB
271
- > - `guides/java-libraries.md` — JsonUtil, Guid, DateUtil, Unirest, EmailBuilder, Jongo
352
+ - **Tratar `entity` como documento único em evento de bulk** `ClassCastException`. Correção: iterar a List.
353
+ - **`entity.size()` em evento não-bulk** → `entity` não é List. Correção: usar List só nos eventos de §4.
@@ -11,6 +11,7 @@ A Funifier funciona como um **backend de aplicações**. Independentemente do ti
11
11
  | Recurso | Ficheiro | Para que serve |
12
12
  |---------|----------|----------------|
13
13
  | **Auth** | `modules/auth.md` | Login de jogadores, geração de tokens JWT, autenticação via API |
14
+ | **Security** | `modules/security.md` | Configuração do documento de segurança — apps com app_secret, roles de jogador, escopos, pipeline de autorização e emissão de tokens Bearer |
14
15
  | **Player** | `modules/player.md` | Cadastro e gestão de utilizadores da aplicação |
15
16
  | **Database** | `modules/database.md` | CRUD em qualquer coleção, queries MongoDB, aggregates |
16
17
  | **Custom Object** | `modules/custom-object.md` | Criar tabelas/coleções próprias (sufixo `__c`) para dados de negócio |
@@ -84,7 +85,8 @@ A Funifier funciona como um **backend de aplicações**. Independentemente do ti
84
85
  | Módulo | Ficheiro | Descrição | Quando usar |
85
86
  |--------|----------|-----------|-------------|
86
87
  | Auth | `modules/auth.md` | Autenticação e tokens | Gerar tokens de acesso; configurar API keys; autenticação OAuth |
87
- | Folder | `modules/folder.md` | Organização em pastas | Organizar módulos (ações, desafios, etc.) em pastas no Studio |
88
+ | Security | `modules/security.md` | Configuração de segurança | Configurar apps (app_secret, scope, whitelist) e roles de jogador; entender escopos hierárquicos, pipeline de autorização e emissão de tokens; diagnóstico de erros 401 |
89
+ | Folder | `modules/folder.md` | Trilhas e cursos | Criar trilhas de aprendizagem e cursos; organizar conteúdos em hierarquia com monitoramento de progresso do jogador |
88
90
  | Backup | `modules/backup.md` | Backup e restauração | Criar backups da gamificação; restaurar configurações |
89
91
  | Compact | `modules/compact.md` | Compactação de dados | Compactar dados históricos para otimizar performance |
90
92
  | Staging | `modules/staging.md` | Ambiente de homologação | Testar configurações em ambiente separado antes de produção |
@@ -98,6 +100,7 @@ A Funifier funciona como um **backend de aplicações**. Independentemente do ti
98
100
  |------|----------|-----------|-------------|
99
101
  | Aggregates | `guides/aggregates.md` | Consultas avançadas MongoDB | Criar relatórios, dashboards, rankings customizados; usar expressões de data Funifier |
100
102
  | Triggers | `guides/triggers-guide.md` | Guia completo de triggers | Referência de eventos, entidades, managers e exemplos de código Java |
103
+ | Trigger Examples | `guides/trigger-examples.md` | Exemplos de produção de triggers | Código Groovy pronto para padrões reais: atualizar coleção relacionada, criar achievement, inicializar jogador, normalizar/rejeitar `__c`, processar lote, registrar ação via `track` |
101
104
  | Database Access | `guides/database-access.md` | Acesso ao banco de dados | Referência de acesso via API REST e via código Java (Jongo) |
102
105
  | Java Managers | `guides/java-managers.md` | Referência de managers Java | Métodos disponíveis em cada manager (PlayerManager, ActionManager, etc.) para uso em triggers, schedulers e public endpoints |
103
106
  | Java Entities | `guides/java-entities.md` | Referência de entidades Java | Campos e tipos dos objetos (Player, Achievement, ActionLog, etc.) e mapeamento para coleções MongoDB |
@@ -116,6 +119,6 @@ Para consultas que envolvem **múltiplos módulos**, carregue cada ficheiro indi
116
119
 
117
120
  Para **relatórios e queries avançadas**, consulte `guides/aggregates.md`.
118
121
 
119
- Para **lógica customizada com código**, consulte `guides/triggers-guide.md` e `guides/database-access.md`.
122
+ Para **lógica customizada com código**, consulte `guides/triggers-guide.md` (conceitos e referência de eventos) e `guides/trigger-examples.md` (exemplos Groovy prontos), além de `guides/database-access.md`.
120
123
 
121
124
  Para **referência completa de recursos Java** (managers, entidades, bibliotecas), consulte `guides/java-managers.md`, `guides/java-entities.md` e `guides/java-libraries.md`.