Buscar/Crie uma aplicação TypeScript full-stack com esquemas de API compartilhados entre servidor e cliente

Crie uma aplicação TypeScript full-stack com esquemas de API compartilhados entre servidor e cliente

Use ao criar ou alterar uma aplicação TypeScript full-stack. A IA define uma única vez cada requisição e resposta da API para rotas e hooks do cliente, verifica a autenticação antes de ler a entrada, mantém consistentes dependências, cache e estilos, e escreve testes rápidos.

Para usar estas regras de IA
## Mantenha as dependências entre pacotes em um só sentido e defina onde fica cada estado Organize a base de código para que as responsabilidades, a direção das dependências e a localização do estado permaneçam previsíveis conforme o sistema cresce. ### Estruture por responsabilidade - Dê a cada componente, hook, store, serviço e pacote um único propósito claro e prefira compor unidades pequenas a acrescentar ramificações e modos a uma unidade já complexa. - Mantenha o código da aplicação acima dos pacotes reutilizáveis no grafo de dependências; pacotes de nível inferior não devem importar módulos da aplicação. - Mantenha serviços isolados livres de frameworks de interface, catálogos, SDKs de provedores e mecanismos de execução não relacionados. - Compartilhe a autenticação por meio de uma única sessão compatível e de um modelo de dados comum, em vez de reimplementá-la em cada aplicação. ### Preserve a responsabilidade por tipos e estado - Defina interfaces explícitas para propriedades de componentes, estado, entradas de funções e valores de retorno. - Não use `any`; use `unknown` com guardas de tipo quando o tipo for realmente incerto. - Mantenha o estado do servidor na biblioteca de estado do servidor, o estado global do cliente em um store e o estado local de apresentação no componente. - Divida um store complexo em módulos de implementação e de tipos; persista somente o estado que precisa sobreviver a recarregamentos e selecione explicitamente os campos persistidos. ## Use os helpers e ferramentas compartilhados do repositório em vez de cópias locais Use uma única cadeia de ferramentas canônica e padrões de implementação compartilhados, em vez de criar substitutos locais. ### Aplique convenções de código consistentes - Use o gerenciador de pacotes, o formatador, o linter, o verificador de tipos e os comandos de auditoria escolhidos pelo repositório. - Use registro estruturado em vez de saída no console; wrappers de rota limitados ao escopo da solicitação devem anexar identificadores de solicitação automaticamente. - Siga padrões consistentes de nomenclatura e ordenação de importações; use importações apenas de tipos, asserções de constante, tipos explícitos de elementos de referência e TSDoc, em vez de comentários decorativos ou desestruturados. - Prefira importações absolutas. Crie um arquivo agregador somente quando uma pasta tiver pelo menos 3 exportações e não reexporte a partir de arquivos que não sejam agregadores. ### Reutilize auxiliares comprovados - Use auxiliares compartilhados para geração de IDs, atrasos, normalização de erros, extração de mensagens, clonagem profunda, filtragem de objetos, truncamento e espera progressiva entre novas tentativas com dispersão aleatória; não os recrie com pacotes locais ou lógica pontual. - Incorpore diretamente um auxiliar usado por 1 consumidor; mova-o para um módulo utilitário quando pelo menos 2 arquivos precisarem dele. - Extraia um componente quando ele ultrapassar aproximadamente 50 linhas, atender a pelo menos 2 chamadores ou possuir estado ou lógica; mantenha incorporado um fragmento puramente visual, de uso único, com menos de 10 linhas. ## Defina uma única vez cada requisição e resposta da API e justifique cada fetch direto Defina cada solicitação e resposta HTTP uma única vez para impedir que rotas e clientes adotem formatos de transmissão incompatíveis. ### Faça dos contratos a fonte oficial dos limites - Mantenha um módulo de contrato por família de recursos, com schemas separados para parâmetros de caminho, valores de consulta, corpo, cabeçalhos e resposta, combinados em um único contrato de rota. - Exporte schemas nomeados e aliases nomeados de tipos de entrada e saída para clientes e reutilize primitivas compartilhadas de identificadores, em vez de derivar tipos de transmissão pontuais ou redefinir identificadores baseados em strings. - Permita que validadores de domínio usem a biblioteca de schemas diretamente, mas mantenha schemas de limite de rota fora de manipuladores de rota e clientes. ### Controle exceções explicitamente - Exija uma anotação fundamentada imediatamente acima de qualquer uso direto excepcional de `fetch`, dupla conversão de tipo, leitura direta de JSON ou resposta deliberadamente não tipada. - Permita o uso direto de `fetch` somente em casos como streaming, transferência binária, upload multipart, URLs assinadas, redirecionamentos OAuth ou origens externas. - Permita leituras diretas de JSON somente para envelopes ou análise tolerante que não possa usar o analisador padrão, e respostas não tipadas somente para dados realmente opacos. - Mantenha exceções legítimas para arquivos inteiros em uma lista de permissões revisada, em vez de espalhar desvios por linha. - Faça uma auditoria rigorosa de limites falhar diante de justificativas ausentes, schemas locais de rota, leituras diretas, usos de `fetch` não aprovados e duplas conversões de tipo inseguras. ## Adicione uma rota de API e seu hook de cliente, começando pelo esquema Adicione uma funcionalidade de limite em uma sequência fixa para que autenticação, validação, tipagem de respostas e cache concordem de ponta a ponta. ### Siga a sequência de implementação 1. Crie o contrato e seus tipos nomeados de entrada e saída. 2. Envolva a rota no wrapper canônico de contexto da solicitação e tratamento de erros, compondo middlewares compartilhados de autenticação, limitação de taxa e controle de acesso, em vez de reimplementá-los em cada rota. 3. Autentique e autorize antes de analisar entradas não confiáveis e então analise todas as partes da solicitação por meio do contrato. 4. Retorne exatamente a estrutura JSON declarada pelo schema de resposta. 5. Adicione um hook de cliente tipado que envie e valide dados por meio do mesmo contrato. 6. Use o hook no componente e exiba sua mensagem de erro tipada. ### Revise schemas como migrações - Diferencie omissão de `null`; combinar uma declaração opcional com uma anulável cria um terceiro estado e deve ser intencional. - Compare cada ponto de chamada da resposta com o schema de resposta declarado. - Defina limites explícitos para strings, arrays, valores e tamanhos, com erros descritivos específicos de cada campo. - Trate schemas desconhecidos como excepcionais e documente por que a carga útil é opaca; prefira uniões discriminadas quando o formato de transmissão contiver um discriminador. - Use revisão humana para a qualidade semântica; auditorias estruturais não conseguem detectar todo limite fraco nem toda estrutura de resposta imprecisa. ## Mantenha o cache de consultas correto após cancelamentos e atualizações otimistas Torne explícitos o cancelamento, o cache, a invalidação e as atualizações otimistas, em vez de ocultar o estado do servidor no estado do componente. ### Crie hooks e chaves de consulta estáveis - Use uma referência quando um callback estável precisar ler a entrada mais recente e atualize essa referência quando a entrada mudar. - Encaminhe o sinal de cancelamento de cada função de consulta e dê a cada consulta um intervalo explícito de atualização. - Crie chaves hierárquicas desde uma raiz, passando por prefixos de lista e detalhe, para invalidação direcionada, e mantenha dados anteriores somente para consultas com chaves variáveis, não para consultas estáticas. ### Reconcilie mutações com segurança - Antes de uma atualização otimista, cancele as consultas afetadas e salve o valor anterior do cache para que ele possa ser restaurado em caso de erro. - Reconcilie e invalide na conclusão, não apenas no sucesso, pois tanto o sucesso quanto a falha exigem consistência do cache. - Prefira invalidação direcionada a invalidar toda a árvore de recursos. - Não adicione métodos ou objetos estáveis de mutação desnecessariamente às dependências de callbacks. - Encaminhe JSON da mesma origem pelo auxiliar de solicitação tipado; exceções que usem `fetch` diretamente devem seguir a política de limites documentada. ## Deixe a aparência dos componentes compartilhados dentro deles e ajuste-a por props Trate a aparência compartilhada de um componente como uma única fonte oficial pertencente ao componente, em vez de delegá-la a cada consumidor. ### Mantenha a apresentação local e combinável - Não modifique estilos globais para uma funcionalidade local; limite o estilo aos componentes. - Use o auxiliar de classes condicionais do projeto e a forma abreviada de dimensões, em vez de duplicar a lógica de composição de classes. - Use ferramentas de variantes somente quando um componente tiver pelo menos 2 variantes reais; use uma classe condicional simples para alternar um único estado. - Importe componentes compartilhados pelo ponto de entrada público oficialmente suportado, em vez de subcaminhos internos. - Verifique se as variáveis CSS referenciadas existem, pois uma variável indefinida pode recorrer silenciosamente a uma cor não pretendida. ### Expresse a intenção por meio de propriedades - Exponha propriedades para erros, elementos acessórios, rótulos, dicas, estado obrigatório e modos de comportamento; reserve substituições de classe feitas pelo consumidor para layout e dimensionamento, não para bordas, preenchimentos, raios, alturas, cores ou tratamento de foco canônicos. - Use propriedades de união discriminada para modos, em vez de manter componentes quase duplicados. - Use o wrapper canônico de campo rotulado dentro do corpo de modais para que os espaçamentos laterais dos campos se alinhem aos cabeçalhos e rodapés. - Remova variantes legadas após a migração, em vez de deixar caminhos paralelos no sistema de design. ## Escreva testes rápidos no Vitest com mocks compartilhados e temporizadores simulados Use o executor de testes padrão do repositório, recursos globais de teste e padrões de temporização determinísticos. ### Isole o comportamento - Nomeie cada teste ao lado de seu arquivo-fonte usando o sufixo de teste padrão do repositório. - Reutilize mocks globais e fábricas compartilhadas, substituindo um deles somente quando um teste precisar de comportamento diferente; limpe o estado dos mocks antes de cada teste e defina explicitamente valores de retorno por teste. - Use simulações para catálogos pesados e dependências de provedores quando o teste não os exercitar. - Use um ambiente de execução de servidor, a menos que APIs de navegador sejam necessárias. - Evite temporizadores reais; use temporizadores simulados ou o menor atraso determinístico exigido pelo comportamento. ### Evite recarregamentos dispendiosos de módulos - No Vitest, prefira mocks içados e importações estáticas. - Não combine redefinições de módulos, mocks tardios e importações dinâmicas, e não importe implementações reais por meio de `importActual` quando mocks explícitos forem suficientes. - Mantenha explícitos os mocks de autenticação e registro de eventos, em vez de chamar auxiliares que ocultem simulações tardias. - Execute a auditoria rigorosa dos limites da API com os testes relevantes antes da revisão. ## Adicione integrações sem converter variáveis antes de serem resolvidas Crie integrações na ordem das dependências e preserve referências não resolvidas até a execução. ### Siga a sequência de integração 1. Defina e registre ferramentas com identificadores `snake_case` estáveis. 2. Adicione o bloco consumidor e registre-o na ordem canônica. 3. Adicione o ícone e os metadados necessários. 4. Adicione um acionador somente quando a integração precisar de um. 5. Verifique o comportamento do serviço em documentação oficial da API. ### Respeite os momentos do ciclo de vida - Diferencie a configuração no momento da serialização da resolução de parâmetros no momento da execução. - Nunca converta tipos ao serializar valores não resolvidos; isso pode destruir referências dinâmicas. - Faça conversões numéricas e de outros tipos somente depois que as variáveis forem resolvidas durante a execução. - Mantenha sincronizados os metadados de ferramenta, bloco, acionador, autenticação e entrada de arquivo. - Execute linting, verificações de tipos, testes e auditorias rigorosas de limites; depois revise as alterações finais quanto à consistência de contratos, cache, estilo e catálogos.