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.
Files changed (111) hide show
  1. package/README.md +182 -351
  2. package/datasource-funifier-docs/knowledge/guides/aggregates.md +152 -0
  3. package/datasource-funifier-docs/knowledge/guides/database-access.md +132 -0
  4. package/datasource-funifier-docs/knowledge/guides/java-entities.md +373 -0
  5. package/datasource-funifier-docs/knowledge/guides/java-libraries.md +330 -0
  6. package/datasource-funifier-docs/knowledge/guides/java-managers.md +509 -0
  7. package/datasource-funifier-docs/knowledge/guides/triggers-guide.md +271 -0
  8. package/datasource-funifier-docs/knowledge/index.md +121 -0
  9. package/datasource-funifier-docs/knowledge/modules/achievement.md +46 -0
  10. package/datasource-funifier-docs/knowledge/modules/action-log.md +88 -0
  11. package/datasource-funifier-docs/knowledge/modules/action.md +80 -0
  12. package/datasource-funifier-docs/knowledge/modules/auth.md +104 -0
  13. package/datasource-funifier-docs/knowledge/modules/avatar.md +28 -0
  14. package/datasource-funifier-docs/knowledge/modules/backup.md +40 -0
  15. package/datasource-funifier-docs/knowledge/modules/challenge.md +91 -0
  16. package/datasource-funifier-docs/knowledge/modules/compact.md +40 -0
  17. package/datasource-funifier-docs/knowledge/modules/competition.md +149 -0
  18. package/datasource-funifier-docs/knowledge/modules/crossword.md +41 -0
  19. package/datasource-funifier-docs/knowledge/modules/csv-data.md +30 -0
  20. package/datasource-funifier-docs/knowledge/modules/custom-object.md +53 -0
  21. package/datasource-funifier-docs/knowledge/modules/database.md +241 -0
  22. package/datasource-funifier-docs/knowledge/modules/folder.md +111 -0
  23. package/datasource-funifier-docs/knowledge/modules/kpi-formulas.md +23 -0
  24. package/datasource-funifier-docs/knowledge/modules/lastmile.md +45 -0
  25. package/datasource-funifier-docs/knowledge/modules/leaderboard.md +98 -0
  26. package/datasource-funifier-docs/knowledge/modules/level.md +83 -0
  27. package/datasource-funifier-docs/knowledge/modules/lottery.md +112 -0
  28. package/datasource-funifier-docs/knowledge/modules/marketplace.md +27 -0
  29. package/datasource-funifier-docs/knowledge/modules/mystery.md +82 -0
  30. package/datasource-funifier-docs/knowledge/modules/notification.md +40 -0
  31. package/datasource-funifier-docs/knowledge/modules/patterns.md +1096 -0
  32. package/datasource-funifier-docs/knowledge/modules/player.md +101 -0
  33. package/datasource-funifier-docs/knowledge/modules/point.md +67 -0
  34. package/datasource-funifier-docs/knowledge/modules/public.md +253 -0
  35. package/datasource-funifier-docs/knowledge/modules/question.md +136 -0
  36. package/datasource-funifier-docs/knowledge/modules/quiz.md +163 -0
  37. package/datasource-funifier-docs/knowledge/modules/scheduler.md +58 -0
  38. package/datasource-funifier-docs/knowledge/modules/security.md +169 -0
  39. package/datasource-funifier-docs/knowledge/modules/staging.md +28 -0
  40. package/datasource-funifier-docs/knowledge/modules/static-repo.md +41 -0
  41. package/datasource-funifier-docs/knowledge/modules/story.md +42 -0
  42. package/datasource-funifier-docs/knowledge/modules/studio-page.md +180 -0
  43. package/datasource-funifier-docs/knowledge/modules/swap.md +132 -0
  44. package/datasource-funifier-docs/knowledge/modules/team.md +75 -0
  45. package/datasource-funifier-docs/knowledge/modules/trigger.md +189 -0
  46. package/datasource-funifier-docs/knowledge/modules/upload.md +155 -0
  47. package/datasource-funifier-docs/knowledge/modules/virtual-good.md +99 -0
  48. package/datasource-funifier-docs/knowledge/modules/webhook.md +41 -0
  49. package/datasource-funifier-docs/knowledge/modules/websocket.md +41 -0
  50. package/datasource-funifier-docs/knowledge/modules/widget.md +42 -0
  51. package/datasource-funifier-docs/process-gtm-saas.md +143 -0
  52. package/datasource-funifier-docs/process-instagram.md +88 -0
  53. package/datasource-funifier-docs/process.md +1826 -0
  54. package/datasource-funifier-docs/readme.md +132 -0
  55. package/dist/cli/config-writers.d.ts +15 -0
  56. package/dist/cli/config-writers.d.ts.map +1 -0
  57. package/dist/cli/config-writers.js +55 -0
  58. package/dist/cli/config-writers.js.map +1 -0
  59. package/dist/cli/config-writers.test.d.ts +2 -0
  60. package/dist/cli/config-writers.test.d.ts.map +1 -0
  61. package/dist/cli/config-writers.test.js +55 -0
  62. package/dist/cli/config-writers.test.js.map +1 -0
  63. package/dist/cli/copy.d.ts +6 -0
  64. package/dist/cli/copy.d.ts.map +1 -0
  65. package/dist/cli/copy.js +63 -0
  66. package/dist/cli/copy.js.map +1 -0
  67. package/dist/cli/copy.test.d.ts +2 -0
  68. package/dist/cli/copy.test.d.ts.map +1 -0
  69. package/dist/cli/copy.test.js +94 -0
  70. package/dist/cli/copy.test.js.map +1 -0
  71. package/dist/cli/init.d.ts +2 -0
  72. package/dist/cli/init.d.ts.map +1 -0
  73. package/dist/cli/init.js +167 -0
  74. package/dist/cli/init.js.map +1 -0
  75. package/dist/cli/paths.d.ts +7 -0
  76. package/dist/cli/paths.d.ts.map +1 -0
  77. package/dist/cli/paths.js +62 -0
  78. package/dist/cli/paths.js.map +1 -0
  79. package/dist/cli/paths.test.d.ts +2 -0
  80. package/dist/cli/paths.test.d.ts.map +1 -0
  81. package/dist/cli/paths.test.js +50 -0
  82. package/dist/cli/paths.test.js.map +1 -0
  83. package/dist/cli/platforms.d.ts +22 -0
  84. package/dist/cli/platforms.d.ts.map +1 -0
  85. package/dist/cli/platforms.js +50 -0
  86. package/dist/cli/platforms.js.map +1 -0
  87. package/dist/cli/prompts.d.ts +7 -0
  88. package/dist/cli/prompts.d.ts.map +1 -0
  89. package/dist/cli/prompts.js +49 -0
  90. package/dist/cli/prompts.js.map +1 -0
  91. package/dist/index.js +1 -1
  92. package/dist/index.js.map +1 -1
  93. package/dist/mcp/bundle.js +94 -49
  94. package/dist/mcp/index.js +18 -1
  95. package/dist/mcp/index.js.map +1 -1
  96. package/package.json +4 -2
  97. package/skills/funifier-create-action/SKILL.md +86 -86
  98. package/skills/funifier-create-aggregate/SKILL.md +39 -0
  99. package/skills/funifier-create-challenge/SKILL.md +87 -87
  100. package/skills/funifier-create-custom-page/SKILL.md +39 -0
  101. package/skills/funifier-create-leaderboard/SKILL.md +87 -87
  102. package/skills/funifier-create-level/SKILL.md +86 -86
  103. package/skills/funifier-create-point/SKILL.md +86 -86
  104. package/skills/funifier-create-quiz/SKILL.md +86 -86
  105. package/skills/funifier-create-scheduler/SKILL.md +39 -0
  106. package/skills/funifier-create-trigger/SKILL.md +39 -0
  107. package/skills/funifier-create-virtual-good/SKILL.md +86 -86
  108. package/skills/funifier-debug/SKILL.md +90 -90
  109. package/skills/funifier-help/SKILL.md +85 -85
  110. package/skills/funifier-implement-frontend/SKILL.md +89 -89
  111. 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)