funifier-mcp 0.2.25 → 0.2.26
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/datasource-funifier-docs/knowledge/index.md +1 -1
- package/datasource-funifier-docs/knowledge/modules/folder.md +347 -68
- package/dist/core/api-client.d.ts +21 -1
- package/dist/core/api-client.d.ts.map +1 -1
- package/dist/core/api-client.js +154 -1
- package/dist/core/api-client.js.map +1 -1
- package/dist/core/constants.d.ts +14 -0
- package/dist/core/constants.d.ts.map +1 -1
- package/dist/core/constants.js +14 -0
- package/dist/core/constants.js.map +1 -1
- package/dist/core/types/Folder.d.ts +16 -0
- package/dist/core/types/Folder.d.ts.map +1 -0
- package/dist/core/types/Folder.js +3 -0
- package/dist/core/types/Folder.js.map +1 -0
- package/dist/core/types/FolderContent.d.ts +10 -0
- package/dist/core/types/FolderContent.d.ts.map +1 -0
- package/dist/core/types/FolderContent.js +3 -0
- package/dist/core/types/FolderContent.js.map +1 -0
- package/dist/core/types/FolderContentType.d.ts +10 -0
- package/dist/core/types/FolderContentType.d.ts.map +1 -0
- package/dist/core/types/FolderContentType.js +3 -0
- package/dist/core/types/FolderContentType.js.map +1 -0
- package/dist/core/types/FolderLog.d.ts +11 -0
- package/dist/core/types/FolderLog.d.ts.map +1 -0
- package/dist/core/types/FolderLog.js +3 -0
- package/dist/core/types/FolderLog.js.map +1 -0
- package/dist/core/types/index.d.ts +4 -0
- package/dist/core/types/index.d.ts.map +1 -1
- package/dist/core/types/index.js +4 -0
- package/dist/core/types/index.js.map +1 -1
- package/dist/mcp/bundle.js +101 -93
- package/dist/mcp/check-update.d.ts +2 -0
- package/dist/mcp/check-update.d.ts.map +1 -0
- package/dist/mcp/check-update.js +44 -0
- package/dist/mcp/check-update.js.map +1 -0
- package/dist/mcp/index.js +3 -0
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/tools/_char-guard.js +1 -1
- package/dist/mcp/tools/_char-guard.js.map +1 -1
- package/dist/mcp/tools/_fetch-current.d.ts +1 -1
- package/dist/mcp/tools/_fetch-current.d.ts.map +1 -1
- package/dist/mcp/tools/_fetch-current.js +12 -0
- package/dist/mcp/tools/_fetch-current.js.map +1 -1
- package/dist/mcp/tools/delete.d.ts.map +1 -1
- package/dist/mcp/tools/delete.js +20 -0
- package/dist/mcp/tools/delete.js.map +1 -1
- package/dist/mcp/tools/folder.d.ts +4 -0
- package/dist/mcp/tools/folder.d.ts.map +1 -0
- package/dist/mcp/tools/folder.js +58 -0
- package/dist/mcp/tools/folder.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/save.d.ts.map +1 -1
- package/dist/mcp/tools/save.js +12 -0
- package/dist/mcp/tools/save.js.map +1 -1
- package/dist/mcp/tools/save.test.js +191 -0
- package/dist/mcp/tools/save.test.js.map +1 -1
- package/package.json +1 -1
- package/datasource-funifier-docs/.search-index.json +0 -17318
- package/datasource-funifier-docs/.skills-map.json +0 -73
|
@@ -84,7 +84,7 @@ A Funifier funciona como um **backend de aplicações**. Independentemente do ti
|
|
|
84
84
|
| Módulo | Ficheiro | Descrição | Quando usar |
|
|
85
85
|
|--------|----------|-----------|-------------|
|
|
86
86
|
| Auth | `modules/auth.md` | Autenticação e tokens | Gerar tokens de acesso; configurar API keys; autenticação OAuth |
|
|
87
|
-
| Folder | `modules/folder.md` |
|
|
87
|
+
| 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
88
|
| Backup | `modules/backup.md` | Backup e restauração | Criar backups da gamificação; restaurar configurações |
|
|
89
89
|
| Compact | `modules/compact.md` | Compactação de dados | Compactar dados históricos para otimizar performance |
|
|
90
90
|
| Staging | `modules/staging.md` | Ambiente de homologação | Testar configurações em ambiente separado antes de produção |
|
|
@@ -1,111 +1,390 @@
|
|
|
1
|
-
# Folder (
|
|
1
|
+
# Folder (Trilha / Curso)
|
|
2
2
|
|
|
3
3
|
**Acesso Studio:** `/studio/folder`
|
|
4
|
-
**API
|
|
4
|
+
**API Base:** `/v3/folder`
|
|
5
5
|
|
|
6
6
|
## O que é
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Sistema de trilhas de aprendizagem e cursos. Permite criar hierarquias de pastas com conteúdos associados (quizzes, vídeos, textos, desafios), monitorar o progresso de cada jogador em cada nível da hierarquia, e desbloquear conteúdo condicionalmente com base no progresso anterior.
|
|
9
9
|
|
|
10
10
|
## Quando usar
|
|
11
11
|
|
|
12
|
-
- Para estruturar cursos
|
|
13
|
-
- Para criar trilhas de capacitação
|
|
14
|
-
- Para acompanhar progresso em
|
|
15
|
-
- Para organizar conteúdos em hierarquias
|
|
12
|
+
- Para estruturar cursos com módulos e aulas
|
|
13
|
+
- Para criar trilhas de capacitação/treinamento
|
|
14
|
+
- Para acompanhar o progresso individual de jogadores em jornadas
|
|
15
|
+
- Para organizar conteúdos em hierarquias com controle de ordem e desbloqueio
|
|
16
16
|
|
|
17
|
-
##
|
|
17
|
+
## Collections MongoDB
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
| Collection | Descrição |
|
|
20
|
+
|------------|-----------|
|
|
21
|
+
| `folder` | Estrutura de pastas (raiz e sub-pastas) |
|
|
22
|
+
| `folder_content` | Vínculo entre pasta e item de conteúdo |
|
|
23
|
+
| `folder_content_type` | Schema de um tipo de conteúdo (video, text, quiz…) |
|
|
24
|
+
| `folder_log` | Histórico de progresso do jogador por item |
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Entidades
|
|
29
|
+
|
|
30
|
+
### Folder
|
|
31
|
+
|
|
32
|
+
Representa uma pasta ou módulo da trilha.
|
|
33
|
+
|
|
34
|
+
| Campo | Tipo | Obrigatório | Descrição |
|
|
35
|
+
|-------|------|-------------|-----------|
|
|
36
|
+
| `_id` | string | Não (auto) | ID único |
|
|
37
|
+
| `title` | string | **Sim** | Nome da pasta |
|
|
38
|
+
| `type` | string | Não | Categoria da pasta (livre) |
|
|
39
|
+
| `parent` | string | Não | ID da pasta pai (ausente = raiz) |
|
|
40
|
+
| `position` | number | Não (default 0) | Ordem de exibição entre irmãos |
|
|
41
|
+
| `active` | boolean | Não (default true) | false = oculta da árvore |
|
|
42
|
+
| `unlock_policy` | UnlockPolicy | Não | Regra de desbloqueio condicional |
|
|
43
|
+
| `extra` | object | Não | Campos livres adicionais |
|
|
44
|
+
|
|
45
|
+
### UnlockPolicy
|
|
46
|
+
|
|
47
|
+
Define quando uma pasta fica disponível para o jogador.
|
|
48
|
+
|
|
49
|
+
| Campo | Tipo | Valores | Descrição |
|
|
50
|
+
|-------|------|---------|-----------|
|
|
51
|
+
| `type` | string | `"progress"` | Único tipo suportado |
|
|
52
|
+
| `folder_ref` | string | `"prev"` ou ID | `"prev"` = pasta irmã anterior; ID = pasta específica |
|
|
53
|
+
| `min_percent` | number | 0–100 | Percentual mínimo exigido |
|
|
54
|
+
|
|
55
|
+
**Herança:** o servidor sobe na árvore até encontrar um `unlock_policy`. Se uma pasta não tem policy própria, herda do pai.
|
|
56
|
+
|
|
57
|
+
### FolderContent
|
|
58
|
+
|
|
59
|
+
Vínculo entre uma pasta e um item de conteúdo.
|
|
60
|
+
|
|
61
|
+
| Campo | Tipo | Obrigatório | Descrição |
|
|
62
|
+
|-------|------|-------------|-----------|
|
|
63
|
+
| `_id` | string | Não (auto) | ID único |
|
|
64
|
+
| `type` | string | **Sim** | `_id` do `FolderContentType` |
|
|
65
|
+
| `content` | string | Condicional | `_id` do item real (apenas quando `input=repository`) |
|
|
66
|
+
| `parent` | string | **Sim** | `_id` da pasta pai |
|
|
67
|
+
| `title` | string | Não | Auto-populado do item real se omitido |
|
|
68
|
+
| `extra` | object | Não | Campos livres |
|
|
69
|
+
| `position` | number | Não (default 0) | Ordem de exibição |
|
|
70
|
+
|
|
71
|
+
### FolderContentType
|
|
72
|
+
|
|
73
|
+
Define o schema de um tipo de conteúdo.
|
|
74
|
+
|
|
75
|
+
| Campo | Tipo | Obrigatório | Descrição |
|
|
76
|
+
|-------|------|-------------|-----------|
|
|
77
|
+
| `_id` | string | **Sim** | Identificador (ex: `"video"`, `"text"`, `"quiz"`) |
|
|
78
|
+
| `entity` | string | **Sim** | Nome da coleção MongoDB onde os dados reais ficam |
|
|
79
|
+
| `input` | string | **Sim** | `"repository"` ou `"formulary"` (ver abaixo) |
|
|
80
|
+
| `title` | string | Não | Label de exibição |
|
|
81
|
+
| `image` | string | Não | URL de ícone |
|
|
82
|
+
| `slug` | string | Não | Slug para URL |
|
|
83
|
+
| `attributes` | array | Não | Campos do formulário (quando `input=formulary`) |
|
|
84
|
+
|
|
85
|
+
**`input=repository`:** o conteúdo referencia um item já existente em outra coleção via `content`.
|
|
86
|
+
**`input=formulary`:** o conteúdo cria um novo item inline na coleção `entity`. ⚠️ Ao deletar o `FolderContent`, o dado real também é deletado.
|
|
87
|
+
|
|
88
|
+
### FolderLog
|
|
89
|
+
|
|
90
|
+
Registo de progresso de um jogador em um conteúdo.
|
|
91
|
+
|
|
92
|
+
| Campo | Tipo | Obrigatório | Descrição |
|
|
93
|
+
|-------|------|-------------|-----------|
|
|
94
|
+
| `_id` | string | Não (auto) | ID único |
|
|
95
|
+
| `item` | string | **Sim** | `_id` do `FolderContent` |
|
|
96
|
+
| `player` | string | **Sim** | ID do jogador |
|
|
97
|
+
| `status` | string | Não | `"done"` para concluído |
|
|
98
|
+
| `percent` | number | Não | 0.0–100.0 |
|
|
99
|
+
| `started` | Date | Não (auto) | Preenchido automaticamente |
|
|
100
|
+
| `finished` | Date | Não (auto) | Preenchido quando concluído |
|
|
101
|
+
| `extra` | object | Não | Campos livres (ex: `date`) |
|
|
102
|
+
|
|
103
|
+
### Inside (resposta de inside/progress)
|
|
104
|
+
|
|
105
|
+
Nó da árvore retornado por `POST /v3/folder/inside` e `POST /v3/folder/progress`.
|
|
106
|
+
|
|
107
|
+
| Campo | Tipo | Descrição |
|
|
108
|
+
|-------|------|-----------|
|
|
109
|
+
| `_id` | string | ID do nó |
|
|
110
|
+
| `folder` | boolean | `true`=pasta, `false`=conteúdo |
|
|
111
|
+
| `title` | string | Título |
|
|
112
|
+
| `type` | string | Tipo |
|
|
113
|
+
| `content` | string | ID do item real (apenas em conteúdos) |
|
|
114
|
+
| `items` | Inside[] | Filhos (sub-pastas e conteúdos), ordenados por `position` |
|
|
115
|
+
| `player` | string | ID do jogador (apenas em `progress`) |
|
|
116
|
+
| `total` | number | Total de conteúdos na sub-árvore (apenas em `progress`) |
|
|
117
|
+
| `done` | number | Conteúdos concluídos (apenas em `progress`) |
|
|
118
|
+
| `percent` | number | % de conclusão (apenas em `progress`) |
|
|
119
|
+
| `time` | Date | Data da última conclusão na sub-árvore |
|
|
120
|
+
| `is_unlocked` | boolean | Se a pasta está desbloqueada (null para conteúdos) |
|
|
121
|
+
|
|
122
|
+
---
|
|
24
123
|
|
|
25
124
|
## API Endpoints
|
|
26
125
|
|
|
27
|
-
###
|
|
28
|
-
**Método:** GET
|
|
29
|
-
**Endpoint:** `/v3/database/folder`
|
|
126
|
+
### Folder
|
|
30
127
|
|
|
31
|
-
|
|
32
|
-
**
|
|
33
|
-
|
|
128
|
+
#### Criar Pasta
|
|
129
|
+
**POST** `/v3/folder`
|
|
130
|
+
```json
|
|
131
|
+
{ "title": "Módulo 1", "parent": "raiz_id", "position": 0 }
|
|
132
|
+
```
|
|
133
|
+
Resposta: `Folder` criado com `_id` gerado.
|
|
134
|
+
|
|
135
|
+
#### Buscar Pasta
|
|
136
|
+
**GET** `/v3/folder/:id`
|
|
137
|
+
|
|
138
|
+
#### Listar Pastas
|
|
139
|
+
**GET** `/v3/database/folder`
|
|
140
|
+
|
|
141
|
+
#### Deletar Pasta ⚠️ CASCATA
|
|
142
|
+
**DELETE** `/v3/folder/:id`
|
|
143
|
+
|
|
144
|
+
> Remove recursivamente: sub-pastas, folder_content, folder_log, e — se `ContentType.input = "formulary"` — os dados reais na coleção `entity`. **Irreversível.**
|
|
145
|
+
|
|
146
|
+
#### Deletar por Query
|
|
147
|
+
**DELETE** `/v3/folder?q=parent:"<id>"`
|
|
34
148
|
|
|
35
|
-
|
|
149
|
+
#### Reordenar Pasta
|
|
150
|
+
**GET** `/v3/folder/:id/move?direction=up` ou `direction=down`
|
|
151
|
+
|
|
152
|
+
#### Árvore Completa
|
|
153
|
+
**POST** `/v3/folder/inside`
|
|
154
|
+
```json
|
|
155
|
+
{ "folder": "<id>" }
|
|
156
|
+
```
|
|
157
|
+
Retorna árvore `Inside` completa (pastas + conteúdos), ordenada por `position`.
|
|
158
|
+
|
|
159
|
+
#### Progresso do Jogador
|
|
160
|
+
**POST** `/v3/folder/progress`
|
|
161
|
+
```json
|
|
162
|
+
{ "folder": "<id>", "player": "<playerId>" }
|
|
163
|
+
```
|
|
164
|
+
Retorna árvore `Inside` com `total`, `done`, `percent`, `time`, `is_unlocked` por nó. Também **dispara o trigger `folder_progress`**.
|
|
165
|
+
|
|
166
|
+
#### Breadcrumb
|
|
167
|
+
**POST** `/v3/folder/breadcrumb`
|
|
168
|
+
```json
|
|
169
|
+
{ "folder": "<id>" }
|
|
170
|
+
```
|
|
171
|
+
Retorna array de `Folder` do raiz até o nó: `[root, ..., target]`.
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
### Folder Content
|
|
176
|
+
|
|
177
|
+
#### Adicionar Conteúdo
|
|
178
|
+
**POST** `/v3/folder/content`
|
|
179
|
+
```json
|
|
180
|
+
{ "type": "video", "content": "<video_id>", "parent": "<folder_id>" }
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
#### Buscar Conteúdo
|
|
184
|
+
**GET** `/v3/folder/content/:id`
|
|
185
|
+
|
|
186
|
+
#### Buscar Dados Reais do Conteúdo
|
|
187
|
+
**GET** `/v3/folder/content/:id/data`
|
|
188
|
+
Retorna o objeto real da coleção `entity` associada ao `FolderContentType`.
|
|
189
|
+
|
|
190
|
+
#### Listar Conteúdos (com aggregate)
|
|
191
|
+
**POST** `/v3/folder/content/aggregate?folder=<id>&cascade=true&append_data=true`
|
|
192
|
+
Body: pipeline MongoDB opcional (array).
|
|
193
|
+
- `cascade=true`: inclui conteúdos de sub-pastas
|
|
194
|
+
- `append_data=true`: adiciona campo `data` com o objeto real de cada conteúdo
|
|
195
|
+
|
|
196
|
+
#### Listar Conteúdos Diretos
|
|
197
|
+
**GET** `/v3/database/folder_content`
|
|
198
|
+
|
|
199
|
+
#### Reordenar Conteúdo
|
|
200
|
+
**GET** `/v3/folder/content/:id/move?direction=up` ou `direction=down`
|
|
201
|
+
|
|
202
|
+
#### Deletar Conteúdo
|
|
203
|
+
**DELETE** `/v3/folder/content/:id`
|
|
204
|
+
> Se `ContentType.input = "formulary"`, também deleta o dado real. Deleta todos os `folder_log` do conteúdo.
|
|
205
|
+
|
|
206
|
+
#### Deletar por Query
|
|
207
|
+
**DELETE** `/v3/folder/content?q=parent:"<id>"`
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
### Folder Content Type
|
|
212
|
+
|
|
213
|
+
#### Criar / Atualizar Tipo
|
|
214
|
+
**PUT** `/v3/database/folder_content_type`
|
|
36
215
|
```json
|
|
37
216
|
{
|
|
38
|
-
"
|
|
39
|
-
"
|
|
217
|
+
"_id": "video",
|
|
218
|
+
"entity": "video__c",
|
|
219
|
+
"input": "repository",
|
|
220
|
+
"title": "Vídeo"
|
|
40
221
|
}
|
|
41
222
|
```
|
|
42
223
|
|
|
43
|
-
|
|
44
|
-
**
|
|
45
|
-
|
|
224
|
+
#### Listar Tipos
|
|
225
|
+
**GET** `/v3/database/folder_content_type`
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
### Folder Log
|
|
230
|
+
|
|
231
|
+
#### Registrar Progresso ⚠️ Via endpoint REST (não via database direto)
|
|
232
|
+
**POST** `/v3/folder/log`
|
|
233
|
+
```json
|
|
234
|
+
{ "item": "<content_id>", "player": "player123", "status": "done" }
|
|
235
|
+
```
|
|
236
|
+
Ou com percentual parcial:
|
|
237
|
+
```json
|
|
238
|
+
{ "item": "<content_id>", "player": "player123", "percent": 60.0 }
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
> **Importante:** use sempre `/v3/folder/log` para registrar progresso, nunca insira direto na collection `folder_log`. O endpoint contém lógica de negócio crítica (idempotência, cálculo de progresso, triggers).
|
|
242
|
+
|
|
243
|
+
#### Buscar Log
|
|
244
|
+
**GET** `/v3/folder/log/:id`
|
|
245
|
+
|
|
246
|
+
#### Deletar Log
|
|
247
|
+
**DELETE** `/v3/folder/log/:id`
|
|
248
|
+
Dispara `BEFORE_DELETE` e `AFTER_DELETE` em triggers de `folder_log`.
|
|
249
|
+
|
|
250
|
+
#### Listar Logs (consulta)
|
|
251
|
+
**GET** `/v3/database/folder_log`
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## Comportamentos Críticos de Segurança
|
|
256
|
+
|
|
257
|
+
### 1. DELETE em Cascata (deleteFolder)
|
|
258
|
+
`DELETE /v3/folder/:id` é uma operação destrutiva em cascata:
|
|
259
|
+
1. Deleta todos os sub-folders recursivamente
|
|
260
|
+
2. Deleta todos os `folder_content` da pasta
|
|
261
|
+
3. Deleta todos os `folder_log` dos conteúdos
|
|
262
|
+
4. Se `FolderContentType.input = "formulary"`: deleta o dado real na coleção `entity`
|
|
263
|
+
|
|
264
|
+
**⚠️ Sempre confirmar com o usuário antes de executar. Irreversível.**
|
|
265
|
+
|
|
266
|
+
### 2. insertLog é Idempotente
|
|
267
|
+
O servidor busca log existente por `(player, item)` sem `finished`. Se encontrado, atualiza em vez de criar novo. Nunca gera duplicata para um conteúdo em andamento.
|
|
46
268
|
|
|
47
|
-
###
|
|
48
|
-
|
|
49
|
-
|
|
269
|
+
### 3. Auto-Status
|
|
270
|
+
- `status: "done"` → `percent = 100.0` + `finished = now` (automático)
|
|
271
|
+
- `percent >= 100` → `status = "done"` + `finished = now` (automático)
|
|
50
272
|
|
|
51
|
-
|
|
273
|
+
### 4. Herança de unlock_policy
|
|
274
|
+
O servidor percorre a árvore para cima até encontrar um `unlock_policy`. Pastas sem policy própria herdam do pai.
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## Trigger Events
|
|
279
|
+
|
|
280
|
+
### Coleção `folder_log`
|
|
281
|
+
| Evento | Quando |
|
|
282
|
+
|--------|--------|
|
|
283
|
+
| `BEFORE_CREATE` | Antes de inserir/atualizar log |
|
|
284
|
+
| `AFTER_CREATE` | Após inserir/atualizar log |
|
|
285
|
+
| `BEFORE_DELETE` | Antes de deletar log |
|
|
286
|
+
| `AFTER_DELETE` | Após deletar log |
|
|
287
|
+
|
|
288
|
+
### Coleção `folder_progress` (evento: `AFTER_CREATE`)
|
|
289
|
+
Disparado para **cada pasta no breadcrumb** (do mais próximo ao raiz) sempre que o progresso aumenta. Payload:
|
|
52
290
|
```json
|
|
53
291
|
{
|
|
54
|
-
"
|
|
292
|
+
"_id": "<folderId>",
|
|
293
|
+
"player": "<playerId>",
|
|
294
|
+
"folder": { "_id": "...", "title": "Módulo 1" },
|
|
295
|
+
"progress": { "percent": 60.0, "done": 3, "total": 5 },
|
|
296
|
+
"previous_percent": 40.0,
|
|
297
|
+
"current_percent": 60.0,
|
|
298
|
+
"time": "<timestamp>"
|
|
55
299
|
}
|
|
56
300
|
```
|
|
57
301
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## Uso com MCP
|
|
305
|
+
|
|
306
|
+
| Operação | Tool | Parâmetros |
|
|
307
|
+
|---------|------|-----------|
|
|
308
|
+
| Criar/atualizar pasta | `funifier_save` | `type: "folder"` |
|
|
309
|
+
| Deletar pasta (cascata) | `funifier_delete` | `type: "folder"` |
|
|
310
|
+
| Adicionar conteúdo | `funifier_save` | `type: "folder-content"` |
|
|
311
|
+
| Deletar conteúdo | `funifier_delete` | `type: "folder-content"` |
|
|
312
|
+
| Definir tipo de conteúdo | `funifier_save` | `type: "folder-content-type"` |
|
|
313
|
+
| Registrar progresso | `funifier_save` | `type: "folder-log"` |
|
|
314
|
+
| Deletar log | `funifier_delete` | `type: "folder-log"` |
|
|
315
|
+
| Ver árvore completa | `funifier_folder` | `operation: "inside"` |
|
|
316
|
+
| Ver progresso do jogador | `funifier_folder` | `operation: "progress"` |
|
|
317
|
+
| Ver breadcrumb | `funifier_folder` | `operation: "breadcrumb"` |
|
|
318
|
+
| Consultar logs/conteúdos | `funifier_database` | `collection: "folder_log"` etc. |
|
|
61
319
|
|
|
62
|
-
|
|
63
|
-
**Método:** PUT
|
|
64
|
-
**Endpoint:** `/v3/database/folder_content_type`
|
|
320
|
+
---
|
|
65
321
|
|
|
66
|
-
|
|
322
|
+
## Exemplo Completo: Criar Trilha de Vendas
|
|
323
|
+
|
|
324
|
+
### 1. Criar pasta raiz
|
|
325
|
+
```json
|
|
326
|
+
funifier_save type=folder
|
|
327
|
+
{ "title": "Trilha de Vendas" }
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### 2. Criar módulo dentro da trilha
|
|
67
331
|
```json
|
|
332
|
+
funifier_save type=folder
|
|
333
|
+
{ "title": "Módulo 1 - Prospecção", "parent": "<trilha_id>", "position": 0 }
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### 3. Criar segundo módulo com unlock_policy
|
|
337
|
+
```json
|
|
338
|
+
funifier_save type=folder
|
|
68
339
|
{
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
|
|
73
|
-
{ "name": "content", "type": "text", "title": "Content" }
|
|
74
|
-
],
|
|
75
|
-
"title": "Text",
|
|
76
|
-
"entity": "text__c"
|
|
340
|
+
"title": "Módulo 2 - Fechamento",
|
|
341
|
+
"parent": "<trilha_id>",
|
|
342
|
+
"position": 1,
|
|
343
|
+
"unlock_policy": { "type": "progress", "folder_ref": "prev", "min_percent": 80 }
|
|
77
344
|
}
|
|
78
345
|
```
|
|
79
346
|
|
|
80
|
-
|
|
347
|
+
### 4. Definir tipo de conteúdo
|
|
348
|
+
```json
|
|
349
|
+
funifier_save type=folder-content-type
|
|
350
|
+
{ "_id": "video", "entity": "video__c", "input": "repository", "title": "Vídeo" }
|
|
351
|
+
```
|
|
81
352
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
-
|
|
85
|
-
|
|
353
|
+
### 5. Adicionar conteúdo ao módulo
|
|
354
|
+
```json
|
|
355
|
+
funifier_save type=folder-content
|
|
356
|
+
{ "type": "video", "content": "<video_id>", "parent": "<modulo1_id>" }
|
|
357
|
+
```
|
|
86
358
|
|
|
87
|
-
|
|
359
|
+
### 6. Registrar progresso do jogador
|
|
360
|
+
```json
|
|
361
|
+
funifier_save type=folder-log
|
|
362
|
+
{ "item": "<content_id>", "player": "player123", "status": "done" }
|
|
363
|
+
```
|
|
88
364
|
|
|
89
|
-
|
|
365
|
+
### 7. Consultar progresso completo
|
|
366
|
+
```json
|
|
367
|
+
funifier_folder operation=progress
|
|
368
|
+
{ "folder": "<trilha_id>", "player": "player123" }
|
|
369
|
+
```
|
|
90
370
|
|
|
91
|
-
|
|
92
|
-
- Registrar action logs ao progredir (aciona técnicas de jogos)
|
|
93
|
-
- Criar desafios vinculados à completude de um folder (ex: "Complete o curso para ganhar 500 XP")
|
|
371
|
+
---
|
|
94
372
|
|
|
95
373
|
## Integração com Outras Técnicas
|
|
96
374
|
|
|
97
375
|
| Técnica | Integração |
|
|
98
376
|
|---------|-----------|
|
|
99
|
-
| **Challenge** |
|
|
100
|
-
| **
|
|
101
|
-
| **
|
|
102
|
-
| **
|
|
103
|
-
|
|
104
|
-
##
|
|
105
|
-
|
|
106
|
-
- [ ]
|
|
107
|
-
- [ ]
|
|
108
|
-
- [ ]
|
|
109
|
-
- [ ]
|
|
110
|
-
- [ ]
|
|
111
|
-
- [ ]
|
|
377
|
+
| **Challenge** | Criar desafio vinculado à completion do folder (rule: `folder_progress` com `percent >= 100`) |
|
|
378
|
+
| **Point** | Conceder pontos via trigger `folder_progress` quando `current_percent >= 100` |
|
|
379
|
+
| **Achievement** | Conquista ao completar 100% de um folder |
|
|
380
|
+
| **Quiz** | Quiz como `FolderContent` dentro de um folder (via `folder-content-type` com `input=repository`) |
|
|
381
|
+
|
|
382
|
+
## Checklist de Configuração
|
|
383
|
+
|
|
384
|
+
- [ ] Criar estrutura de pastas (raiz + sub-pastas com position)
|
|
385
|
+
- [ ] Definir FolderContentTypes necessários
|
|
386
|
+
- [ ] Adicionar FolderContent às pastas
|
|
387
|
+
- [ ] Configurar unlock_policy nas pastas que precisam de desbloqueio condicional
|
|
388
|
+
- [ ] Verificar árvore com `funifier_folder operation=inside`
|
|
389
|
+
- [ ] Testar progresso com `funifier_folder operation=progress`
|
|
390
|
+
- [ ] Configurar triggers em `folder_log` ou `folder_progress` se necessário
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FunifierConfig } from "./config";
|
|
2
|
-
import { Trigger, Scheduler, Aggregate, Widget, CustomPage, PublicEndpoint, ChallengeAggregate, AiKnowledge, AuthModule, Websocket, Action, Challenge, Point, Level, LevelConfig, Leaderboard, LeaderboardEntry, Quiz, Question, VirtualGoodCatalog, VirtualGoodItem } from "./types";
|
|
2
|
+
import { Trigger, Scheduler, Aggregate, Widget, CustomPage, PublicEndpoint, ChallengeAggregate, AiKnowledge, AuthModule, Websocket, Action, Challenge, Point, Level, LevelConfig, Leaderboard, LeaderboardEntry, Quiz, Question, VirtualGoodCatalog, VirtualGoodItem, Folder, FolderContent, FolderContentType, FolderLog } from "./types";
|
|
3
3
|
export declare function serializeToFunifierQuery(filter: Record<string, any>): string;
|
|
4
4
|
export declare function createAPIClient(config: FunifierConfig): {
|
|
5
5
|
listTriggers: () => Promise<Trigger[]>;
|
|
@@ -63,6 +63,20 @@ export declare function createAPIClient(config: FunifierConfig): {
|
|
|
63
63
|
_id: string;
|
|
64
64
|
title: string;
|
|
65
65
|
}[]>;
|
|
66
|
+
listFolders: () => Promise<Folder[]>;
|
|
67
|
+
saveFolder: (payload: Folder) => Promise<Folder>;
|
|
68
|
+
deleteFolder: (id: string) => Promise<any>;
|
|
69
|
+
listFolderContents: () => Promise<FolderContent[]>;
|
|
70
|
+
saveFolderContent: (payload: FolderContent) => Promise<FolderContent>;
|
|
71
|
+
deleteFolderContent: (id: string) => Promise<any>;
|
|
72
|
+
listFolderContentTypes: () => Promise<FolderContentType[]>;
|
|
73
|
+
saveFolderContentType: (payload: FolderContentType) => Promise<FolderContentType>;
|
|
74
|
+
listFolderLogs: () => Promise<FolderLog[]>;
|
|
75
|
+
saveFolderLog: (payload: FolderLog) => Promise<FolderLog>;
|
|
76
|
+
deleteFolderLog: (id: string) => Promise<any>;
|
|
77
|
+
folderInside: (folderId: string) => Promise<any>;
|
|
78
|
+
folderProgress: (folderId: string, playerId: string) => Promise<any>;
|
|
79
|
+
folderBreadcrumb: (folderId: string) => Promise<any>;
|
|
66
80
|
evaluateCron: (expression: string) => Promise<{
|
|
67
81
|
valid: boolean;
|
|
68
82
|
expression: string;
|
|
@@ -106,6 +120,12 @@ export declare function createAPIClient(config: FunifierConfig): {
|
|
|
106
120
|
saveVirtualGoodCatalog: (payload: VirtualGoodCatalog) => Promise<VirtualGoodCatalog>;
|
|
107
121
|
listVirtualGoodItems: () => Promise<VirtualGoodItem[]>;
|
|
108
122
|
saveVirtualGoodItem: (payload: VirtualGoodItem) => Promise<VirtualGoodItem>;
|
|
123
|
+
deleteVirtualGoodCatalog: (id: string) => Promise<{
|
|
124
|
+
success: boolean;
|
|
125
|
+
}>;
|
|
126
|
+
deleteVirtualGoodItem: (id: string) => Promise<{
|
|
127
|
+
success: boolean;
|
|
128
|
+
}>;
|
|
109
129
|
getGamification: (apiKey: string) => Promise<{
|
|
110
130
|
_id: string;
|
|
111
131
|
name: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../src/core/api-client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EACL,OAAO,EACP,SAAS,EACT,SAAS,EACT,MAAM,EACN,UAAU,EACV,cAAc,EACd,kBAAkB,EAClB,WAAW,EACX,UAAU,EACV,SAAS,EACT,MAAM,EACN,SAAS,EACT,KAAK,EACL,KAAK,EACL,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,IAAI,EACJ,QAAQ,EACR,kBAAkB,EAClB,eAAe,
|
|
1
|
+
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../src/core/api-client.ts"],"names":[],"mappings":"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"}
|