funifier-mcp 0.2.26 → 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 (170) 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 +4 -1
  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 +935 -280
  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/mcp/bundle.js +119 -93
  66. package/dist/mcp/index.js +2 -2
  67. package/dist/mcp/index.js.map +1 -1
  68. package/dist/mcp/resources/documentation.d.ts +1 -1
  69. package/dist/mcp/resources/documentation.d.ts.map +1 -1
  70. package/dist/mcp/resources/documentation.js +39 -3
  71. package/dist/mcp/resources/documentation.js.map +1 -1
  72. package/dist/mcp/tools/connect.d.ts.map +1 -1
  73. package/dist/mcp/tools/connect.js +18 -8
  74. package/dist/mcp/tools/connect.js.map +1 -1
  75. package/dist/mcp/tools/database.d.ts.map +1 -1
  76. package/dist/mcp/tools/database.js +59 -47
  77. package/dist/mcp/tools/database.js.map +1 -1
  78. package/dist/mcp/tools/database.test.js +2 -2
  79. package/dist/mcp/tools/database.test.js.map +1 -1
  80. package/dist/mcp/tools/delete.d.ts.map +1 -1
  81. package/dist/mcp/tools/delete.js +13 -3
  82. package/dist/mcp/tools/delete.js.map +1 -1
  83. package/dist/mcp/tools/execute.d.ts.map +1 -1
  84. package/dist/mcp/tools/execute.js +20 -9
  85. package/dist/mcp/tools/execute.js.map +1 -1
  86. package/dist/mcp/tools/folder.d.ts.map +1 -1
  87. package/dist/mcp/tools/folder.js +22 -12
  88. package/dist/mcp/tools/folder.js.map +1 -1
  89. package/dist/mcp/tools/get.d.ts.map +1 -1
  90. package/dist/mcp/tools/get.js +16 -6
  91. package/dist/mcp/tools/get.js.map +1 -1
  92. package/dist/mcp/tools/index.d.ts +1 -1
  93. package/dist/mcp/tools/index.d.ts.map +1 -1
  94. package/dist/mcp/tools/index.js +3 -1
  95. package/dist/mcp/tools/index.js.map +1 -1
  96. package/dist/mcp/tools/list.d.ts.map +1 -1
  97. package/dist/mcp/tools/list.js +38 -14
  98. package/dist/mcp/tools/list.js.map +1 -1
  99. package/dist/mcp/tools/logs.d.ts.map +1 -1
  100. package/dist/mcp/tools/logs.js +15 -5
  101. package/dist/mcp/tools/logs.js.map +1 -1
  102. package/dist/mcp/tools/save.d.ts.map +1 -1
  103. package/dist/mcp/tools/save.js +14 -4
  104. package/dist/mcp/tools/save.js.map +1 -1
  105. package/dist/mcp/tools/save.test.js +3 -3
  106. package/dist/mcp/tools/save.test.js.map +1 -1
  107. package/dist/mcp/tools/search-docs.d.ts +3 -0
  108. package/dist/mcp/tools/search-docs.d.ts.map +1 -0
  109. package/dist/mcp/tools/search-docs.js +102 -0
  110. package/dist/mcp/tools/search-docs.js.map +1 -0
  111. package/package.json +6 -2
  112. package/skills/acquire-funifier-knowledge/SKILL.md +132 -0
  113. package/skills/acquire-funifier-knowledge/assets/templates/CONCERNS.md +25 -0
  114. package/skills/acquire-funifier-knowledge/assets/templates/CUSTOM_ENDPOINTS.md +24 -0
  115. package/skills/acquire-funifier-knowledge/assets/templates/CUSTOM_PAGES.md +24 -0
  116. package/skills/acquire-funifier-knowledge/assets/templates/GAME_MECHANICS.md +35 -0
  117. package/skills/acquire-funifier-knowledge/assets/templates/INTEGRATIONS.md +35 -0
  118. package/skills/acquire-funifier-knowledge/assets/templates/LEADERBOARDS.md +24 -0
  119. package/skills/acquire-funifier-knowledge/assets/templates/OVERVIEW.md +47 -0
  120. package/skills/acquire-funifier-knowledge/assets/templates/PLAYER_MODEL.md +31 -0
  121. package/skills/acquire-funifier-knowledge/assets/templates/SCHEDULERS.md +25 -0
  122. package/skills/acquire-funifier-knowledge/assets/templates/TECHNIQUES_AND_PATTERNS.md +26 -0
  123. package/skills/acquire-funifier-knowledge/assets/templates/TRIGGERS.md +27 -0
  124. package/skills/acquire-funifier-knowledge/references/funifier-inventory-checklist.md +81 -0
  125. package/skills/acquire-funifier-knowledge/references/game-techniques-taxonomy.md +62 -0
  126. package/skills/acquire-funifier-knowledge/references/mcp-call-patterns.md +118 -0
  127. package/skills/funifier/SKILL.md +88 -0
  128. package/skills/funifier/references/configure-security.md +96 -0
  129. package/skills/{funifier-create-action/SKILL.md → funifier/references/create-action.md} +0 -33
  130. package/skills/funifier/references/create-aggregate.md +144 -0
  131. package/skills/funifier/references/create-challenge.md +116 -0
  132. package/skills/funifier/references/create-competition.md +98 -0
  133. package/skills/funifier/references/create-crossword.md +574 -0
  134. package/skills/funifier/references/create-custom-object.md +91 -0
  135. package/skills/funifier/references/create-custom-page.md +135 -0
  136. package/skills/funifier/references/create-folder.md +104 -0
  137. package/skills/funifier/references/create-lastmile.md +643 -0
  138. package/skills/{funifier-create-leaderboard/SKILL.md → funifier/references/create-leaderboard.md} +0 -33
  139. package/skills/funifier/references/create-level.md +94 -0
  140. package/skills/funifier/references/create-lottery.md +913 -0
  141. package/skills/funifier/references/create-mystery.md +769 -0
  142. package/skills/funifier/references/create-notification.md +75 -0
  143. package/skills/{funifier-create-point/SKILL.md → funifier/references/create-point.md} +0 -33
  144. package/skills/funifier/references/create-quiz.md +98 -0
  145. package/skills/funifier/references/create-scheduler.md +141 -0
  146. package/skills/funifier/references/create-story.md +636 -0
  147. package/skills/funifier/references/create-swap.md +95 -0
  148. package/skills/{funifier-create-trigger/SKILL.md → funifier/references/create-trigger.md} +0 -33
  149. package/skills/funifier/references/create-virtual-good.md +96 -0
  150. package/skills/funifier/references/create-webhook.md +72 -0
  151. package/skills/funifier/references/create-websocket.md +71 -0
  152. package/skills/funifier/references/create-widget.md +76 -0
  153. package/skills/funifier/references/debug.md +87 -0
  154. package/skills/funifier/references/help.md +81 -0
  155. package/skills/funifier/references/implement-frontend.md +106 -0
  156. package/skills/funifier/references/import-csv.md +75 -0
  157. package/skills/funifier/references/manage-player.md +82 -0
  158. package/skills/funifier/references/manage-team.md +76 -0
  159. package/skills/funifier/references/upload-file.md +91 -0
  160. package/skills/funifier-create-aggregate/SKILL.md +0 -127
  161. package/skills/funifier-create-challenge/SKILL.md +0 -88
  162. package/skills/funifier-create-custom-page/SKILL.md +0 -127
  163. package/skills/funifier-create-level/SKILL.md +0 -87
  164. package/skills/funifier-create-quiz/SKILL.md +0 -87
  165. package/skills/funifier-create-scheduler/SKILL.md +0 -127
  166. package/skills/funifier-create-virtual-good/SKILL.md +0 -87
  167. package/skills/funifier-debug/SKILL.md +0 -92
  168. package/skills/funifier-help/SKILL.md +0 -86
  169. package/skills/funifier-implement-frontend/SKILL.md +0 -90
  170. package/skills/funifier-index/SKILL.md +0 -58
@@ -1,96 +1,211 @@
1
1
  # Aggregates Funifier
2
2
 
3
- A plataforma Funifier utiliza o MongoDB como banco de dados, permitindo consultas avançadas por meio de **aggregates**. Esta funcionalidade é fundamental para extrair relatórios, gerar indicadores personalizados e construir dashboards.
3
+ ## 1. Visão Geral
4
4
 
5
- ## Como Executar
5
+ ### 1.1 O que é este documento
6
6
 
7
- **Método:** POST
8
- **Endpoint:** `/v3/database/{collection}/aggregate`
9
- **Body:** Pipeline JSON com comandos aggregate
7
+ Este documento descreve como executar pipelines de aggregate MongoDB na Funifier e a sintaxe das **expressões de data Funifier** — para relatórios, indicadores e rankings customizados. É o dono único das expressões de data.
10
8
 
11
- ## Principais Coleções
9
+ ### 1.2 Quando consultar
12
10
 
13
- ### player
14
- Jogadores da gamificação.
15
- ```json
16
- {"_id": "john", "name": "John Travolta", "email": "john@funifier.com", "teams": ["sales"], "extra": {"country": "USA", "department": "IT"}, "created": {"$date": "2023-07-05T20:57:25.776Z"}}
17
- ```
11
+ - Consulte ao construir **relatórios/dashboards** (top N, médias, contagens) via `$group`/`$sort`.
12
+ - Consulte ao precisar **juntar coleções** com `$lookup` (e por isso precisar das relações entre coleções).
13
+ - Consulte ao precisar de **filtros por data relativa** (`-0M-`, `-1d+`) em queries ou código.
18
14
 
19
- ### action
20
- Configurações dos tipos de ações.
21
- ```json
22
- {"_id": "sell", "action": "Sell", "attributes": [{"name": "product", "type": "String"}, {"name": "price", "type": "Number"}], "active": true}
23
- ```
15
+ ### 1.3 Quando NÃO consultar
24
16
 
25
- ### action_log
26
- Ações executadas pelos jogadores. Campo `userId` `player._id`. Campo `actionId` `action._id`.
27
- ```json
28
- {"_id": "64a5d92", "actionId": "sell", "userId": "john", "time": {"$date": "2023-07-05T20:57:33.303Z"}, "attributes": {"product": "book", "price": 120}}
29
- ```
17
+ - **NÃO** consulte para o **CRUD/mecânica geral** de `/v3/database` — use `datasource-funifier-docs/knowledge/guides/database-access.md`.
18
+ - **NÃO** consulte para os **métodos Java de `DateUtil`** (`fromKeyword`, `add`, escalas) — use `java-libraries.md` §4. Aqui fica a *semântica* das expressões.
19
+ - **NÃO** consulte para os **campos completos** das coleções — use `java-entities.md`. Aqui ficam só as relações relevantes a `$lookup`.
30
20
 
31
- ### achievement
32
- Conquistas dos jogadores. Campo `type`: 0=Point, 1=Challenge, 2=Virtual Good, 3=Level. Campo `player` → `player._id`.
33
- ```json
34
- {"_id": "64a5d2", "player": "john", "total": 25.0, "type": 0, "item": "xp", "time": {"$date": "2023-07-05T20:57:33.303Z"}}
35
- ```
21
+ ### 1.4 Índice de decisão
36
22
 
37
- ### challenge
38
- Desafios da gamificação.
39
- ```json
40
- {"challenge": "Watch Video", "active": true, "_id": "DTo8dS3", "rules": [{"actionId": "watch_video", "operator": 5, "total": 0}], "points": [{"total": 10.0, "category": "xp", "operation": 0}]}
41
- ```
23
+ | Problema / Situação | O que fazer | Seção |
24
+ |---|---|---|
25
+ | Executar um pipeline | `POST /v3/database/:collection/aggregate` | §2 |
26
+ | Saber qual campo liga duas coleções (`$lookup`) | Ver relações entre coleções | §3 |
27
+ | Filtrar por "mês atual", "ontem", "este ano" | Expressões de data Funifier | §4 |
28
+ | Saber quais operadores são aceitos | Ver operadores suportados | §5 |
29
+ | Ver um pipeline pronto (top N, média, distintos) | Ver exemplos práticos | §6 |
42
30
 
43
- ### point_category
44
- Tipos de pontos.
45
- ```json
46
- {"_id": "xp", "category": "Experience Points", "shortName": "XP", "extra": {}}
31
+ ### 1.5 Restrições globais críticas
32
+
33
+ > ⚠️ **O GET de listagem (`/v3/database`) não ordena.** Consequência de usar `_sort`: ignorado (`patterns.md` §1.5). → Para ordenar, use `$sort` num pipeline de aggregate.
34
+
35
+ > ⚠️ **Em escrita/leitura tipada, use `strict=true` (`?strict=true` na URL do aggregate).** Consequência de omitir: `Date` degrada para número e o `$match` por data falha (`patterns.md` §9).
36
+
37
+ > ⚠️ **`$` precisa de escape em código Groovy de Public Endpoint.** Consequência: operadores Mongo (`$match`, `$group`) quebram. → Ver o padrão de escape em `database-access.md` §3.
38
+
39
+ ### 1.6 Documentos relacionados
40
+
41
+ > 📄 `datasource-funifier-docs/knowledge/guides/database-access.md` — mecânica de acesso e execução via API/Jongo
42
+ > 📄 `datasource-funifier-docs/knowledge/guides/java-libraries.md` §4 — métodos Java de `DateUtil`
43
+ > 📄 `datasource-funifier-docs/knowledge/guides/java-entities.md` — campos completos das coleções
44
+
45
+ ---
46
+
47
+ ## 2. Execução de Aggregate
48
+
49
+ Quando usar: rodar um pipeline de agregação sobre uma coleção.
50
+ Não usar quando: precisar só de um filtro simples → `GET ?q=` (`database-access.md` §2).
51
+ Depende de: token autenticado com `database` no scope.
52
+ Disponível em: API REST e código (Jongo).
53
+
54
+ ### Descrição
55
+
56
+ Um aggregate aplica uma sequência de estágios (`$match`, `$group`, etc.) sobre os documentos de uma coleção e retorna o resultado transformado.
57
+
58
+ ### Uso
59
+
60
+ **Via API REST:**
61
+ ```
62
+ POST /v3/database/{collection}/aggregate?strict=true
63
+ [
64
+ { "$match": { "player": "john", "type": 0, "item": "xp" } },
65
+ { "$group": { "_id": null, "totalXP": { "$sum": "$total" } } }
66
+ ]
67
+ → [{ "totalXP": 250 }]
47
68
  ```
48
69
 
49
- ### catalog_item
50
- Itens da loja virtual.
51
- ```json
52
- {"_id": "prd1", "catalogId": "gifts", "name": "T-shirt", "amount": 100, "active": true, "requires": [{"total": 15, "type": 0, "item": "coin", "operation": 1}]}
70
+ **Via Jongo (código):** cada estágio é um argumento de `.and(...)`:
71
+ ```java
72
+ Iterable<Map> result = database.getCollection("achievement")
73
+ .aggregate("{$match: {type: 0, item: 'xp'}}")
74
+ .and("{$group: {_id: '$player', total: {$sum: '$total'}}}")
75
+ .and("{$sort: {total: -1}}")
76
+ .and("{$limit: 10}")
77
+ .as(Map.class);
53
78
  ```
54
79
 
55
- ## Expressões de Data (Funifier Syntax)
80
+ ### Armadilhas conhecidas
81
+
82
+ - **Esperar ordenação do GET** → não ordena (§1.5). Correção: `$sort` no pipeline.
83
+ - **Pipeline sem `strict=true` lendo datas** → `$match` por data falha (§1.5).
84
+
85
+ ---
86
+
87
+ ## 3. Coleções e Relações (para `$lookup`)
88
+
89
+ Quando usar: ao escrever `$lookup` e precisar saber qual campo liga as coleções.
90
+ Não usar quando: precisar de todos os campos da coleção → `java-entities.md`.
91
+ Depende de: `java-entities.md` (campos completos).
92
+ Disponível em: —
93
+
94
+ ### Descrição
95
+
96
+ Relações que importam ao juntar coleções. Os exemplos mostram o documento mínimo; campos completos em `java-entities.md`.
56
97
 
57
- Formato: `[sinal][quantidade][unidade][ajuste opcional]`
98
+ ### Uso
99
+
100
+ | Coleção | Relação-chave | Exemplo |
101
+ |---|---|---|
102
+ | `player` | `_id` é a ponta de `userId`/`player` | `{"_id":"john","name":"John","extra":{"department":"IT"}}` |
103
+ | `action_log` | `userId` → `player._id`; `actionId` → `action._id` | `{"actionId":"sell","userId":"john","attributes":{"price":120}}` |
104
+ | `achievement` | `player` → `player._id`; `item` → coleção do `type` | `{"player":"john","total":25.0,"type":0,"item":"xp"}` |
105
+ | `challenge` | `_id` é referenciado por `achievement.item` (type 1) | `{"_id":"DTo8dS3","challenge":"Watch Video"}` |
106
+ | `catalog_item` | `_id` é referenciado por `achievement.item` (type 2) | `{"_id":"prd1","name":"T-shirt"}` |
107
+ | `point_category` | `_id` é referenciado por `achievement.item` (type 0) | `{"_id":"xp","category":"Experience Points"}` |
108
+
109
+ > `achievement.type`: `0`=Point, `1`=Challenge, `2`=Virtual Good, `3`=Level, `5`=Lottery, `9`=Competition (`java-entities.md` §3). O `item` aponta para a coleção correspondente ao `type`.
110
+
111
+ ### Armadilhas conhecidas
112
+
113
+ - **`$lookup` com `localField` errado** → resultado vazio. Correção: conferir a relação acima (ex: em `achievement`, juntar por `player` e não `_id`).
114
+
115
+ ---
116
+
117
+ ## 4. Expressões de Data Funifier
118
+
119
+ Quando usar: filtrar por períodos relativos ("mês atual", "ontem") em `$match` ou em código.
120
+ Não usar quando: a data é absoluta e conhecida → use ISO-8601 (`{"$date": "2023-08-01T00:00:00.000Z"}`).
121
+ Depende de: —
122
+ Disponível em: filtros de aggregate (`{"$date": "..."}`) e `DateUtil.fromKeyword(...)` (`java-libraries.md` §4).
123
+
124
+ ### Descrição
125
+
126
+ Sintaxe própria da Funifier para datas relativas, resolvida no servidor. Formato: `[sinal][quantidade][unidade][ajuste]`.
127
+
128
+ - **Unidades:** `y`=ano, `M`=mês, `w`=semana, `d`=dia, `h`=hora, `m`=minuto, `s`=segundo
129
+ - **Ajuste:** `-` = início da unidade (floor), `+` = fim da unidade (ceil), sem ajuste = instante exato
130
+
131
+ ### Uso
58
132
 
59
133
  | Expressão | Significado |
60
134
  |-----------|------------|
61
135
  | `-0d` | Agora |
62
136
  | `-0d-` | Início do dia atual (00:00:00) |
63
137
  | `-0d+` | Fim do dia atual (23:59:59) |
64
- | `-1d` | Exatamente um dia atrás |
65
- | `-1d-` | Início do dia anterior (00:00:00) |
66
- | `-1d+` | Fim do dia anterior (23:59:59) |
138
+ | `-1d` | Exatamente 1 dia atrás |
139
+ | `-1d-` | Início do dia anterior |
140
+ | `-1d+` | Fim do dia anterior |
141
+ | `+1d` | Exatamente 1 dia no futuro |
142
+ | `+1d-` | Início do dia seguinte |
67
143
  | `-0w-` | Início da semana atual |
68
144
  | `-0w+` | Fim da semana atual |
69
- | `-1w` | Exatamente uma semana atrás |
70
- | `-0M-` | Início do mês atual |
71
- | `-0M+` | Fim do mês atual |
72
- | `-1M` | Exatamente um mês atrás |
73
- | `-1M-` | Início do mês anterior |
74
- | `-0y-` | Início do ano atual |
75
- | `-0y+` | Fim do ano atual |
145
+ | `-1w` | Exatamente 1 semana atrás |
146
+ | `-0M-` | Primeiro dia do mês (00:00:00) |
147
+ | `-0M+` | Último dia do mês (23:59:59) |
148
+ | `-1M` | Exatamente 1 mês atrás |
149
+ | `-1M-` | Primeiro dia do mês anterior |
150
+ | `-0y-` | 1 de janeiro do ano atual |
151
+ | `-0y+` | 31 de dezembro do ano atual |
76
152
 
77
- **Unidades:** `m`=minuto, `h`=hora, `d`=dia, `w`=semana, `M`=mês, `y`=ano
153
+ **Encadeamento com `|`** (ajustes e fuso):
154
+ ```
155
+ -1d+|GMT+3 → fim do dia anterior no fuso GMT+3
156
+ -0d-|+5h|+30m|GMT-3 → início do dia + 5h30m no fuso GMT-3
157
+ ```
78
158
 
79
- **Uso em filtros:**
159
+ **Em filtro de aggregate:**
80
160
  ```json
81
- {"$date": "-0M-"}
161
+ { "$match": { "time": { "$gte": { "$date": "-0M-" }, "$lte": { "$date": "-0M+" } } } }
82
162
  ```
83
163
 
84
- ## Operadores Suportados
164
+ **Em código:** `DateUtil.fromKeyword("-0M-")` (`java-libraries.md` §4).
165
+
166
+ ### Armadilhas conhecidas
167
+
168
+ - **Esquecer o ajuste** (`-0M` em vez de `-0M-`) → instante exato, não início do mês. Correção: incluir `-`/`+` conforme o limite desejado.
169
+ - **`$gte` sem `$lte`** → janela aberta inclui o futuro. Correção: par `-0M-`/`-0M+`.
170
+
171
+ ---
172
+
173
+ ## 5. Operadores Suportados
174
+
175
+ Quando usar: ao montar o pipeline.
176
+ Não usar quando: —
177
+ Depende de: —
178
+ Disponível em: API REST e Jongo.
179
+
180
+ ### Descrição
181
+
182
+ Operadores de pipeline aceitos.
183
+
184
+ ### Uso
85
185
 
86
186
  `$match`, `$group`, `$sort`, `$limit`, `$lookup`, `$project`, `$unwind`, `$addFields`, `$count`
87
187
 
88
- ## Exemplos Práticos
188
+ ### Armadilhas conhecidas
189
+
190
+ - **Usar operador fora desta lista** → pode não ser suportado. Valide em homologação antes.
191
+
192
+ ---
193
+
194
+ ## 6. Exemplos Práticos
195
+
196
+ Quando usar: como ponto de partida para relatórios comuns.
197
+ Não usar quando: a necessidade é um CRUD simples → `database-access.md`.
198
+ Depende de: §3 (relações) e §4 (datas).
199
+ Disponível em: API REST.
89
200
 
90
- ### Exemplo 1: Top 10 jogadores com mais pontos XP no mês atual
201
+ ### Descrição
91
202
 
203
+ Pipelines prontos para os relatórios mais frequentes.
204
+
205
+ ### Uso
206
+
207
+ **Top 10 jogadores com mais XP no mês atual** (`POST /v3/database/achievement/aggregate`):
92
208
  ```json
93
- // POST /v3/database/achievement/aggregate
94
209
  [
95
210
  {"$match": {"type": 0, "item": "xp", "time": {"$gte": {"$date": "-0M-"}, "$lte": {"$date": "-0M+"}}}},
96
211
  {"$group": {"_id": "$player", "total": {"$sum": "$total"}}},
@@ -102,10 +217,8 @@ Formato: `[sinal][quantidade][unidade][ajuste opcional]`
102
217
  ]
103
218
  ```
104
219
 
105
- ### Exemplo 2: Quantos jogadores distintos completaram um desafio
106
-
220
+ **Jogadores distintos que completaram um desafio:**
107
221
  ```json
108
- // POST /v3/database/achievement/aggregate
109
222
  [
110
223
  {"$match": {"type": 1, "item": "DTo8dS3"}},
111
224
  {"$group": {"_id": "$player", "challenge": {"$first": "$item"}}},
@@ -115,20 +228,16 @@ Formato: `[sinal][quantidade][unidade][ajuste opcional]`
115
228
  ]
116
229
  ```
117
230
 
118
- ### Exemplo 3: Média de pontos XP por jogador em um mês específico
119
-
231
+ **Média de XP por jogador em mês específico:**
120
232
  ```json
121
- // POST /v3/database/achievement/aggregate
122
233
  [
123
234
  {"$match": {"type": 0, "item": "xp", "time": {"$gte": {"$date": "2023-08-01T00:00:00.000Z"}, "$lte": {"$date": "2023-08-31T23:59:59.999Z"}}}},
124
235
  {"$group": {"_id": "$player", "averageXP": {"$avg": "$total"}}}
125
236
  ]
126
237
  ```
127
238
 
128
- ### Exemplo 4: Top 3 itens mais vendidos na loja virtual este ano
129
-
239
+ **Top 3 itens mais vendidos este ano:**
130
240
  ```json
131
- // POST /v3/database/achievement/aggregate
132
241
  [
133
242
  {"$match": {"type": 2, "time": {"$gte": {"$date": "-0y-"}, "$lte": {"$date": "-0y+"}}}},
134
243
  {"$group": {"_id": "$item", "totalSold": {"$sum": "$total"}}},
@@ -139,10 +248,8 @@ Formato: `[sinal][quantidade][unidade][ajuste opcional]`
139
248
  ]
140
249
  ```
141
250
 
142
- ### Exemplo 5: Jogadores que executaram ações ontem
143
-
251
+ **Jogadores que executaram ações ontem** (`POST /v3/database/action_log/aggregate`):
144
252
  ```json
145
- // POST /v3/database/action_log/aggregate
146
253
  [
147
254
  {"$match": {"time": {"$gte": {"$date": "-1d-"}, "$lte": {"$date": "-1d+"}}}},
148
255
  {"$group": {"_id": "$userId"}},
@@ -150,3 +257,8 @@ Formato: `[sinal][quantidade][unidade][ajuste opcional]`
150
257
  {"$project": {"_id": 1, "playerName": {"$first": "$p.name"}}}
151
258
  ]
152
259
  ```
260
+
261
+ ### Armadilhas conhecidas
262
+
263
+ - **`$lookup` em `achievement` por `_id`** → resultado vazio; junte por `$player`/`$item` conforme o caso (§3).
264
+ - **`$project` esperando `$p.name` sem `$unwind`** → `$p` é array. Correção: `$unwind` ou `{"$first": "$p.name"}`.
@@ -1,132 +1,218 @@
1
1
  # Acesso ao Banco de Dados Funifier
2
2
 
3
- A plataforma Funifier oferece duas formas principais de acessar e manipular os dados da gamificação:
3
+ ## 1. Visão Geral
4
4
 
5
- 1. **Via API REST** endpoint `/v3/database`
6
- 2. **Via código Java** — objeto `manager` em triggers, schedulers e public endpoints
5
+ ### 1.1 O que é este documento
7
6
 
8
- Ambas utilizam **MongoDB** como banco de dados.
7
+ Este documento descreve as duas formas de acessar o MongoDB da Funifier — via API REST (`/v3/database`) e via código Java/Groovy (Jongo) — para operações CRUD, filtros e índices. É o dono único da mecânica de acesso ao banco.
8
+
9
+ ### 1.2 Quando consultar
10
+
11
+ - Consulte ao **ler/escrever coleções** via API REST ou código.
12
+ - Consulte ao precisar dos **placeholders seguros** (`#`) do Jongo.
13
+ - Consulte ao **filtrar** uma listagem (`q`) ou gerir **índices**.
14
+ - Consulte ao escolher entre **`database.getCollection(...)`** (trigger) e **`manager.getJongoConnection()`** (scheduler/endpoint).
15
+
16
+ ### 1.3 Quando NÃO consultar
17
+
18
+ - **NÃO** consulte para **pipelines de aggregate** (`$match`/`$group`/`$sort`) nem **expressões de data** — use `datasource-funifier-docs/knowledge/guides/aggregates.md`. Aqui fica só o endpoint/mecânica.
19
+ - **NÃO** consulte para escrita de **entidades nativas** (`player`, `action`, etc.) — use o endpoint nativo (`patterns.md` §10); `/v3/database` é para coleções genéricas/`__c`.
20
+ - **NÃO** consulte para **tipos BSON e strict mode em detalhe** — use `patterns.md` §9.
21
+
22
+ ### 1.4 Índice de decisão
23
+
24
+ | Problema / Situação | O que fazer | Seção |
25
+ |---|---|---|
26
+ | Listar coleções existentes | `GET /v3/database/collections` | §2 |
27
+ | CRUD numa coleção genérica/`__c` | `/v3/database/:collection` | §2 |
28
+ | Filtrar uma listagem | `?q=campo:"valor"` (não `_filter`) | §2 |
29
+ | Ordenar resultados | `POST .../aggregate` com `$sort` (o GET não ordena) | §2 → `aggregates.md` |
30
+ | Ler/escrever em código (trigger) | `database.getCollection(...)` | §3 |
31
+ | Ler/escrever em código (scheduler/endpoint) | `manager.getJongoConnection()...` | §3 |
32
+ | Evitar injeção em query | placeholder `#` | §4 |
33
+ | Criar/listar/excluir índice | `/v3/database/:collection/index` | §5 |
34
+
35
+ ### 1.5 Restrições globais críticas
36
+
37
+ > ⚠️ **O parâmetro de filtro é `q` (sintaxe Mongo), não `_filter`.** Consequência: `_filter`/`_sort`/`_limit` são **silenciosamente ignorados** e a query retorna todos os registros (`patterns.md` §1.5, `modules/database.md` §4.2). → Use `?q=campo:"valor"&strict=true`. Para ordenar, use `POST .../aggregate` com `$sort`.
38
+
39
+ > ⚠️ **`PUT /v3/database/:collection` é replace total.** Consequência: campos não enviados são apagados. → Envie o objeto completo (read-merge-write).
40
+
41
+ > ⚠️ **`POST /v3/database/:collection` (sem `/aggregate`) cria um documento.** Consequência de enviar um filtro esperando busca: cria lixo na coleção (`patterns.md` §10). → Para filtrar, use `GET ?q=`; para pipeline, `POST .../aggregate`.
42
+
43
+ > ⚠️ **Nunca use `/v3/database/player`.** `player` é entidade nativa; `GET` dá 404 e `PUT` faz replace perdendo campos (`patterns.md` §10). → Use `/v3/player`.
44
+
45
+ > ⚠️ **Use `strict=true` em todo GET/escrita de campos tipados.** Consequência de omitir: `Date` é lido como número e regravado com tipo errado, quebrando queries por data (`patterns.md` §9).
46
+
47
+ ### 1.6 Documentos relacionados
48
+
49
+ > 📄 `datasource-funifier-docs/knowledge/guides/aggregates.md` — pipelines de aggregate e expressões de data
50
+ > 📄 `datasource-funifier-docs/knowledge/guides/java-libraries.md` §Jongo — ponteiro para este documento
51
+ > 📄 `datasource-funifier-docs/knowledge/modules/patterns.md` §9–§10 — strict mode, `q` vs `_filter`, Player nativo
9
52
 
10
53
  ---
11
54
 
12
- ## 1. Acesso via API Endpoint `/v3/database`
55
+ ## 2. Acesso via API REST (`/v3/database`)
56
+
57
+ Quando usar: ler/escrever coleções genéricas ou `__c` a partir do frontend ou de integrações.
58
+ Não usar quando: a coleção é uma entidade nativa (use o endpoint nativo) ou precisa de pipeline (use aggregate).
59
+ Depende de: token de autenticação com `database` no scope (`modules/security.md`).
60
+ Disponível em: API REST (cliente HTTP autenticado).
13
61
 
14
- ### 1.1 Listar Coleções Disponíveis
62
+ ### Descrição
15
63
 
16
- **Método:** GET
17
- **Endpoint:** `/v3/database/collections`
64
+ CRUD genérico sobre qualquer coleção via REST. Todas as operações usam **MongoDB** por trás.
18
65
 
19
- **Resposta:**
20
- ```json
21
- ["player", "action_log", "achievement", "challenge", "car__c", "email__c"]
66
+ ### Uso
67
+
68
+ **Listar coleções**
69
+ ```
70
+ GET /v3/database/collections
71
+ → ["player", "action_log", "achievement", "car__c", "email__c"]
22
72
  ```
23
73
 
24
- ### 1.2 Operações CRUD
74
+ **CRUD**
25
75
 
26
- | Operação | Método | Endpoint | Descrição |
27
- |----------|--------|----------|-----------|
28
- | Create | POST | `/v3/database/:collection` | Cria um novo registro |
29
- | Read | GET | `/v3/database/:collection` | Lista registros da coleção |
30
- | Update | PUT | `/v3/database/:collection` | Atualiza registro existente (via `_id`) |
31
- | Delete | DELETE | `/v3/database/:collection?q=...` | Remove registros com filtro |
32
- | Bulk Insert | POST | `/v3/database/:collection/bulk` | Cria/atualiza múltiplos registros |
76
+ | Operação | Método | Endpoint |
77
+ |----------|--------|----------|
78
+ | Create | POST | `/v3/database/:collection` |
79
+ | Read (lista) | GET | `/v3/database/:collection?q=...&strict=true` |
80
+ | Update | PUT | `/v3/database/:collection` (objeto completo) |
81
+ | Delete | DELETE | `/v3/database/:collection?q=...` |
82
+ | Bulk | POST | `/v3/database/:collection/bulk` |
33
83
 
34
- **Exemplo — Criar item na coleção `car__c`:**
35
84
  ```
36
85
  POST /v3/database/car__c
86
+ { "_id": "car001", "name": "Civic", "brand": "Honda", "price": 50000 }
37
87
  ```
38
- ```json
39
- {
40
- "_id": "car001",
41
- "name": "Civic",
42
- "brand": "Honda",
43
- "price": 50000
44
- }
88
+
89
+ **Filtrar** (param `q`, sintaxe Mongo — ver §1.5):
45
90
  ```
91
+ GET /v3/database/profile__c?strict=true&q=_id:'john'
92
+ ```
93
+ > A resposta de um `q=_id:` é um **array** — normalize pegando `[0]` (`patterns.md` §10).
46
94
 
47
- ### 1.3 Executar Aggregates
95
+ **Aggregate** (mecânica aqui; pipelines em `aggregates.md`):
96
+ ```
97
+ POST /v3/database/:collection/aggregate
98
+ [ { "$match": { "type": 0 } }, { "$group": { "_id": null, "total": { "$sum": "$total" } } } ]
99
+ ```
48
100
 
49
- **Método:** POST
50
- **Endpoint:** `/v3/database/:collection/aggregate`
101
+ ### Armadilhas conhecidas
51
102
 
52
- **Body (pipeline JSON):**
53
- ```json
54
- [
55
- { "$match": { "player": "john", "type": 0, "item": "xp" } },
56
- { "$group": { "_id": null, "totalXP": { "$sum": "$total" } } }
57
- ]
58
- ```
103
+ - **`_filter`/`_sort`/`_limit`** → ignorados (§1.5). Correção: `q` + aggregate `$sort`.
104
+ - **`PUT` parcial** → replace apaga campos (§1.5). Correção: objeto completo.
105
+ - **`POST` esperando busca** → cria documento (§1.5). Correção: `GET ?q=`.
59
106
 
60
- **Resultado:**
61
- ```json
62
- [{ "totalXP": 250 }]
63
- ```
107
+ ---
64
108
 
65
- **Operadores suportados:** `$match`, `$group`, `$sort`, `$limit`, `$lookup`, `$project`, `$unwind`, `$addFields`, `$count`
109
+ ## 3. Acesso via Código (Jongo)
66
110
 
67
- ### 1.4 Índices
111
+ Quando usar: ler/escrever coleções dentro de trigger, scheduler ou public endpoint.
112
+ Não usar quando: existir um manager para a operação → `java-managers.md`.
113
+ Depende de: `database` (param do trigger) ou `manager.getJongoConnection()`.
114
+ Disponível em: Todos (em Public Endpoint via `manager.getJongoConnection()` — `patterns.md` §6).
68
115
 
69
- | Operação | Método | Endpoint |
70
- |----------|--------|----------|
71
- | Listar | GET | `/v3/database/:collection/index` |
72
- | Criar | POST | `/v3/database/:collection/index` |
73
- | Excluir | DELETE | `/v3/database/:collection/index/:index_name` |
116
+ ### Descrição
74
117
 
75
- **Exemplo Criar índice:**
76
- ```json
77
- { "fuel": 1 }
118
+ Acesso direto ao MongoDB via driver Jongo. Em **triggers** use o param `database`; em **schedulers/public endpoints** (que não recebem `database`) use `manager.getJongoConnection()`. Ambos retornam o mesmo tipo de coleção.
119
+
120
+ ### Uso
121
+
122
+ ```java
123
+ // --- Obter coleção ---
124
+ database.getCollection("car__c"); // em trigger
125
+ manager.getJongoConnection().getCollection("car__c"); // em scheduler/endpoint
126
+
127
+ // --- SAVE (insere ou atualiza se _id existir) ---
128
+ database.getCollection("email__c").save(payload);
129
+
130
+ // --- FIND ---
131
+ Object one = database.getCollection("player").findOne("{_id: #}", "john").as(Map.class);
132
+ Iterable<Object> many = database.getCollection("action_log").find("{userId: #}", "john").as(Object.class);
133
+
134
+ // --- FIND com projeção ---
135
+ Object proj = database.getCollection("player")
136
+ .findOne("{_id: #}", id).projection("{name: 1, email: 1}").as(Object.class);
137
+
138
+ // --- COUNT ---
139
+ long total = database.getCollection("action_log").count("{userId: #}", "john");
140
+
141
+ // --- DELETE ---
142
+ database.getCollection("car__c").remove("{_id: #}", "car001");
143
+
144
+ // --- UPDATE (set parcial) ---
145
+ manager.getJongoConnection().getCollection("player").update("{_id: #}", playerId).with(setCmd);
78
146
  ```
79
147
 
148
+ > No Public Endpoint, escapar `$` de operadores Mongo (`patterns.md` §6):
149
+ > ```groovy
150
+ > def d = String.valueOf((char)0x24)
151
+ > def setCmd = '{"' + d + 'set": {"extra.plan.type": "premium"}}'
152
+ > ```
153
+
154
+ Para **aggregate via Jongo**, ver `aggregates.md` (a sintaxe `.aggregate(...).and(...)` é detalhada lá).
155
+
156
+ ### Armadilhas conhecidas
157
+
158
+ - **`manager.getJongoConnection()` esperado em trigger** → funciona, mas o param `database` é mais curto. Prefira `database` em triggers.
159
+ - **`update(...).with(...)` sem `$set`** → substitui o documento. Correção: usar `$set` para atualização parcial.
160
+
80
161
  ---
81
162
 
82
- ## 2. Acesso via Código Java (Triggers, Schedulers, Public Endpoints)
163
+ ## 4. Placeholders e Segurança
83
164
 
84
- Módulos que executam código Java têm acesso ao objeto `manager`, que provê conexão direta com o MongoDB através do driver Jongo.
165
+ Quando usar: sempre que a query envolver valores dinâmicos.
166
+ Não usar quando: —
167
+ Depende de: —
168
+ Disponível em: Todos.
85
169
 
86
- ### 2.1 Estrutura de Acesso
170
+ ### Descrição
87
171
 
88
- ```java
89
- manager.getJongoConnection().getCollection("nome_da_colecao").operacao(...);
90
- ```
172
+ O Jongo usa `#` como placeholder posicional para parâmetros seguros, evitando injeção. Os valores substituem os `#` na ordem.
91
173
 
92
- ### 2.2 Operações
174
+ ### Uso
93
175
 
94
- #### Salvar (Insert/Update)
95
176
  ```java
96
- manager.getJongoConnection()
97
- .getCollection("email__c")
98
- .save(payload);
99
- ```
177
+ // Um parâmetro
178
+ database.getCollection("player").findOne("{_id: #}", playerId).as(Object.class);
100
179
 
101
- #### Buscar (Find)
102
- ```java
103
- Object result = manager.getJongoConnection()
104
- .getCollection("player")
105
- .findOne("{_id: 'john'}")
106
- .as(Map.class);
180
+ // Múltiplos parâmetros (ordem importa)
181
+ database.getCollection("action_log")
182
+ .find("{userId: #, actionId: #}", "john", "sell").as(Object.class);
107
183
  ```
108
184
 
109
- #### Deletar
110
- ```java
111
- manager.getJongoConnection()
112
- .getCollection("car__c")
113
- .remove("{_id: 'car001'}");
114
- ```
185
+ ### Armadilhas conhecidas
115
186
 
116
- #### Aggregate
117
- ```java
118
- Iterable<Map> resultado = manager.getJongoConnection()
119
- .getCollection("action_log")
120
- .aggregate("[{ $match: { item: 'xp' } }, { $group: { _id: '$player', total: { $sum: '$total' } } }]")
121
- .as(Map.class);
122
- ```
187
+ - **Concatenar valores na string da query** → injeção. Correção: sempre `#` + argumento.
188
+ - **Número de `#` ≠ número de argumentos** → erro de parsing. Correção: alinhar quantidade e ordem.
123
189
 
124
190
  ---
125
191
 
126
- ## 3. Considerações de Segurança e Boas Práticas
192
+ ## 5. Índices
193
+
194
+ Quando usar: otimizar consultas frequentes numa coleção.
195
+ Não usar quando: a coleção é pequena ou a consulta é pontual.
196
+ Depende de: token autenticado.
197
+ Disponível em: API REST.
198
+
199
+ ### Descrição
200
+
201
+ Gestão de índices via REST.
202
+
203
+ ### Uso
204
+
205
+ | Operação | Método | Endpoint |
206
+ |----------|--------|----------|
207
+ | Listar | GET | `/v3/database/:collection/index` |
208
+ | Criar | POST | `/v3/database/:collection/index` |
209
+ | Excluir | DELETE | `/v3/database/:collection/index/:index_name` |
210
+
211
+ ```
212
+ POST /v3/database/car__c/index
213
+ { "fuel": 1 }
214
+ ```
215
+
216
+ ### Armadilhas conhecidas
127
217
 
128
- - As operações via API devem ser protegidas por **token de autenticação**
129
- - Endpoints públicos não requerem token — usar com cautela
130
- - Manipulação direta do banco afeta dados em **tempo real**
131
- - Sempre testar em **ambiente de homologação** antes de aplicar em produção
132
- - Coleções customizadas usam sufixo `__c` (ex: `car__c`, `email__c`)
218
+ - **Criar índice em ambiente de produção sob carga** impacto momentâneo. Correção: validar em homologação primeiro (`modules/staging.md`).