funifier-mcp 0.1.0 → 0.2.0
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/README.md +182 -351
- package/datasource-funifier-docs/knowledge/guides/aggregates.md +152 -0
- package/datasource-funifier-docs/knowledge/guides/database-access.md +132 -0
- package/datasource-funifier-docs/knowledge/guides/java-entities.md +373 -0
- package/datasource-funifier-docs/knowledge/guides/java-libraries.md +330 -0
- package/datasource-funifier-docs/knowledge/guides/java-managers.md +509 -0
- package/datasource-funifier-docs/knowledge/guides/triggers-guide.md +271 -0
- package/datasource-funifier-docs/knowledge/index.md +121 -0
- package/datasource-funifier-docs/knowledge/modules/achievement.md +46 -0
- package/datasource-funifier-docs/knowledge/modules/action-log.md +88 -0
- package/datasource-funifier-docs/knowledge/modules/action.md +80 -0
- package/datasource-funifier-docs/knowledge/modules/auth.md +104 -0
- package/datasource-funifier-docs/knowledge/modules/avatar.md +28 -0
- package/datasource-funifier-docs/knowledge/modules/backup.md +40 -0
- package/datasource-funifier-docs/knowledge/modules/challenge.md +91 -0
- package/datasource-funifier-docs/knowledge/modules/compact.md +40 -0
- package/datasource-funifier-docs/knowledge/modules/competition.md +149 -0
- package/datasource-funifier-docs/knowledge/modules/crossword.md +41 -0
- package/datasource-funifier-docs/knowledge/modules/csv-data.md +30 -0
- package/datasource-funifier-docs/knowledge/modules/custom-object.md +53 -0
- package/datasource-funifier-docs/knowledge/modules/database.md +241 -0
- package/datasource-funifier-docs/knowledge/modules/folder.md +111 -0
- package/datasource-funifier-docs/knowledge/modules/kpi-formulas.md +23 -0
- package/datasource-funifier-docs/knowledge/modules/lastmile.md +45 -0
- package/datasource-funifier-docs/knowledge/modules/leaderboard.md +98 -0
- package/datasource-funifier-docs/knowledge/modules/level.md +83 -0
- package/datasource-funifier-docs/knowledge/modules/lottery.md +112 -0
- package/datasource-funifier-docs/knowledge/modules/marketplace.md +27 -0
- package/datasource-funifier-docs/knowledge/modules/mystery.md +82 -0
- package/datasource-funifier-docs/knowledge/modules/notification.md +40 -0
- package/datasource-funifier-docs/knowledge/modules/patterns.md +1096 -0
- package/datasource-funifier-docs/knowledge/modules/player.md +101 -0
- package/datasource-funifier-docs/knowledge/modules/point.md +67 -0
- package/datasource-funifier-docs/knowledge/modules/public.md +253 -0
- package/datasource-funifier-docs/knowledge/modules/question.md +136 -0
- package/datasource-funifier-docs/knowledge/modules/quiz.md +163 -0
- package/datasource-funifier-docs/knowledge/modules/scheduler.md +58 -0
- package/datasource-funifier-docs/knowledge/modules/security.md +169 -0
- package/datasource-funifier-docs/knowledge/modules/staging.md +28 -0
- package/datasource-funifier-docs/knowledge/modules/static-repo.md +41 -0
- package/datasource-funifier-docs/knowledge/modules/story.md +42 -0
- package/datasource-funifier-docs/knowledge/modules/studio-page.md +180 -0
- package/datasource-funifier-docs/knowledge/modules/swap.md +132 -0
- package/datasource-funifier-docs/knowledge/modules/team.md +75 -0
- package/datasource-funifier-docs/knowledge/modules/trigger.md +189 -0
- package/datasource-funifier-docs/knowledge/modules/upload.md +155 -0
- package/datasource-funifier-docs/knowledge/modules/virtual-good.md +99 -0
- package/datasource-funifier-docs/knowledge/modules/webhook.md +41 -0
- package/datasource-funifier-docs/knowledge/modules/websocket.md +41 -0
- package/datasource-funifier-docs/knowledge/modules/widget.md +42 -0
- package/datasource-funifier-docs/process-gtm-saas.md +143 -0
- package/datasource-funifier-docs/process-instagram.md +88 -0
- package/datasource-funifier-docs/process.md +1826 -0
- package/datasource-funifier-docs/readme.md +132 -0
- package/dist/cli/config-writers.d.ts +15 -0
- package/dist/cli/config-writers.d.ts.map +1 -0
- package/dist/cli/config-writers.js +55 -0
- package/dist/cli/config-writers.js.map +1 -0
- package/dist/cli/config-writers.test.d.ts +2 -0
- package/dist/cli/config-writers.test.d.ts.map +1 -0
- package/dist/cli/config-writers.test.js +55 -0
- package/dist/cli/config-writers.test.js.map +1 -0
- package/dist/cli/copy.d.ts +6 -0
- package/dist/cli/copy.d.ts.map +1 -0
- package/dist/cli/copy.js +63 -0
- package/dist/cli/copy.js.map +1 -0
- package/dist/cli/copy.test.d.ts +2 -0
- package/dist/cli/copy.test.d.ts.map +1 -0
- package/dist/cli/copy.test.js +94 -0
- package/dist/cli/copy.test.js.map +1 -0
- package/dist/cli/init.d.ts +2 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +167 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/paths.d.ts +7 -0
- package/dist/cli/paths.d.ts.map +1 -0
- package/dist/cli/paths.js +62 -0
- package/dist/cli/paths.js.map +1 -0
- package/dist/cli/paths.test.d.ts +2 -0
- package/dist/cli/paths.test.d.ts.map +1 -0
- package/dist/cli/paths.test.js +50 -0
- package/dist/cli/paths.test.js.map +1 -0
- package/dist/cli/platforms.d.ts +22 -0
- package/dist/cli/platforms.d.ts.map +1 -0
- package/dist/cli/platforms.js +50 -0
- package/dist/cli/platforms.js.map +1 -0
- package/dist/cli/prompts.d.ts +7 -0
- package/dist/cli/prompts.d.ts.map +1 -0
- package/dist/cli/prompts.js +49 -0
- package/dist/cli/prompts.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/bundle.js +94 -49
- package/dist/mcp/index.js +18 -1
- package/dist/mcp/index.js.map +1 -1
- package/package.json +4 -2
- package/skills/funifier-create-action/SKILL.md +86 -86
- package/skills/funifier-create-aggregate/SKILL.md +39 -0
- package/skills/funifier-create-challenge/SKILL.md +87 -87
- package/skills/funifier-create-custom-page/SKILL.md +39 -0
- package/skills/funifier-create-leaderboard/SKILL.md +87 -87
- package/skills/funifier-create-level/SKILL.md +86 -86
- package/skills/funifier-create-point/SKILL.md +86 -86
- package/skills/funifier-create-quiz/SKILL.md +86 -86
- package/skills/funifier-create-scheduler/SKILL.md +39 -0
- package/skills/funifier-create-trigger/SKILL.md +39 -0
- package/skills/funifier-create-virtual-good/SKILL.md +86 -86
- package/skills/funifier-debug/SKILL.md +90 -90
- package/skills/funifier-help/SKILL.md +85 -85
- package/skills/funifier-implement-frontend/SKILL.md +89 -89
- package/skills/funifier-index/SKILL.md +50 -50
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# Quiz (Quiz)
|
|
2
|
+
|
|
3
|
+
**Acesso Studio:** `/studio/quiz`
|
|
4
|
+
**API Endpoint:** `/v3/quiz`
|
|
5
|
+
|
|
6
|
+
## O que é
|
|
7
|
+
|
|
8
|
+
Agrupamento de perguntas em formato de prova ou simulado. Permite criar provas compostas por perguntas, definir nota total, controlar tentativas e embaralhar questões para cada jogador. Os quizzes podem ser apresentados como mini games.
|
|
9
|
+
|
|
10
|
+
## Quando usar
|
|
11
|
+
|
|
12
|
+
- Para criar provas e avaliações
|
|
13
|
+
- Para simulados com nota
|
|
14
|
+
- Para treinamentos com pontuação
|
|
15
|
+
- Para concursos de conhecimento
|
|
16
|
+
|
|
17
|
+
## Dependências
|
|
18
|
+
|
|
19
|
+
- **Question**: perguntas devem ser criadas para compor o quiz
|
|
20
|
+
|
|
21
|
+
## Checklist de Configuração no Studio
|
|
22
|
+
|
|
23
|
+
- [ ] Definir título e descrição do quiz
|
|
24
|
+
- [ ] Definir nota total (grade)
|
|
25
|
+
- [ ] Criar perguntas associadas ao quiz
|
|
26
|
+
- [ ] Configurar embaralhamento (shuffle)
|
|
27
|
+
- [ ] Definir se mostra nota antes de finalizar (showGradeBeforeFinish)
|
|
28
|
+
- [ ] Configurar numeração das questões (questionNumbering)
|
|
29
|
+
|
|
30
|
+
## API Endpoints
|
|
31
|
+
|
|
32
|
+
### Listar Quizzes
|
|
33
|
+
**Método:** GET
|
|
34
|
+
**Endpoint:** `/v3/database/quiz`
|
|
35
|
+
|
|
36
|
+
### Criar Quiz
|
|
37
|
+
**Método:** POST
|
|
38
|
+
**Endpoint:** `/v3/quiz`
|
|
39
|
+
|
|
40
|
+
**Exemplo de Body:**
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"_id": "650c82fe832",
|
|
44
|
+
"title": "Funifier Exam",
|
|
45
|
+
"description": "Test your knowledge about the best gamification platform in the world.",
|
|
46
|
+
"grade": 10,
|
|
47
|
+
"i18n": {},
|
|
48
|
+
"extra": {},
|
|
49
|
+
"feedbacks": [],
|
|
50
|
+
"questionNumbering": "uppercase_letters",
|
|
51
|
+
"showGradeBeforeFinish": false,
|
|
52
|
+
"shuffle": false
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Deletar Quiz
|
|
57
|
+
**Método:** DELETE
|
|
58
|
+
**Endpoint:** `/v3/quiz/:id`
|
|
59
|
+
|
|
60
|
+
### Listar Perguntas de um Quiz
|
|
61
|
+
**Método:** GET
|
|
62
|
+
**Endpoint:** `/v3/quiz/:id/question`
|
|
63
|
+
|
|
64
|
+
### Criar Pergunta para um Quiz
|
|
65
|
+
**Método:** POST
|
|
66
|
+
**Endpoint:** `/v3/question`
|
|
67
|
+
|
|
68
|
+
**Exemplo de Body:**
|
|
69
|
+
```json
|
|
70
|
+
{
|
|
71
|
+
"quiz": "650c82fe832",
|
|
72
|
+
"type": "MULTIPLE_CHOICE",
|
|
73
|
+
"title": "Best Platform",
|
|
74
|
+
"question": "What is the best gamification platform?",
|
|
75
|
+
"grade": 1,
|
|
76
|
+
"choices": [
|
|
77
|
+
{ "answer": "1", "label": "Funifier", "grade": 1, "extra": {}, "gradePercent": 100, "gradeCheck": true },
|
|
78
|
+
{ "answer": "2", "label": "Points", "grade": 0, "extra": {}, "gradePercent": 0 },
|
|
79
|
+
{ "answer": "3", "label": "Badges", "grade": 0, "extra": {}, "gradePercent": 0 },
|
|
80
|
+
{ "answer": "4", "label": "Leaderboards", "grade": 0, "extra": {}, "gradePercent": 0 }
|
|
81
|
+
],
|
|
82
|
+
"i18n": {},
|
|
83
|
+
"select": "one_answer",
|
|
84
|
+
"shuffle": false
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Iniciar Quiz
|
|
89
|
+
**Método:** POST
|
|
90
|
+
**Endpoint:** `/v3/quiz/start`
|
|
91
|
+
|
|
92
|
+
**Exemplo de Body:**
|
|
93
|
+
```json
|
|
94
|
+
{
|
|
95
|
+
"quiz": "650c82fe832",
|
|
96
|
+
"player": "tom"
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Registrar Respostas em Lote
|
|
101
|
+
**Método:** POST
|
|
102
|
+
**Endpoint:** `/v3/question/log/bulk`
|
|
103
|
+
|
|
104
|
+
**Exemplo de Body:**
|
|
105
|
+
```json
|
|
106
|
+
[
|
|
107
|
+
{
|
|
108
|
+
"quiz": "650c82fe832",
|
|
109
|
+
"quiz_log": "650dc6168325771ffaa94098",
|
|
110
|
+
"question": "650dc4d98325771ffaa93e5e",
|
|
111
|
+
"answer": ["1"],
|
|
112
|
+
"player": "tom"
|
|
113
|
+
}
|
|
114
|
+
]
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Finalizar Quiz
|
|
118
|
+
**Método:** POST
|
|
119
|
+
**Endpoint:** `/v3/quiz/finish`
|
|
120
|
+
|
|
121
|
+
**Exemplo de Body:**
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"quiz_log": "650dc6168325771ffaa94098"
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Fluxo Completo do Quiz
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
1. Admin cria Quiz (POST /v3/quiz)
|
|
132
|
+
2. Admin cria Questions vinculadas ao Quiz (POST /v3/question com "quiz": "quiz_id")
|
|
133
|
+
3. Jogador inicia Quiz (POST /v3/quiz/start → retorna quiz_log_id)
|
|
134
|
+
4. Jogador responde questões (POST /v3/question/log/bulk com quiz_log_id)
|
|
135
|
+
5. Jogador finaliza Quiz (POST /v3/quiz/finish → calcula nota)
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Campos Importantes
|
|
139
|
+
|
|
140
|
+
| Campo | Tipo | Descrição |
|
|
141
|
+
|-------|------|-----------|
|
|
142
|
+
| `grade` | Number | Nota total do quiz (ex: 10) |
|
|
143
|
+
| `shuffle` | Boolean | Embaralhar ordem das perguntas |
|
|
144
|
+
| `showGradeBeforeFinish` | Boolean | Mostrar nota parcial antes de finalizar |
|
|
145
|
+
| `questionNumbering` | String | Formato numeração (`uppercase_letters`, `numbers`, etc.) |
|
|
146
|
+
| `feedbacks` | Array | Mensagens de feedback por faixa de nota |
|
|
147
|
+
|
|
148
|
+
## Apresentação como Mini Game
|
|
149
|
+
|
|
150
|
+
Quizzes podem ser apresentados em formatos de mini games:
|
|
151
|
+
- Corrida espacial
|
|
152
|
+
- Quiz tradicional com timer
|
|
153
|
+
- Formato personalizado via widget/frontend
|
|
154
|
+
|
|
155
|
+
## Validações e Testes
|
|
156
|
+
|
|
157
|
+
- [ ] Quiz aparece na lista GET /v3/database/quiz
|
|
158
|
+
- [ ] Perguntas estão associadas ao quiz
|
|
159
|
+
- [ ] Jogador consegue iniciar quiz (POST /v3/quiz/start)
|
|
160
|
+
- [ ] Respostas são registradas corretamente (POST /v3/question/log/bulk)
|
|
161
|
+
- [ ] Ao finalizar, nota é calculada (POST /v3/quiz/finish)
|
|
162
|
+
- [ ] Embaralhamento funciona (se ativado)
|
|
163
|
+
- [ ] Feedbacks aparecem conforme faixa de nota
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Scheduler (Scheduler)
|
|
2
|
+
|
|
3
|
+
**Acesso Studio:** `/studio/scheduler`
|
|
4
|
+
**API Endpoint:** `/v3/scheduler`
|
|
5
|
+
|
|
6
|
+
## O que é
|
|
7
|
+
|
|
8
|
+
Execução de códigos JAVA em datas e horários agendados (expressões CRON). Permite agendar tarefas e automações para rodar em horários ou intervalos pré-definidos.
|
|
9
|
+
|
|
10
|
+
## Quando usar
|
|
11
|
+
|
|
12
|
+
- Para gerar relatórios automatizados (ex: toda sexta às 10h)
|
|
13
|
+
- Para debitar pontos de jogadores inativos
|
|
14
|
+
- Para enviar lembretes automáticos de metas
|
|
15
|
+
- Para campanhas temporais com início/fim automático
|
|
16
|
+
|
|
17
|
+
## Script Runtime Environment (Wrapper Class)
|
|
18
|
+
|
|
19
|
+
O script do scheduler **não é standalone** — ele é inserido dentro de uma classe Java wrapper gerada pelo Funifier, idêntica à do Public Endpoint (ver `public.md` para a lista completa de imports).
|
|
20
|
+
|
|
21
|
+
### Regras
|
|
22
|
+
|
|
23
|
+
1. **NÃO use `import`** — todos os imports já estão no wrapper (Unirest, Groovy JSON, Funifier entities/utils, Apache HTTP, Simple Java Mail, etc.)
|
|
24
|
+
2. Se precisar de uma classe não importada, use o nome completo: `com.example.MinhaClasse`
|
|
25
|
+
3. **`manager`** (ManagerFactory) está disponível como campo da classe
|
|
26
|
+
4. **Método principal:** `void execute()` (sem parâmetros)
|
|
27
|
+
5. **Timeout padrão de 10 segundos** — pode ser customizado via campo `timeout` (em **segundos**) na API: `POST /v3/scheduler` com `{"_id": "scheduler_id", "timeout": 30}`. Este campo não aparece no Studio.
|
|
28
|
+
6. Scripts rodam em **Groovy** — cuidado com `$` em GStrings
|
|
29
|
+
7. Use apenas **ASCII em comentários**
|
|
30
|
+
|
|
31
|
+
> 📖 Ver `public.md` → **Script Runtime Environment** para a lista completa de imports e bibliotecas disponíveis.
|
|
32
|
+
|
|
33
|
+
## Checklist de Configuração no Studio
|
|
34
|
+
|
|
35
|
+
- [ ] Definir nome e descrição do scheduler
|
|
36
|
+
- [ ] Definir expressão CRON
|
|
37
|
+
- [ ] Escrever script Java
|
|
38
|
+
- [ ] Testar em ambiente de homologação
|
|
39
|
+
|
|
40
|
+
## API Endpoints
|
|
41
|
+
|
|
42
|
+
### Listar Schedulers
|
|
43
|
+
**Método:** GET
|
|
44
|
+
**Endpoint:** `/v3/scheduler`
|
|
45
|
+
|
|
46
|
+
### Criar Scheduler
|
|
47
|
+
**Método:** POST
|
|
48
|
+
**Endpoint:** `/v3/scheduler`
|
|
49
|
+
|
|
50
|
+
### Deletar Scheduler
|
|
51
|
+
**Método:** DELETE
|
|
52
|
+
**Endpoint:** `/v3/scheduler/:id`
|
|
53
|
+
|
|
54
|
+
## Validações e Testes
|
|
55
|
+
|
|
56
|
+
- [ ] Scheduler aparece na lista
|
|
57
|
+
- [ ] Expressão CRON é válida
|
|
58
|
+
- [ ] Script executa no horário configurado
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# Security (Segurança)
|
|
2
|
+
|
|
3
|
+
**Acesso Studio:** Gamification Settings → "Mais" → Security → "Change your gamification security settings"
|
|
4
|
+
**Armazenamento:** Coleção `security`, documento com `_id` = API Key da gamificação
|
|
5
|
+
|
|
6
|
+
## Estrutura do Documento
|
|
7
|
+
|
|
8
|
+
```json
|
|
9
|
+
{
|
|
10
|
+
"_id": "API_KEY_DA_GAMIFICACAO",
|
|
11
|
+
"roles": [
|
|
12
|
+
{ "name": "public", "scope": "read_all", "timeout": "" },
|
|
13
|
+
{ "name": "player", "scope": "read_all, write_all, delete_all, database", "timeout": "" }
|
|
14
|
+
],
|
|
15
|
+
"apps": [
|
|
16
|
+
{ "name": "Nome do App", "app_secret": "GUID_GERADO", "scope": "read_all, write_all, delete_all, database" }
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Roles
|
|
22
|
+
|
|
23
|
+
Definem o nível de acesso dos tokens Bearer (jogadores logados) e Basic (acesso público).
|
|
24
|
+
|
|
25
|
+
### Campos
|
|
26
|
+
- `name` — Identificador da role (ex: `public`, `player`, `admin`)
|
|
27
|
+
- `scope` — Permissões separadas por vírgula
|
|
28
|
+
- `timeout` — Tempo de expiração do token (ex: `7d`, `1h`). **⚠️ NÃO usar string vazia `""`** — causa NPE no auth. Omitir o campo ou usar `null` para timeout padrão (7 dias).
|
|
29
|
+
|
|
30
|
+
### Scopes Disponíveis
|
|
31
|
+
| Scope | Descrição |
|
|
32
|
+
|-------|-----------|
|
|
33
|
+
| `read_all` | Leitura em todas as coleções |
|
|
34
|
+
| `write_all` | Escrita em todas as coleções |
|
|
35
|
+
| `delete_all` | Exclusão em todas as coleções |
|
|
36
|
+
| `database` | **Obrigatório** para acessar `/v3/database`. Sem ele, POST retorna 201 mas não persiste |
|
|
37
|
+
|
|
38
|
+
### Roles Comuns
|
|
39
|
+
- **`public`** — `read_all, write_database_signup__c` — Para acesso não autenticado (signup, landing page). Usa token Basic. Precisa de `write_database_signup__c` para o signup pattern funcionar.
|
|
40
|
+
- **`player`** — `read_all, write_all, delete_all, database` — Para usuários logados. Usa token Bearer.
|
|
41
|
+
|
|
42
|
+
### ⚠️ Lição Crítica
|
|
43
|
+
A palavra **`database`** deve estar literalmente no scope para que `/v3/database` funcione. Mesmo com `write_all` e `read_all`, sem `database` as operações falham silenciosamente.
|
|
44
|
+
|
|
45
|
+
## Apps
|
|
46
|
+
|
|
47
|
+
Apps geram tokens Basic não-expirantes para uso em triggers, endpoints públicos e integrações server-side.
|
|
48
|
+
|
|
49
|
+
### Campos
|
|
50
|
+
- `name` — Nome descritivo do app
|
|
51
|
+
- `app_secret` — GUID gerado pelo Funifier (via `/v3/util/guid/new`)
|
|
52
|
+
- `scope` — Permissões (mesmo formato das roles)
|
|
53
|
+
|
|
54
|
+
### Token Basic do App
|
|
55
|
+
```
|
|
56
|
+
Basic base64(API_KEY + ":" + APP_SECRET)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Exemplo:
|
|
60
|
+
```javascript
|
|
61
|
+
var basicToken = 'Basic ' + btoa('69ab1a9a607db81962b92cd2:69ab3566607db81962b9686e');
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Como Criar via API (sem Studio UI)
|
|
65
|
+
|
|
66
|
+
### 1. Obter token de autenticação do Studio
|
|
67
|
+
O Studio armazena o token em `localStorage` com a chave `marketplace_authorization`:
|
|
68
|
+
```javascript
|
|
69
|
+
var auth = localStorage.getItem('marketplace_authorization');
|
|
70
|
+
// Retorna: "Bearer eyJ..."
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### 2. Gerar GUID para App Secret
|
|
74
|
+
```
|
|
75
|
+
GET https://service2.funifier.com/v3/util/guid/new
|
|
76
|
+
Authorization: Bearer <studio_token>
|
|
77
|
+
```
|
|
78
|
+
Retorna: `{ "guid": "69ab3566607db81962b9686e" }`
|
|
79
|
+
|
|
80
|
+
### 3. Criar/Atualizar Security Document
|
|
81
|
+
```
|
|
82
|
+
PUT https://service2.funifier.com/v3/database/security
|
|
83
|
+
Authorization: Bearer <studio_token>
|
|
84
|
+
Content-Type: application/json
|
|
85
|
+
|
|
86
|
+
{
|
|
87
|
+
"_id": "API_KEY",
|
|
88
|
+
"roles": [...],
|
|
89
|
+
"apps": [...]
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**⚠️ PUT é upsert** — substitui o documento inteiro. Sempre incluir roles E apps existentes.
|
|
94
|
+
|
|
95
|
+
### 4. Verificar
|
|
96
|
+
```
|
|
97
|
+
GET https://service2.funifier.com/v3/database/security/API_KEY?strict=true
|
|
98
|
+
Authorization: Bearer <studio_token>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Navegação no Studio (Browser Automation)
|
|
102
|
+
|
|
103
|
+
1. Abrir `https://my.funifier.com`
|
|
104
|
+
2. Selecionar a gamificação desejada (botão "Select")
|
|
105
|
+
3. Se gamificação nova, clicar "Começar do Zero" para inicializar
|
|
106
|
+
4. Clicar no nome da gamificação na sidebar (link para `/studio/gamification/me`)
|
|
107
|
+
5. Expandir seção "Mais"
|
|
108
|
+
6. Clicar "Change your gamification security settings"
|
|
109
|
+
7. Na página Security: botão "Apps" expande a seção de Apps, botão "Roles" expande Roles
|
|
110
|
+
|
|
111
|
+
**⚠️ SPA Redirect:** Se a gamificação não foi inicializada (wizard "Escolha o melhor caminho"), qualquer navegação para `/studio/security` redireciona para o wizard. Primeiro clicar "Começar do Zero".
|
|
112
|
+
|
|
113
|
+
## Token Basic da Gamificação (público)
|
|
114
|
+
Para acesso público sem App (signup, leitura):
|
|
115
|
+
```
|
|
116
|
+
Basic base64(API_KEY + ":")
|
|
117
|
+
```
|
|
118
|
+
Nota: dois-pontos no final, sem app_secret. Usa a role `public` se existir.
|
|
119
|
+
|
|
120
|
+
## Auth Token (`/v3/auth/token`)
|
|
121
|
+
|
|
122
|
+
### Request (JSON body)
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"grant_type": "password",
|
|
126
|
+
"apiKey": "API_KEY",
|
|
127
|
+
"username": "player_email",
|
|
128
|
+
"password": "plain_text_password"
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**⚠️ Campos obrigatórios:**
|
|
133
|
+
- `grant_type` — DEVE ser `"password"` (sem isso, retorna `invalid_grant`)
|
|
134
|
+
- `username` — NÃO `login` (campo frontend pode usar `login` mas API espera `username`)
|
|
135
|
+
- A senha do Player no banco DEVE ser BCrypt hash (`$2a$...`). Senha em texto plano causa `"Invalid salt version"`
|
|
136
|
+
|
|
137
|
+
### Response
|
|
138
|
+
```json
|
|
139
|
+
{
|
|
140
|
+
"access_token": "eyJ...",
|
|
141
|
+
"token_type": "Bearer",
|
|
142
|
+
"expires_in": "1772..."
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Campos da Security que afetam auth
|
|
147
|
+
| Campo | Tipo | Descrição |
|
|
148
|
+
|-------|------|-----------|
|
|
149
|
+
| `requirePassword` | boolean | Se `true`, valida senha BCrypt. **NÃO** é `passwordRequired` |
|
|
150
|
+
| `createPlayerIfDontExist` | boolean | Se `true`, cria player automaticamente no login. **NÃO** é `autoCreatePlayer` |
|
|
151
|
+
|
|
152
|
+
### ⚠️ Role timeout NUNCA string vazia
|
|
153
|
+
```json
|
|
154
|
+
// ❌ ERRADO — causa NPE no auth (DateUtil.fromKeyword("+") falha)
|
|
155
|
+
{ "name": "player", "scope": "...", "timeout": "" }
|
|
156
|
+
|
|
157
|
+
// ✅ CORRETO — omitir campo para timeout padrão (7 dias)
|
|
158
|
+
{ "name": "player", "scope": "..." }
|
|
159
|
+
|
|
160
|
+
// ✅ CORRETO — valor explícito
|
|
161
|
+
{ "name": "player", "scope": "...", "timeout": "7d" }
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Validações e Testes
|
|
165
|
+
- [ ] Role `public` criada com scope `read_all`
|
|
166
|
+
- [ ] Role `player` criada com scope incluindo `database`
|
|
167
|
+
- [ ] App criada com secret gerado
|
|
168
|
+
- [ ] Token Basic do App acessa `/v3/database/collections`
|
|
169
|
+
- [ ] Token Basic público (sem app) acessa endpoints de leitura
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Staging (Staging)
|
|
2
|
+
|
|
3
|
+
**Acesso Studio:** `/studio/integration/staging`
|
|
4
|
+
|
|
5
|
+
## O que é
|
|
6
|
+
|
|
7
|
+
Gerenciamento de ambientes de homologação e produção, com clonagem e migração de dados. Permite criar e gerenciar ambientes de homologação (staging) separados do ambiente de produção. Possibilita clonar o ambiente produtivo para testes e migrar dados entre servidores.
|
|
8
|
+
|
|
9
|
+
## Quando usar
|
|
10
|
+
|
|
11
|
+
- Para testar novas funcionalidades sem impactar produção
|
|
12
|
+
- Para validar atualizações antes do go-live
|
|
13
|
+
- Para migrar dados entre servidores de diferentes regiões
|
|
14
|
+
- Para criar ambientes espelho de produção
|
|
15
|
+
|
|
16
|
+
## Checklist de Configuração no Studio
|
|
17
|
+
|
|
18
|
+
- [ ] Criar ambiente de staging
|
|
19
|
+
- [ ] Clonar dados de produção para staging
|
|
20
|
+
- [ ] Testar novas funcionalidades em staging
|
|
21
|
+
- [ ] Migrar alterações aprovadas para produção
|
|
22
|
+
|
|
23
|
+
## Validações e Testes
|
|
24
|
+
|
|
25
|
+
- [ ] Ambiente de staging é criado corretamente
|
|
26
|
+
- [ ] Dados são clonados sem perda
|
|
27
|
+
- [ ] Alterações em staging não afetam produção
|
|
28
|
+
- [ ] Migração para produção funciona
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Static Repo (Repositório Estático)
|
|
2
|
+
|
|
3
|
+
**Acesso Studio:** `/studio/static`
|
|
4
|
+
**API Endpoint:** `/v3/static`
|
|
5
|
+
|
|
6
|
+
## O que é
|
|
7
|
+
|
|
8
|
+
Hospedagem de interfaces e conteúdos estáticos em subdomínios Funifier. Permite criar repositórios públicos nos servidores da Funifier para hospedar interfaces gráficas customizadas. Os conteúdos podem ser enviados manualmente, sincronizados via Git ou upload de arquivos.
|
|
9
|
+
|
|
10
|
+
## Quando usar
|
|
11
|
+
|
|
12
|
+
- Para hospedar interface exclusiva da gamificação
|
|
13
|
+
- Para criar páginas personalizadas em subdomínio (ex: seugame.funifier.app)
|
|
14
|
+
- Para deploy de frontends customizados
|
|
15
|
+
|
|
16
|
+
## Checklist de Configuração no Studio
|
|
17
|
+
|
|
18
|
+
- [ ] Criar repositório estático
|
|
19
|
+
- [ ] Fazer upload dos arquivos (HTML, CSS, JS)
|
|
20
|
+
- [ ] Configurar subdomínio
|
|
21
|
+
- [ ] Testar acesso público
|
|
22
|
+
|
|
23
|
+
## API Endpoints
|
|
24
|
+
|
|
25
|
+
### Listar Repositórios
|
|
26
|
+
**Método:** GET
|
|
27
|
+
**Endpoint:** `/v3/static`
|
|
28
|
+
|
|
29
|
+
### Criar Repositório
|
|
30
|
+
**Método:** POST
|
|
31
|
+
**Endpoint:** `/v3/static`
|
|
32
|
+
|
|
33
|
+
### Deletar Repositório
|
|
34
|
+
**Método:** DELETE
|
|
35
|
+
**Endpoint:** `/v3/static/:id`
|
|
36
|
+
|
|
37
|
+
## Validações e Testes
|
|
38
|
+
|
|
39
|
+
- [ ] Repositório é criado com sucesso
|
|
40
|
+
- [ ] Arquivos são acessíveis via URL pública
|
|
41
|
+
- [ ] Subdomínio funciona corretamente
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Story (História)
|
|
2
|
+
|
|
3
|
+
**Acesso Studio:** `/studio/story`
|
|
4
|
+
**API Endpoint:** `/v3/story`
|
|
5
|
+
|
|
6
|
+
## O que é
|
|
7
|
+
|
|
8
|
+
Criação de histórias interativas com múltiplos caminhos e finais. Permite criar narrativas gamificadas nas quais o jogador faz escolhas que afetam o desenrolar da trama. Cenários, personagens, imagens e vídeos podem ser utilizados para enriquecer a experiência.
|
|
9
|
+
|
|
10
|
+
## Quando usar
|
|
11
|
+
|
|
12
|
+
- Para treinamentos baseados em storytelling
|
|
13
|
+
- Para campanhas de marketing com desfechos alternativos
|
|
14
|
+
- Para jogos educacionais interativos
|
|
15
|
+
- Para experiências de role-playing
|
|
16
|
+
|
|
17
|
+
## Checklist de Configuração no Studio
|
|
18
|
+
|
|
19
|
+
- [ ] Definir título e descrição da história
|
|
20
|
+
- [ ] Criar cenários/cenas com textos e mídias
|
|
21
|
+
- [ ] Definir ramificações e escolhas
|
|
22
|
+
- [ ] Configurar finais alternativos
|
|
23
|
+
|
|
24
|
+
## API Endpoints
|
|
25
|
+
|
|
26
|
+
### Listar Stories
|
|
27
|
+
**Método:** GET
|
|
28
|
+
**Endpoint:** `/v3/story`
|
|
29
|
+
|
|
30
|
+
### Criar Story
|
|
31
|
+
**Método:** POST
|
|
32
|
+
**Endpoint:** `/v3/story`
|
|
33
|
+
|
|
34
|
+
### Deletar Story
|
|
35
|
+
**Método:** DELETE
|
|
36
|
+
**Endpoint:** `/v3/story/:id`
|
|
37
|
+
|
|
38
|
+
## Validações e Testes
|
|
39
|
+
|
|
40
|
+
- [ ] História aparece na lista
|
|
41
|
+
- [ ] Navegação entre cenários funciona
|
|
42
|
+
- [ ] Escolhas do jogador são registradas
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# Studio Page (Página Customizada do Studio)
|
|
2
|
+
|
|
3
|
+
**Acesso Studio:** `/studio/page`
|
|
4
|
+
|
|
5
|
+
## O que é
|
|
6
|
+
|
|
7
|
+
Páginas customizadas dentro do Funifier Studio para atender necessidades específicas dos administradores. Permitem criar dashboards, CRUDs, gráficos, relatórios — tudo com AngularJS + Bootstrap.
|
|
8
|
+
|
|
9
|
+
## Configuração
|
|
10
|
+
|
|
11
|
+
Cada página é um JSON com:
|
|
12
|
+
- `_id` — Identificador único (auto-gerado se omitido)
|
|
13
|
+
- `display` — `true` para aparecer no menu do Studio, `false` para páginas internas
|
|
14
|
+
- `title` — Nome exibido no menu
|
|
15
|
+
- `slug` — Caminho relativo (ex: `studio/custom/hello`). Suporta parâmetros: `studio/custom/car/form/:id`
|
|
16
|
+
- `html` — Código HTML (usa Bootstrap CSS)
|
|
17
|
+
- `script` — Código JavaScript (roda no contexto AngularJS)
|
|
18
|
+
|
|
19
|
+
## Contexto JavaScript
|
|
20
|
+
|
|
21
|
+
Dentro do `script`, você tem acesso a:
|
|
22
|
+
- `$scope` — Scope do AngularJS
|
|
23
|
+
- `$http` — Para requisições HTTP
|
|
24
|
+
- `$location` — Para navegação entre páginas (`$location.path("/studio/custom/...")`)
|
|
25
|
+
- `$routeParams` — Para ler parâmetros do slug (ex: `$routeParams.id`)
|
|
26
|
+
- `Marketplace` — Objeto utilitário (ver abaixo)
|
|
27
|
+
|
|
28
|
+
### Marketplace API
|
|
29
|
+
|
|
30
|
+
| Método | Descrição | Exemplo de retorno |
|
|
31
|
+
|--------|-----------|-------------------|
|
|
32
|
+
| `Marketplace.auth.getService()` | URL da API Funifier | `https://service2.funifier.com` |
|
|
33
|
+
| `Marketplace.auth.getAuthorization()` | Token de acesso do usuário logado no Studio | Bearer token |
|
|
34
|
+
| `Marketplace.range.parse(content_range)` | Analisa header `content-range` para paginação | `{page, pages, count, ...}` |
|
|
35
|
+
| `Marketplace.range.paginate(page, content_range)` | Gera header `Range` para ir a uma página | `items=0-100` |
|
|
36
|
+
|
|
37
|
+
## Diretivas Disponíveis
|
|
38
|
+
|
|
39
|
+
- `<image-picker>` — Seletor de imagem (URL, local, galeria). Atributos: `on-change`, `show-picker-url`, `show-picker-local`, `show-picker-gallery`, `upload-max-size`, `transform`
|
|
40
|
+
- `<principal-picker>` — Seletor de jogadores/equipes. Atributos: `title`, `model`, `show-picker-player`, `black-list`, `max`
|
|
41
|
+
- `<input-extra>` — Campos extras dinâmicos. Atributos: `title`, `show-inline`, `model`
|
|
42
|
+
|
|
43
|
+
## Bibliotecas Disponíveis
|
|
44
|
+
|
|
45
|
+
- **Highcharts** — Gráficos (pizza, barra, linhas, etc.)
|
|
46
|
+
- **Bootstrap** — CSS framework (classes `btn`, `table`, `form-control`, etc.)
|
|
47
|
+
- **Glyphicons** — Ícones via `glyphicon glyphicon-*`
|
|
48
|
+
- Traduções: `{{'SAVE'|translate}}`, `{{'CANCEL'|translate}}`, `{{'BACK'|translate}}`, `{{'NEW'|translate}}`, `{{'SEARCH_FOR'|translate}}`
|
|
49
|
+
|
|
50
|
+
## Exemplos
|
|
51
|
+
|
|
52
|
+
### 1. Hello World
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"_id": "hello1",
|
|
56
|
+
"display": true,
|
|
57
|
+
"title": "Hello World!",
|
|
58
|
+
"slug": "studio/custom/hello",
|
|
59
|
+
"html": "<button ng-click=\"hello()\" class=\"btn btn-warning\">Hello</button>",
|
|
60
|
+
"script": "$scope.hello = function(){ alert('Hello World!'); }"
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 2. Lista Simples (Desafios)
|
|
65
|
+
```javascript
|
|
66
|
+
/* "display": true, "title": "Quest List", "slug": "studio/custom/challenge" */
|
|
67
|
+
$scope.all = [];
|
|
68
|
+
$scope.list = function () {
|
|
69
|
+
$http({method: 'GET', url:Marketplace.auth.getService() + '/v3/database/challenge',
|
|
70
|
+
headers: {"Authorization": Marketplace.auth.getAuthorization(), "content-type": "application/json"}
|
|
71
|
+
}).then(function(data){
|
|
72
|
+
$scope.all = data.data;
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
$scope.list();
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 3. Lista Paginada (Players)
|
|
79
|
+
```javascript
|
|
80
|
+
/* "display": true, "title": "Player List", "slug": "studio/custom/player" */
|
|
81
|
+
$scope.range = { request: "items=0-100" };
|
|
82
|
+
$scope.gotopage = function(page){
|
|
83
|
+
$scope.range.request = Marketplace.range.paginate(page, $scope.range.response);
|
|
84
|
+
$scope.list();
|
|
85
|
+
};
|
|
86
|
+
$scope.paginate = function (total) {
|
|
87
|
+
var to = $scope.range.page + total;
|
|
88
|
+
$scope.range.request = Marketplace.range.paginate(to, $scope.range.response);
|
|
89
|
+
$scope.list();
|
|
90
|
+
};
|
|
91
|
+
$scope.all = [];
|
|
92
|
+
$scope.list = function () {
|
|
93
|
+
$http({method: 'GET', url:Marketplace.auth.getService() + '/v3/database/player',
|
|
94
|
+
headers: {"Authorization": Marketplace.auth.getAuthorization(), "Range": $scope.range.request, "content-type": "application/json"}
|
|
95
|
+
}).then(function(data){
|
|
96
|
+
$scope.all = data.data;
|
|
97
|
+
$scope.range = Marketplace.range.parse(data.headers(["content-range"]));
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
$scope.list();
|
|
101
|
+
```
|
|
102
|
+
HTML de paginação:
|
|
103
|
+
```html
|
|
104
|
+
<div>
|
|
105
|
+
Page <input type="number" ng-model="range.page" ng-change="gotopage(range.page)" style="width:40px;" /> of {{range.pages}}
|
|
106
|
+
<button ng-click="paginate(-1)" class="btn btn-default"><span class="glyphicon glyphicon-chevron-left"></span></button>
|
|
107
|
+
<button ng-click="paginate(+1)" class="btn btn-default"><span class="glyphicon glyphicon-chevron-right"></span></button>
|
|
108
|
+
</div>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### 4. CRUD Completo (Carros)
|
|
112
|
+
**Lista** (`display: true`, slug: `studio/custom/car/list`): Lista + busca + paginação + botões editar/excluir + botão "NEW"
|
|
113
|
+
- DELETE: `$http({method: 'DELETE', url: API + "/v3/database/car__c?q=_id:'" + id + "'", ...})`
|
|
114
|
+
- Navegação: `$location.path("/studio/custom/car/form/" + id)` ou `"/studio/custom/car/form/new"`
|
|
115
|
+
|
|
116
|
+
**Formulário** (`display: false`, slug: `studio/custom/car/form/:id`):
|
|
117
|
+
- Carrega via GET: `/v3/database/car__c?strict=true&q=_id:'ID'`
|
|
118
|
+
- Salva via PUT: `/v3/database/car__c`
|
|
119
|
+
- Usa `$routeParams.id` para saber se é edição ou criação (`"new"` = novo)
|
|
120
|
+
- `<image-picker on-change="setImage" ...>` para upload de imagem
|
|
121
|
+
|
|
122
|
+
### 5. Gráfico Highcharts (Active Players)
|
|
123
|
+
```javascript
|
|
124
|
+
/* "display": true, "title": "Daily Active Players", "slug": "studio/custom/kpi/players" */
|
|
125
|
+
$scope.load = function () {
|
|
126
|
+
$http({
|
|
127
|
+
method: 'POST', url: Marketplace.auth.getService() + '/v3/database/action_log/aggregate',
|
|
128
|
+
headers: { Authorization: Marketplace.auth.getAuthorization(), 'content-type': 'application/json'},
|
|
129
|
+
data: [
|
|
130
|
+
{"$match": { "time": { "$gte": { "$date": "-1y" } } } },
|
|
131
|
+
{"$addFields": { "day": { "$dayOfYear": "$time" } } },
|
|
132
|
+
{"$group": { "_id": { "player": "$userId", "day": "$day" }, "time": { "$max": "$time" }}},
|
|
133
|
+
{"$group": { "_id": "$_id.day", "total_users": { "$sum": 1 }, "time": { "$max": "$time" }}},
|
|
134
|
+
{"$project": { "_id": 0, "day_of_year": '$_id', "total": '$total_users', "time": 1}},
|
|
135
|
+
{"$sort": { "day_of_year": 1 } }
|
|
136
|
+
]
|
|
137
|
+
}).then(function (data) {
|
|
138
|
+
var transformedData = data.data.map(function (d) { return [d.time, d.total]; });
|
|
139
|
+
new Highcharts.Chart({
|
|
140
|
+
chart: { renderTo: 'chart', type: 'line' },
|
|
141
|
+
title: { text: 'Daily Active Players' },
|
|
142
|
+
xAxis: { type: 'datetime' },
|
|
143
|
+
yAxis: { title: { text: 'Total' } },
|
|
144
|
+
series: [{ name: 'Total over time', data: transformedData }],
|
|
145
|
+
credits: { enabled: false }
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
};
|
|
149
|
+
$scope.load();
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## API REST para Gerenciar Páginas
|
|
153
|
+
|
|
154
|
+
**IMPORTANTE:** As páginas customizadas ficam na collection `studio_page` (NÃO `page`).
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
# Criar/atualizar página
|
|
158
|
+
curl -X PUT "https://service2.funifier.com/v3/database/studio_page" \
|
|
159
|
+
-H "Authorization: Bearer TOKEN" \
|
|
160
|
+
-H "Content-Type: application/json" \
|
|
161
|
+
-d '{"_id":"minha_pagina", "display":true, "title":"Minha Página", "slug":"studio/custom/minha-pagina", "html":"<h1>Oi</h1>", "script":"/* js */"}'
|
|
162
|
+
|
|
163
|
+
# Listar páginas
|
|
164
|
+
curl "https://service2.funifier.com/v3/database/studio_page" \
|
|
165
|
+
-H "Authorization: Bearer TOKEN"
|
|
166
|
+
|
|
167
|
+
# Deletar página
|
|
168
|
+
curl -X DELETE "https://service2.funifier.com/v3/database/studio_page?q=_id:'ID'" \
|
|
169
|
+
-H "Authorization: Bearer TOKEN"
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Checklist
|
|
173
|
+
|
|
174
|
+
- [ ] Definir `_id`, `title`, `slug`, `display`
|
|
175
|
+
- [ ] Escrever `html` com Bootstrap
|
|
176
|
+
- [ ] Escrever `script` com AngularJS
|
|
177
|
+
- [ ] Usar `Marketplace.auth.*` para autenticação
|
|
178
|
+
- [ ] Usar `?strict=true` em GETs para preservar tipos BSON
|
|
179
|
+
- [ ] Testar no Studio (navegar até a URL do slug)
|
|
180
|
+
- [ ] Para CRUDs: criar página de lista (display:true) + formulário (display:false)
|