@etus/bhono-app 0.1.6 → 0.1.7

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 (61) hide show
  1. package/package.json +3 -2
  2. package/templates/base/.claude/commands/check-skill-rules.md +112 -29
  3. package/templates/base/.claude/commands/linear/implement-issue.md +383 -55
  4. package/templates/base/.claude/commands/ship.md +77 -13
  5. package/templates/base/.claude/hooks/package-lock.json +0 -419
  6. package/templates/base/.claude/hooks/skill-activation-prompt.ts +185 -113
  7. package/templates/base/.claude/hooks/skill-tool-guard.sh +6 -0
  8. package/templates/base/.claude/hooks/skill-tool-guard.ts +198 -0
  9. package/templates/base/.claude/scripts/validate-skill-rules.sh +55 -32
  10. package/templates/base/.claude/settings.json +18 -11
  11. package/templates/base/.claude/skills/skill-rules.json +326 -173
  12. package/templates/base/.env.example +3 -0
  13. package/templates/base/README.md +9 -7
  14. package/templates/base/config/eslint.config.js +1 -0
  15. package/templates/base/config/wrangler.json +16 -17
  16. package/templates/base/docs/SETUP-GUIDE.md +566 -0
  17. package/templates/base/docs/architecture/README.md +162 -8
  18. package/templates/base/docs/architecture/api-catalog.md +575 -0
  19. package/templates/base/docs/architecture/c4-component.md +309 -0
  20. package/templates/base/docs/architecture/c4-container.md +183 -0
  21. package/templates/base/docs/architecture/c4-context.md +106 -0
  22. package/templates/base/docs/architecture/dependencies.md +327 -0
  23. package/templates/base/docs/architecture/tech-debt.md +184 -0
  24. package/templates/base/package.json +20 -15
  25. package/templates/base/scripts/capture-prod-session.ts +2 -2
  26. package/templates/base/scripts/sync-template.sh +104 -0
  27. package/templates/base/src/server/db/sql.ts +24 -4
  28. package/templates/base/src/server/index.ts +1 -0
  29. package/templates/base/src/server/lib/audited-db.ts +10 -10
  30. package/templates/base/src/server/middleware/account.ts +1 -1
  31. package/templates/base/src/server/middleware/auth.ts +11 -11
  32. package/templates/base/src/server/middleware/rate-limit.ts +3 -6
  33. package/templates/base/src/server/routes/auth/handlers.ts +5 -5
  34. package/templates/base/src/server/routes/auth/test-login.ts +9 -9
  35. package/templates/base/src/server/routes/index.ts +9 -0
  36. package/templates/base/src/server/routes/invitations/handlers.ts +6 -6
  37. package/templates/base/src/server/routes/openapi.ts +1 -1
  38. package/templates/base/src/server/services/accounts.ts +9 -9
  39. package/templates/base/src/server/services/audits.ts +12 -12
  40. package/templates/base/src/server/services/auth.ts +15 -15
  41. package/templates/base/src/server/services/invitations.ts +16 -16
  42. package/templates/base/src/server/services/users.ts +13 -13
  43. package/templates/base/src/shared/types/api.ts +66 -198
  44. package/templates/base/tests/e2e/auth.setup.ts +1 -1
  45. package/templates/base/tests/unit/server/auth/guards.test.ts +1 -1
  46. package/templates/base/tests/unit/server/middleware/auth.test.ts +273 -0
  47. package/templates/base/tests/unit/server/routes/auth/handlers.test.ts +111 -0
  48. package/templates/base/tests/unit/server/routes/users/handlers.test.ts +69 -5
  49. package/templates/base/tests/unit/server/services/accounts.test.ts +148 -0
  50. package/templates/base/tests/unit/server/services/audits.test.ts +219 -0
  51. package/templates/base/tests/unit/server/services/auth.test.ts +480 -3
  52. package/templates/base/tests/unit/server/services/invitations.test.ts +178 -0
  53. package/templates/base/tests/unit/server/services/users.test.ts +363 -8
  54. package/templates/base/tests/unit/shared/schemas.test.ts +1 -1
  55. package/templates/base/vite.config.ts +3 -1
  56. package/templates/base/.github/workflows/test.yml +0 -127
  57. package/templates/base/.husky/pre-push +0 -26
  58. package/templates/base/auth-setup-error.png +0 -0
  59. package/templates/base/pnpm-lock.yaml +0 -8052
  60. package/templates/base/tests/e2e/_auth/.gitkeep +0 -0
  61. package/templates/base/tsconfig.tsbuildinfo +0 -1
@@ -1,31 +1,30 @@
1
1
  {
2
2
  "$schema": "../node_modules/wrangler/config-schema.json",
3
- "name": "{{projectName}}",
3
+ "name": "hono-boilerplate",
4
+ "account_id": "10ca68c044521baa536840a17160933b",
4
5
  "main": "../src/server/index.ts",
5
6
  "compatibility_date": "2025-01-01",
6
- "compatibility_flags": [
7
- "nodejs_compat"
8
- ],
7
+ "compatibility_flags": ["nodejs_compat"],
9
8
  "dev": {
10
9
  "port": 3000
11
10
  },
12
11
  "d1_databases": [
13
12
  {
14
13
  "binding": "DB",
15
- "database_name": "{{projectName}}-db",
16
- "database_id": "TO_BE_PROVISIONED"
14
+ "database_name": "boilerplate-db",
15
+ "database_id": "a9de77f8-3189-41d9-84dd-a38d3c9c27bd"
17
16
  }
18
17
  ],
19
18
  "r2_buckets": [
20
19
  {
21
20
  "binding": "R2_BUCKET",
22
- "bucket_name": "{{projectName}}-storage"
21
+ "bucket_name": "boilerplate-storage"
23
22
  }
24
23
  ],
25
24
  "kv_namespaces": [
26
25
  {
27
26
  "binding": "SESSIONS",
28
- "id": "TO_BE_PROVISIONED"
27
+ "id": "3dea2b79495f490ca088a18c6bab6b38"
29
28
  }
30
29
  ],
31
30
  "assets": {
@@ -39,36 +38,36 @@
39
38
  },
40
39
  "vars": {
41
40
  "ENVIRONMENT": "production",
42
- "APP_URL": "https://{{projectName}}.a3s.workers.dev",
43
- "GOOGLE_REDIRECT_URI": "https://{{projectName}}.a3s.workers.dev/auth/callback",
41
+ "APP_URL": "https://hono-boilerplate.a3s.workers.dev",
42
+ "GOOGLE_REDIRECT_URI": "https://hono-boilerplate.a3s.workers.dev/auth/callback",
44
43
  "R2_PUBLIC_URL": "https://pub-your-bucket-id.r2.dev"
45
44
  },
46
45
  "env": {
47
46
  "staging": {
48
- "name": "{{projectName}}-staging",
47
+ "name": "hono-boilerplate-staging",
49
48
  "d1_databases": [
50
49
  {
51
50
  "binding": "DB",
52
- "database_name": "{{projectName}}-db-staging",
53
- "database_id": "TO_BE_PROVISIONED"
51
+ "database_name": "boilerplate-db-staging",
52
+ "database_id": "2fe5e1b5-8168-4024-9060-be7972380228"
54
53
  }
55
54
  ],
56
55
  "kv_namespaces": [
57
56
  {
58
57
  "binding": "SESSIONS",
59
- "id": "TO_BE_PROVISIONED"
58
+ "id": "c341542f0efd466a93b65e6cadf1f9ba"
60
59
  }
61
60
  ],
62
61
  "r2_buckets": [
63
62
  {
64
63
  "binding": "R2_BUCKET",
65
- "bucket_name": "{{projectName}}-storage-staging"
64
+ "bucket_name": "boilerplate-storage-staging"
66
65
  }
67
66
  ],
68
67
  "vars": {
69
68
  "ENVIRONMENT": "staging",
70
- "APP_URL": "https://{{projectName}}-staging.a3s.workers.dev",
71
- "GOOGLE_REDIRECT_URI": "https://{{projectName}}-staging.a3s.workers.dev/auth/callback",
69
+ "APP_URL": "https://hono-boilerplate-staging.a3s.workers.dev",
70
+ "GOOGLE_REDIRECT_URI": "https://hono-boilerplate-staging.a3s.workers.dev/auth/callback",
72
71
  "R2_PUBLIC_URL": "https://pub-your-bucket-id.r2.dev"
73
72
  }
74
73
  }
@@ -0,0 +1,566 @@
1
+ # BHono App - Guia de Setup Completo
2
+
3
+ ## Setup Rápido (Recomendado)
4
+
5
+ O script `init.sh` foi atualizado para resolver automaticamente todos os problemas documentados neste guia.
6
+
7
+ ### Para Projetos Novos
8
+
9
+ ```bash
10
+ # Criar projeto
11
+ npm init bhono-app@latest meu-projeto -- --yes
12
+ cd meu-projeto
13
+
14
+ # Setup completo com credenciais Google
15
+ ./scripts/init.sh --port 8787 \
16
+ --google-id "seu-client-id.apps.googleusercontent.com" \
17
+ --google-secret "GOCSPX-xxx"
18
+
19
+ # Ou setup básico (configure credenciais depois)
20
+ ./scripts/init.sh --port 8787
21
+ ```
22
+
23
+ ### Para Projetos Existentes
24
+
25
+ ```bash
26
+ # Setup completo
27
+ ./scripts/init.sh --port 8787 \
28
+ --google-id "seu-client-id" \
29
+ --google-secret "seu-secret"
30
+
31
+ # Setup sem provisionar recursos Cloudflare
32
+ ./scripts/init.sh --no-provision --port 8787
33
+
34
+ # Setup sem iniciar o servidor
35
+ ./scripts/init.sh --skip-dev
36
+ ```
37
+
38
+ ### Múltiplas Contas Cloudflare
39
+
40
+ ```bash
41
+ CLOUDFLARE_ACCOUNT_ID=seu-account-id ./scripts/init.sh
42
+ ```
43
+
44
+ ### O que o init.sh faz automaticamente:
45
+
46
+ 1. ✅ Corrige nome do projeto em `package.json`, `etus.config.json`, `wrangler.json`
47
+ 2. ✅ Configura `vite.config.ts` (configPath + porta)
48
+ 3. ✅ Cria `config/.dev.vars` com todas as variáveis necessárias
49
+ 4. ✅ Adiciona `config/.dev.vars` ao `.gitignore`
50
+ 5. ✅ Aumenta rate limit de auth para desenvolvimento (100 req/min)
51
+ 6. ✅ Corrige caminhos no `drizzle.config.ts`
52
+ 7. ✅ Sincroniza bancos SQLite (resolve problema de hash do plugin)
53
+ 8. ✅ Provisiona recursos Cloudflare (D1, KV, R2)
54
+ 9. ✅ Aplica schema e seed no banco de dados
55
+
56
+ ---
57
+
58
+ ## Resumo dos Problemas Encontrados e Soluções
59
+
60
+ ### 1. Criação do Projeto com Prompts Interativos
61
+
62
+ **Problema:** O comando `npm init bhono-app@latest .` falha em ambientes não-TTY (como Claude Code ou CI/CD) porque usa prompts interativos.
63
+
64
+ **Solução:** Usar a flag `--yes` para pular os prompts:
65
+ ```bash
66
+ npm init bhono-app@latest . -- --yes
67
+ ```
68
+
69
+ ---
70
+
71
+ ### 2. Nome do Projeto Incorreto
72
+
73
+ **Problema:** Quando usado com `.` como diretório, o nome do projeto fica como "." em vez do nome da pasta, causando:
74
+ - `wrangler.json` com nomes inválidos (`.-db`, `.-storage`)
75
+ - `package.json` com `"name": "."`
76
+ - Erros de validação do Cloudflare
77
+
78
+ **Solução:** Após criar o projeto, corrigir manualmente:
79
+
80
+ **package.json:**
81
+ ```json
82
+ {
83
+ "name": "nome-do-projeto"
84
+ }
85
+ ```
86
+
87
+ **config/wrangler.json:**
88
+ - Substituir todas ocorrências de `"."` e `".-"` pelo nome correto do projeto
89
+ - Corrigir: `name`, `database_name`, `bucket_name`, URLs em `vars`
90
+
91
+ ---
92
+
93
+ ### 3. Múltiplas Contas Cloudflare
94
+
95
+ **Problema:** Se você tem múltiplas contas Cloudflare, o wrangler falha com:
96
+ ```
97
+ More than one account available but unable to select one in non-interactive mode
98
+ ```
99
+
100
+ **Solução:** Definir a variável de ambiente `CLOUDFLARE_ACCOUNT_ID`:
101
+ ```bash
102
+ CLOUDFLARE_ACCOUNT_ID=seu-account-id ./scripts/init.sh
103
+ ```
104
+
105
+ Ou adicionar `account_id` no `wrangler.json`:
106
+ ```json
107
+ {
108
+ "account_id": "seu-account-id"
109
+ }
110
+ ```
111
+
112
+ ---
113
+
114
+ ### 4. Cloudflare Vite Plugin não Encontra wrangler.json
115
+
116
+ **Problema:** O plugin `@cloudflare/vite-plugin` não encontra o `wrangler.json` quando está em `config/`.
117
+
118
+ **Solução:** Configurar o caminho no `vite.config.ts`:
119
+ ```typescript
120
+ cloudflare({
121
+ configPath: './config/wrangler.json',
122
+ }),
123
+ ```
124
+
125
+ ---
126
+
127
+ ### 5. Variáveis de Ambiente não Carregadas
128
+
129
+ **Problema:** O arquivo `.dev.vars` precisa estar no mesmo diretório que o `wrangler.json` para ser carregado.
130
+
131
+ **Solução:** Criar `config/.dev.vars` com todas as variáveis necessárias:
132
+ ```env
133
+ # Environment
134
+ ENVIRONMENT=development
135
+ APP_URL=http://localhost:8787
136
+
137
+ # JWT Configuration
138
+ JWT_SECRET=super-secret-jwt-key-with-at-least-32-characters-for-security
139
+ JWT_EXPIRY_MINUTES=15
140
+
141
+ # Google OAuth
142
+ GOOGLE_CLIENT_ID=seu-client-id
143
+ GOOGLE_CLIENT_SECRET=seu-client-secret
144
+ GOOGLE_REDIRECT_URI=http://localhost:8787/auth/callback
145
+
146
+ # Refresh Token
147
+ REFRESH_TOKEN_EXPIRY_DAYS=30
148
+
149
+ # SendGrid
150
+ SENDGRID_API_KEY=your-sendgrid-api-key
151
+ SENDGRID_FROM_EMAIL=noreply@example.com
152
+ ```
153
+
154
+ **Importante:** `JWT_SECRET` deve ter pelo menos 32 caracteres.
155
+
156
+ ---
157
+
158
+ ### 6. Banco de Dados com Hash Diferente
159
+
160
+ **Problema:** O Cloudflare Vite Plugin cria o banco SQLite com um hash baseado nas configurações, não no `database_id` do wrangler.json. Isso causa erro "no such table: users".
161
+
162
+ **Solução:** Após executar `pnpm db:push`, identificar o arquivo correto e copiar:
163
+
164
+ ```bash
165
+ # Encontrar todos os arquivos sqlite
166
+ find .wrangler -name "*.sqlite"
167
+
168
+ # Copiar o banco com dados para o banco que o plugin usa
169
+ cp .wrangler/state/v3/d1/miniflare-D1DatabaseObject/ID_CORRETO.sqlite \
170
+ .wrangler/state/v3/d1/miniflare-D1DatabaseObject/HASH_DO_PLUGIN.sqlite
171
+ ```
172
+
173
+ **Melhor solução:** Atualizar `config/drizzle.config.ts` para usar o caminho correto do banco usado pelo plugin.
174
+
175
+ ---
176
+
177
+ ### 7. Drizzle Config com Caminhos Relativos Incorretos
178
+
179
+ **Problema:** O `drizzle.config.ts` usa caminhos relativos que não funcionam quando executado da raiz.
180
+
181
+ **Solução:** Usar caminhos relativos à raiz do projeto:
182
+ ```typescript
183
+ export default defineConfig({
184
+ schema: './src/server/db/schema/index.ts',
185
+ out: './src/server/db/migrations',
186
+ dialect: 'sqlite',
187
+ dbCredentials: {
188
+ url: './.wrangler/state/v3/d1/miniflare-D1DatabaseObject/SEU_DB_ID.sqlite',
189
+ },
190
+ })
191
+ ```
192
+
193
+ ---
194
+
195
+ ### 8. Rate Limit Muito Restritivo
196
+
197
+ **Problema:** O rate limit de auth (10 req/min) é atingido rapidamente porque o frontend chama `/auth/me` múltiplas vezes para verificar sessão.
198
+
199
+ **Solução:** Aumentar o limite em `src/server/middleware/rate-limit.ts`:
200
+ ```typescript
201
+ export function authRateLimit() {
202
+ return rateLimit({
203
+ windowMs: 60000,
204
+ max: 100, // Aumentado de 10 para 100
205
+ message: 'Too many authentication attempts, please try again later',
206
+ })
207
+ }
208
+ ```
209
+
210
+ ---
211
+
212
+ ### 9. Porta do Servidor
213
+
214
+ **Problema:** Por padrão o Vite usa porta 5173, não a porta configurada no wrangler.json.
215
+
216
+ **Solução:** Configurar a porta no `vite.config.ts`:
217
+ ```typescript
218
+ export default defineConfig({
219
+ server: {
220
+ port: 8787,
221
+ },
222
+ // ...
223
+ })
224
+ ```
225
+
226
+ ---
227
+
228
+ ### 10. Redirect após Login vai para Produção
229
+
230
+ **Problema:** Após login OAuth, o redirect vai para a URL de produção em vez de localhost.
231
+
232
+ **Solução:** Adicionar `APP_URL` no `config/.dev.vars`:
233
+ ```env
234
+ APP_URL=http://localhost:8787
235
+ ```
236
+
237
+ ---
238
+
239
+ ## Checklist de Setup Rápido
240
+
241
+ Com o `init.sh` atualizado, a maioria destes itens são automáticos:
242
+
243
+ - [x] ~~Criar projeto com `--yes`~~ (use `npm init bhono-app@latest nome -- --yes`)
244
+ - [x] ~~Corrigir nome em arquivos de config~~ (**automático via init.sh**)
245
+ - [x] ~~Criar `config/.dev.vars`~~ (**automático via init.sh**)
246
+ - [x] ~~Adicionar `config/.dev.vars` ao `.gitignore`~~ (**automático via init.sh**)
247
+ - [x] ~~Configurar `vite.config.ts`~~ (**automático via init.sh**)
248
+ - [x] ~~Executar `pnpm db:push` e `pnpm db:seed`~~ (**automático via init.sh**)
249
+ - [x] ~~Sincronizar bancos sqlite~~ (**automático via init.sh**)
250
+ - [x] ~~Aumentar rate limit de auth~~ (**automático via init.sh**)
251
+ - [ ] **Configurar Google OAuth redirect URI no console** (manual)
252
+
253
+ ---
254
+
255
+ ## Variáveis de Ambiente Necessárias
256
+
257
+ | Variável | Descrição | Obrigatório |
258
+ |----------|-----------|-------------|
259
+ | `ENVIRONMENT` | development/staging/production | Sim |
260
+ | `APP_URL` | URL da aplicação | Sim |
261
+ | `JWT_SECRET` | Chave para tokens (min 32 chars) | Sim |
262
+ | `JWT_EXPIRY_MINUTES` | Expiração do JWT | Sim |
263
+ | `GOOGLE_CLIENT_ID` | ID do OAuth Google | Sim |
264
+ | `GOOGLE_CLIENT_SECRET` | Secret do OAuth Google | Sim |
265
+ | `GOOGLE_REDIRECT_URI` | URI de callback | Sim |
266
+ | `REFRESH_TOKEN_EXPIRY_DAYS` | Dias para refresh token | Sim |
267
+ | `SENDGRID_API_KEY` | API key do SendGrid | Opcional* |
268
+ | `SENDGRID_FROM_EMAIL` | Email remetente | Opcional* |
269
+
270
+ *Necessário para envio de convites por email.
271
+
272
+ ---
273
+
274
+ ## Google OAuth Setup
275
+
276
+ 1. Acesse [Google Cloud Console](https://console.cloud.google.com/)
277
+ 2. Crie um novo projeto ou selecione existente
278
+ 3. Vá em APIs & Services > Credentials
279
+ 4. Crie OAuth 2.0 Client ID (Web application)
280
+ 5. Adicione os URIs de redirecionamento autorizados:
281
+ - `http://localhost:8787/auth/callback` (desenvolvimento)
282
+ - `https://seu-app.workers.dev/auth/callback` (produção)
283
+ 6. Copie Client ID e Client Secret para `.dev.vars`
284
+
285
+ ---
286
+
287
+ ## Lacunas Adicionais Descobertas
288
+
289
+ ### 11. Arquivo etus.config.json não Corrigido
290
+
291
+ **Problema:** O arquivo `etus.config.json` também fica com nome "." após a criação do projeto.
292
+
293
+ **Solução:** Corrigir manualmente:
294
+ ```json
295
+ {
296
+ "name": "nome-do-projeto",
297
+ "domain": "nome-do-projeto.com",
298
+ "modules": [],
299
+ "providers": {
300
+ "auth": "google",
301
+ "email": "sendgrid"
302
+ }
303
+ }
304
+ ```
305
+
306
+ ---
307
+
308
+ ### 12. Dois Arquivos .dev.vars (Raiz e config/)
309
+
310
+ **Problema:** O projeto pode ter dois arquivos `.dev.vars`:
311
+ - `.dev.vars` na raiz (usado pelo `scripts/init.sh`)
312
+ - `config/.dev.vars` (usado pelo Cloudflare Vite Plugin)
313
+
314
+ **Solução:** Manter ambos sincronizados com as mesmas variáveis, ou usar apenas `config/.dev.vars` e criar um symlink:
315
+ ```bash
316
+ ln -sf config/.dev.vars .dev.vars
317
+ ```
318
+
319
+ ---
320
+
321
+ ### 13. Como Descobrir Qual Banco SQLite o Plugin Usa
322
+
323
+ **Problema:** O Cloudflare Vite Plugin usa um hash diferente do `database_id` para o arquivo SQLite. Difícil saber qual arquivo atualizar.
324
+
325
+ **Solução:** Verificar qual arquivo foi modificado mais recentemente ou é maior:
326
+ ```bash
327
+ # Listar todos os bancos com tamanho e data
328
+ find .wrangler -name "*.sqlite" -not -name "*-shm" -not -name "*-wal" -exec ls -la {} \;
329
+
330
+ # O maior arquivo geralmente é o que tem dados
331
+ # Ou verificar qual foi modificado após fazer uma operação
332
+ ```
333
+
334
+ **Dica:** Após descobrir o hash correto, atualize `config/drizzle.config.ts` para apontar para ele.
335
+
336
+ ---
337
+
338
+ ### 14. Atualizar .gitignore para config/.dev.vars
339
+
340
+ **Problema:** O arquivo `config/.dev.vars` contém credenciais sensíveis mas pode não estar no `.gitignore`.
341
+
342
+ **Solução:** Adicionar ao `.gitignore`:
343
+ ```bash
344
+ echo "config/.dev.vars" >> .gitignore
345
+ ```
346
+
347
+ ---
348
+
349
+ ### 15. KV Namespace para Sessions
350
+
351
+ **Informação:** O projeto usa KV Namespace para armazenar sessões. Em desenvolvimento local, o miniflare cria um arquivo SQLite para simular o KV:
352
+ ```
353
+ .wrangler/state/v3/kv/miniflare-KVNamespaceObject/*.sqlite
354
+ ```
355
+
356
+ Este arquivo é gerenciado automaticamente e não precisa de intervenção manual.
357
+
358
+ ---
359
+
360
+ ## Arquivos que Precisam ser Corrigidos (Lista Completa)
361
+
362
+ > **Nota:** Todos estes arquivos são corrigidos automaticamente pelo `init.sh` atualizado.
363
+
364
+ | Arquivo | O que corrigir | Status |
365
+ |---------|----------------|--------|
366
+ | `package.json` | `"name": "."` → `"name": "nome-projeto"` | ✅ Automático |
367
+ | `config/wrangler.json` | `name`, `database_name`, `bucket_name`, URLs | ✅ Automático |
368
+ | `etus.config.json` | `"name": "."` → `"name": "nome-projeto"` | ✅ Automático |
369
+ | `vite.config.ts` | Adicionar `configPath` e `server.port` | ✅ Automático |
370
+ | `config/drizzle.config.ts` | Corrigir caminhos e apontar para banco correto | ✅ Automático |
371
+ | `config/.dev.vars` | Criar com todas as variáveis | ✅ Automático |
372
+ | `.gitignore` | Adicionar `config/.dev.vars` (segurança!) | ✅ Automático |
373
+ | `src/server/middleware/rate-limit.ts` | Aumentar `max` de 10 para 100 | ✅ Automático |
374
+
375
+ ---
376
+
377
+ ## Comandos Úteis
378
+
379
+ ```bash
380
+ # Verificar tabelas no banco
381
+ sqlite3 .wrangler/state/v3/d1/miniflare-D1DatabaseObject/*.sqlite ".tables"
382
+
383
+ # Ver estrutura de uma tabela
384
+ sqlite3 .wrangler/state/v3/d1/miniflare-D1DatabaseObject/*.sqlite ".schema users"
385
+
386
+ # Executar query
387
+ sqlite3 .wrangler/state/v3/d1/miniflare-D1DatabaseObject/*.sqlite "SELECT * FROM users;"
388
+
389
+ # Aplicar seed manualmente
390
+ sqlite3 ARQUIVO.sqlite < seed.sql
391
+
392
+ # Listar todos os bancos sqlite
393
+ find .wrangler -name "*.sqlite" -not -name "*-shm" -not -name "*-wal"
394
+
395
+ # Verificar qual banco tem tabelas
396
+ for f in $(find .wrangler -name "*.sqlite" -not -name "*-shm" -not -name "*-wal"); do
397
+ echo "=== $f ==="
398
+ sqlite3 "$f" ".tables"
399
+ done
400
+ ```
401
+
402
+ ---
403
+
404
+ ## Testes
405
+
406
+ ```bash
407
+ # Rodar todos os testes
408
+ pnpm test
409
+
410
+ # Testes unitários do servidor
411
+ pnpm test:unit:server
412
+
413
+ # Testes unitários do cliente
414
+ pnpm test:unit:client
415
+
416
+ # Testes de integração
417
+ pnpm test:integration
418
+
419
+ # Testes E2E (requer servidor rodando)
420
+ pnpm test:e2e
421
+
422
+ # Testes E2E com UI
423
+ pnpm test:e2e:ui
424
+ ```
425
+
426
+ ---
427
+
428
+ ## Deploy para Produção
429
+
430
+ ### 1. Provisionar Recursos Cloudflare
431
+
432
+ ```bash
433
+ # Login no Cloudflare
434
+ pnpm exec wrangler login
435
+
436
+ # Criar D1 Database
437
+ pnpm exec wrangler d1 create nome-projeto-db
438
+
439
+ # Criar KV Namespace
440
+ pnpm exec wrangler kv namespace create nome-projeto-sessions
441
+
442
+ # Criar R2 Bucket
443
+ pnpm exec wrangler r2 bucket create nome-projeto-storage
444
+ ```
445
+
446
+ ### 2. Atualizar wrangler.json com IDs
447
+
448
+ Após criar os recursos, atualize `config/wrangler.json` com os IDs retornados.
449
+
450
+ ### 3. Configurar Secrets
451
+
452
+ ```bash
453
+ # Configurar variáveis secretas
454
+ pnpm exec wrangler secret put JWT_SECRET --config config/wrangler.json
455
+ pnpm exec wrangler secret put GOOGLE_CLIENT_ID --config config/wrangler.json
456
+ pnpm exec wrangler secret put GOOGLE_CLIENT_SECRET --config config/wrangler.json
457
+ pnpm exec wrangler secret put SENDGRID_API_KEY --config config/wrangler.json
458
+ ```
459
+
460
+ ### 4. Aplicar Schema no D1 Remoto
461
+
462
+ ```bash
463
+ pnpm exec wrangler d1 execute nome-projeto-db --remote --file=seed.sql --config config/wrangler.json
464
+ ```
465
+
466
+ ### 5. Deploy
467
+
468
+ ```bash
469
+ pnpm run deploy
470
+ ```
471
+
472
+ ---
473
+
474
+ ## Troubleshooting
475
+
476
+ ### Erro: INTERNAL_ERROR 500
477
+
478
+ ```json
479
+ {"error":{"code":"INTERNAL_ERROR","message":"Internal server error","status":500}}
480
+ ```
481
+
482
+ **Causas possíveis:**
483
+
484
+ 1. **JWT_SECRET muito curto**
485
+ - O JWT_SECRET deve ter pelo menos 32 caracteres
486
+ - Verifique `config/.dev.vars`:
487
+ ```env
488
+ JWT_SECRET=super-secret-jwt-key-with-at-least-32-characters-for-security
489
+ ```
490
+
491
+ 2. **Variáveis de ambiente não carregadas**
492
+ - O Cloudflare Vite Plugin lê de `config/.dev.vars`, não da raiz
493
+ - Certifique-se que `config/.dev.vars` existe e tem todas as variáveis
494
+
495
+ 3. **Banco de dados sem tabelas**
496
+ - Execute: `pnpm db:push && pnpm db:seed`
497
+ - Verifique com: `sqlite3 .wrangler/state/v3/d1/miniflare-D1DatabaseObject/*.sqlite ".tables"`
498
+
499
+ 4. **configPath não configurado no vite.config.ts**
500
+ - Adicione ao plugin cloudflare:
501
+ ```typescript
502
+ cloudflare({
503
+ configPath: './config/wrangler.json',
504
+ })
505
+ ```
506
+
507
+ **Diagnóstico rápido:**
508
+ ```bash
509
+ # Ver logs detalhados
510
+ pnpm dev 2>&1 | head -50
511
+
512
+ # Verificar se config/.dev.vars existe
513
+ cat config/.dev.vars
514
+
515
+ # Verificar se banco tem tabelas
516
+ find .wrangler -name "*.sqlite" -exec sqlite3 {} ".tables" \;
517
+ ```
518
+
519
+ ---
520
+
521
+ ### Erro: "no such table: users"
522
+ - Verifique se `pnpm db:push` foi executado
523
+ - Verifique se o drizzle.config.ts aponta para o banco correto
524
+ - Copie o banco com dados para o arquivo que o plugin usa
525
+
526
+ ### Erro: "JWT_SECRET must be at least 32 characters"
527
+ - Atualize `JWT_SECRET` no `config/.dev.vars` com pelo menos 32 caracteres
528
+
529
+ ### Erro: "Rate limit exceeded"
530
+ - Reinicie o servidor para limpar o rate limiter
531
+ - Ou aumente o limite em `src/server/middleware/rate-limit.ts`
532
+
533
+ ### Redirect vai para produção após login
534
+ - Verifique se `APP_URL=http://localhost:8787` está em `config/.dev.vars`
535
+
536
+ ### Frontend carrega mas API dá 404
537
+ - Verifique se `configPath` foi adicionado ao cloudflare plugin no vite.config.ts
538
+
539
+ ### Múltiplas contas Cloudflare
540
+ - Defina `CLOUDFLARE_ACCOUNT_ID` antes de executar comandos wrangler
541
+
542
+ ---
543
+
544
+ ## Referência do init.sh
545
+
546
+ ```
547
+ BHono - Development Environment Setup
548
+
549
+ Usage: ./scripts/init.sh [OPTIONS]
550
+
551
+ Options:
552
+ --port PORT Set dev server port (default: 8787)
553
+ --google-id ID Set Google OAuth Client ID
554
+ --google-secret SEC Set Google OAuth Client Secret
555
+ --no-provision Skip Cloudflare resource provisioning
556
+ --skip-dev Don't start dev server after setup
557
+ --skip-seed Skip database seeding
558
+ --update Update dependencies
559
+ --help, -h Show this help message
560
+
561
+ Examples:
562
+ ./scripts/init.sh
563
+ ./scripts/init.sh --port 3000
564
+ ./scripts/init.sh --port 8787 --google-id 'xxx.apps.googleusercontent.com' --google-secret 'GOCSPX-xxx'
565
+ CLOUDFLARE_ACCOUNT_ID=xxx ./scripts/init.sh
566
+ ```