Seed de Dados
O mecanismo de seed popula o banco de dados (D1 no backend e SQLite WASM no frontend) com dados de demonstração assim que a aplicação é acessada pela primeira vez em ambientes de desenvolvimento. Em produção, o seed é completamente desabilitado — todos os dados são reais, cadastrados pelos próprios usuários.
v0.54.0: Guard
ENVIRONMENT— o seed só roda seENVIRONMENT != 'production'(backend) eDEPLOY_ENV != 'prod'(frontend). Um deploy comNODE_ENV=productionautomaticamente desabilita o seed.
O seed cria 5 usuários com papéis distintos e senha compartilhada senha123: admin@neemias.local (ADMIN), chamador@neemias.local (CHAMADOR), relatorios@neemias.local (RELATORIOS), cadastro@neemias.local (CADASTRO), e um usuário multi-role com CHAMADOR + RESPONSAVEL simultâneos (v0.56.0+). Cada um possui o conjunto de permissões definido pelo sistema de RBAC (packages/permissions), permitindo testar os diferentes níveis de acesso logo após a inicialização.
Além dos usuários, o seed insere estudantes (padrão: 150 no backend — configurável via SEED_STUDENT_COUNT; 150 no seed demo do frontend via VITE_SEED_STUDENTS) com nomes realistas (combinação de ~100 nomes e ~50 sobrenomes brasileiros), avatares via DiceBear adventurer-neutral (cartoon infantil, sem gênero — zero mistura de traços — determinístico), dados de responsável, telefones, endereços completos, alergias, necessidades especiais e campos sociodemográficos completos (estrutura familiar, vulnerabilidade econômica, violência doméstica, situação escolar, etc.). São criadas 7 turmas (Berçário, Maternal, Jardim de Infância, Infantil, Juniores 1, Juniores 2, Pré-Adolescentes) com distribuição em curva sino (mais alunos nas turmas intermediárias) e 20 núcleos (14 na região Azul Celeste com crianças, 1 em cada uma das outras 6 regiões). O seed gera eventos de presença baseados em personas (consistente 60%, esporádico 25%, em risco 10%, crônico 5%) com efeito sazonal (queda de 15% na 4ª semana de cada ciclo), distribuídos em 4 slots de turma (Terça-feira 20h, Sexta-feira 19h30, Domingo 9h, Domingo 19h) com sessões pré-calculadas para as últimas 8 semanas (56 dias).
Teto de tamanho (Workers Free): o Worker da Cloudflare no plano gratuito tem orçamento de 10ms de CPU por invocação (erro 1102
exceededCpu). O seed gera ~11,6 statements D1 por estudante; 500 estudantes consomem ~11-14ms de CPU e morrem comINTERNAL_ERROR(medido localmente, 2026-08). O padrão de 150 estudantes fica em ~metade do orçamento com folga. Para seeds maiores (ex. 500), use o plano Workers Paid (30s de CPU) e ajusteSEED_STUDENT_COUNT.
A geração de dados é feita pelo pacote compartilhado @neemias/seed-data (packages/seed-data/), garantindo que frontend (SQLite WASM) e backend (D1) produzam dados idênticos a partir das mesmas funções puras.
O controle de ambiente é feito pela variável DEPLOY_ENV (ou VITE_DEPLOY_ENV no frontend). O frontend (app/src/modules/_dev/seed.ts) verifica se __DEPLOY_ENV__ === "prod" e aborta o seed nesse caso; caso contrário, popula o IndexedDB local via Dexie. O backend expõe o endpoint POST /api/v1/_seed (disponível apenas em desenvolvimento), que insere os mesmos dados diretamente no D1 da Cloudflare. Esse endpoint possui uma guarda de idempotência: se a tabela users já contiver registros, retorna HTTP 409 (ALREADY_SEEDED), evitando duplicação acidental.
O disparo é automático no primeiro acesso (frontend) ou sob demanda via chamada HTTP (backend). Para acionar o seed do backend manualmente, basta enviar um POST para /api/v1/_seed com o Worker rodando localmente (wrangler dev). A senha padrão pode ser alterada pela variável de ambiente SEED_PASSWORD no wrangler.toml ou .dev.vars.
Refresh semanal — demo sempre "vivo" (rolling seed)
Pós-1.0:
app.neemias.appeapi.neemias.approdam com configuração de produção (DEPLOY_ENV=production,AUTH_MODE=jwt), mas funcionam como ambiente de demonstração. Para que o demo pareça um sistema vivo, um cron semanal —[triggers] crons = ["0 0 * * 1"]emworkers/wrangler.toml(segunda-feira 00:00 UTC) — apaga todos os dados de demonstração e re-insere um dataset fresco ancorado emnew Date(): a janela de sessões (últimas 8 semanas) e a frequência (check-ins por persona) sempre parecem recentes.
Como funciona:
scheduledhandler (workers/src/index.ts): o cron da Cloudflare invoca o handler apenas quandoDEMO_MODE=true(var em[vars]dowrangler.toml). Além do cron,DEMO_MODE=truetambém registraPOST /api/v1/_demo/refresh, a versão manual do mesmo refresh (bearer token =SEED_PASSWORD, obrigatório — sem fallbacksenha123; o endpoint falha fechado e é limitado por IP) — útil para re-gerar o demo sob demanda sem esperar a segunda-feira. A rota HTTPPOST /api/v1/_seedcontinua restrita a dev (SEED_ENABLED+ENVIRONMENT), então produção configurada não expõe endpoint de seed.refreshDemoData()(workers/src/routes/seed.ts): chamawipeDemoTables()—DELETEem todas as tabelas demo/operacionais em ordem segura de FKs (filhos antes dos pais) — e depoisinsertDemoData(), as mesmas funções puras de@neemias/seed-datausadas pela rota HTTP.- Frequência gerada (novo): além de usuários/estudantes/sessões, o seed insere eventos de presença em
check_in_events(CHECK_IN/CHECK_OUT) por persona (consistente 60%, esporádico 25%, em risco 10%, crônico 5%) com efeito sazonal (queda de 15% na 4ª semana de cada ciclo de 4 semanas) e populasession_capacity.occupiedespelhando os check-ins — os relatórios e telas de presença das últimas 8 semanas mostram dados realistas.
Trade-offs:
- Mudanças feitas por visitantes do demo durante a semana são descartadas no refresh seguinte — o demo é sempre consistente com a baseline.
- O frontend em
app.neemias.appé um build de produção, mas comVITE_DEMO_MODE=trueroda o seed local rico (ver seção abaixo); sem o flag, o seed IndexedDB local não roda e os dados vêm da API. - O refresh é idempotente por construção (wipe + insert); se o cron falhar, a Cloudflare tenta novamente e o log
[demo-seed]registra o resultado.
Seed local no demo (VITE_DEMO_MODE)
O app em app.neemias.app é construído com VITE_DEMO_MODE=true (app/.env.production): mesmo sendo um build de produção, o frontend roda o seed local rico (app/src/modules/_dev/seed.ts, mesmas funções puras de @neemias/seed-data) — alunos com todos os campos (telefones, endereços, alergias, necessidades especiais, estrutura familiar, foto adventurer-neutral), turmas, núcleos, slots, sessões de 8 semanas e presenças (CHECK_IN → attendance_events MARK_PRESENT). É o que alimenta os relatórios (assiduidade, cobertura de chamada, engajamento por turma, membros, pico de frequência) — check-ins sozinhos não bastam.
- Limpeza antes do seed: quando a versão do seed local muda (constante
DEMO_SEED_VERSION, marcador emlocalStorage), o app apaga as tabelas demo locais (DELETE FROMemDEMO_WIPE_TABLES) e re-seeda — depois de um deploy novo, o demo aparece limpo; nos loads seguintes as mudanças dos visitantes são preservadas até o próximo deploy. - Sem duplicação com o backend: em demo mode o
hydrateStudents()(login) é pulado — o seed local é a fonte dos alunos; hidratar do D1 duplicaria (mesmos nomes, ids diferentes). - Credenciais:
VITE_SEED_PASSWORDdeve casar com oSEED_PASSWORDdo worker (default localsenha123); o unlock local de campos sensíveis usa a mesma senha do login do backend. - Builds de produção sem
VITE_DEMO_MODEcontinuam sem seed local (guardashouldSeedLocal()).
⚠️ Seção em expansão.
Fonte: workers/src/routes/seed.ts e app/src/modules/_dev/seed.ts