Status: Approved · v2 · SPEC-ARCH-FRONTEND-001
depends_on: SPEC-CONTRACTS-RESPONSE-001, SPEC-MOCKS-CONTRACTS-001
used_by: IS-ZERO-00.2, IS-MVP-01.1, IS-MVP-16.1
Arquitetura de services e dados no frontend
Camadas compartilhadas entre Expo e Next para trocar mocks pela API sem reescrever telas.
Arquitetura
Fluxo canônico
Route/Page
→ Screen/Feature Container
→ Feature Hook
→ Domain Service
→ HttpClient
→ ApiClient | MockClient
- Routes resolvem parâmetros e composição de alto nível.
- Screens coordenam estados visuais e componentes; não conhecem URLs.
- Hooks convertem
ApiResponseemidle/loading/success/empty/error, mutations erefetch. - Services expõem linguagem do domínio e conhecem paths/request/response.
- Clients executam transporte e autenticação.
- Componentes de
@raizfc/uirecebem props e nunca buscam dados.
Estrutura
packages/shared/src/
clients/
services/
hooks/
state/
navigation/
errors/
utils/
HttpClient
export interface HttpClient {
get<T extends object>(path: string, query?: QueryParams): Promise<ApiResponse<T>>;
post<T extends object>(path: string, body?: unknown, options?: RequestOptions): Promise<ApiResponse<T>>;
patch<T extends object>(path: string, body?: unknown, options?: RequestOptions): Promise<ApiResponse<T>>;
put<T extends object>(path: string, body?: unknown, options?: RequestOptions): Promise<ApiResponse<T>>;
delete<T extends object>(path: string, body?: unknown, options?: RequestOptions): Promise<ApiResponse<T>>;
}
Cache MVP
Cache simples em memória por query key, TTL curto para páginas públicas e invalidation explícita após mutations. Não duplicar server data em Zustand. TanStack Query pode ser adotado após a primeira capability se resolver um problema observado e for compatível com mobile/web.
Erros
Um mapper central transforma códigos em título, mensagem, ação e severity. Formulários recebem fieldErrors; 401 ativa AuthIntent; 403 explica permission; 404/merged/suspended usam estados específicos.
Auth e armazenamento
- ApiClient recebe
getAccessTokeneonUnauthorized; não importa storage concreto. - Mobile adapter usa SecureStore; web usa cookies/sessão conforme estratégia do app.
- Refresh é coordenado para evitar múltiplas renovações simultâneas.
Uploads
- Hook pede presign, envia para URL e confirma asset.
- Progress é UI state; asset final vem do backend.
- Falha de upload não cria entidade parcial sem regra explícita.
Testes
- Service com fake HttpClient.
- Hook com service injetado/provider.
- Screen com hooks/providers mockados.
- Contract assertions para paths e payloads críticos.
Anti-padrões
fetch/axios em screen.- Endpoint string em component/hook.
- Fixture importada por app.
- Toast/navigation dentro de service.
- DTO privado em página pública.
Critérios de aceite
- Mock/API trocados por factory/config.
- Loading/empty/error consistentes.
- Apps não importam mocks diretamente.
- Services são por domínio e testáveis.