Skip to content

Padrões de Código: Convenções TypeScript, Estrutura de Arquivos e Códigos de Erro ​

O Que Você Vai Aprender ​

  • ✅ Entender as convenções de codificação que o código gerado pelo AI App Factory deve seguir
  • ✅ Dominar as convenções de tipos e nomenclatura do TypeScript
  • ✅ Conhecer a estrutura de arquivos e organização do código front-end e back-end
  • ✅ Aprender a usar o sistema unificado de códigos de erro

Conceito Central ​

O código gerado pelo AI App Factory deve seguir convenções de codificação unificadas para garantir qualidade consistente, manutenibilidade e facilidade de compreensão. Essas convenções abrangem formatação geral, sistema de tipos TypeScript, design de arquitetura front-end e back-end, estilo de comentários e mecanismos de tratamento de erros.

Por que precisamos de padrões de código?

  • Consistência: Todo código gerado pelos Agents segue o mesmo estilo, reduzindo a curva de aprendizado
  • Manutenibilidade: Nomenclatura e estrutura claras facilitam modificações futuras
  • Legibilidade: Código padronizado permite que membros da equipe entendam rapidamente a intenção
  • Segurança: Sistema de tipos rigoroso e tratamento de erros reduzem erros em tempo de execução

1. Convenções Gerais ​

1.1 Linguagem e Formatação ​

ItemConvenção
LinguagemTypeScript (modo estrito)
Indentação2 espaços
Fim de linhaLF (Unix)
CodificaçãoUTF-8
Comprimento máximo de linha100 caracteres (código), 80 caracteres (comentários)
Ponto e vírgulaObrigatório
AspasAspas simples (strings), aspas duplas (atributos JSX)

1.2 Convenções de Nomenclatura ​

TipoEstiloExemplo
Nome de arquivo (comum)camelCase.tsuserService.ts, apiClient.ts
Nome de arquivo (componente)PascalCase.tsxButton.tsx, HomeScreen.tsx
Nome de arquivo (teste)*.test.ts/tsxuser.test.ts, Button.test.tsx
VariávelcamelCaseuserName, isLoading
FunçãocamelCasegetUserById, formatDate
Classe/Interface/TipoPascalCaseUser, ApiResponse, CreateItemDto
ConstanteUPPER_SNAKE_CASEAPI_URL, MAX_RETRY_COUNT
Propriedade privadaSem prefixo underscoreUse a palavra-chave private do TypeScript
Variável booleanaPrefixo is/has/canisActive, hasPermission, canEdit
Manipulador de eventoPrefixo handlehandleClick, handleSubmit
HookPrefixo useuseItems, useAuth

Dicas de Nomenclatura

Uma boa nomenclatura deve ser autoexplicativa, sem necessidade de comentários adicionais para explicar o propósito. Por exemplo, isValid é mais claro que check, e getUserById é mais específico que getData.

1.3 Organização de Arquivos ​

Cada arquivo com responsabilidade única:

  • Um componente por arquivo
  • Um serviço por arquivo
  • Tipos relacionados podem ficar no mesmo arquivo types.ts

Ordem de importações:

typescript
// 1. Módulos nativos do Node.js
import path from 'path';

// 2. Dependências externas
import express from 'express';
import { z } from 'zod';

// 3. Módulos internos (caminho absoluto)
import { prisma } from '@/lib/prisma';
import { config } from '@/config';

// 4. Importações com caminho relativo
import { UserService } from './userService';
import type { User } from './types';

2. Convenções TypeScript ​

2.1 Definição de Tipos ​

Prefira interface para definir tipos de objeto:

typescript
// ✅ Bom
interface User {
  id: number;
  name: string;
  email: string;
}

// ❌ Evite (exceto quando precisar de union types ou mapped types)
type User = {
  id: number;
  name: string;
  email: string;
};

Defina tipos para todas as APIs públicas:

typescript
// ✅ Bom
interface CreateUserDto {
  name: string;
  email: string;
}

interface ApiResponse<T> {
  success: boolean;
  data?: T;
  error?: {
    message: string;
    details?: unknown;
  };
}

function createUser(data: CreateUserDto): Promise<ApiResponse<User>> {
  // ...
}

// ❌ Evite
function createUser(data: any): Promise<any> {
  // ...
}

2.2 Asserção de Tipos ​

Proibido usar any

No código gerado é absolutamente proibido usar o tipo any. Deve-se usar unknown e adicionar type guards.

Evite usar any:

typescript
// ✅ Bom
function parseJson(text: string): unknown {
  return JSON.parse(text);
}

const data = parseJson(text);
if (isUser(data)) {
  // data é inferido como User
}

// ❌ Evite
const data: any = JSON.parse(text);

Use type guards:

typescript
// ✅ Bom
function isUser(value: unknown): value is User {
  return (
    typeof value === 'object' &&
    value !== null &&
    'id' in value &&
    'name' in value
  );
}

// ❌ Evite
const user = data as User; // asserção insegura

2.3 Generics ​

Use nomes significativos para parâmetros genéricos:

typescript
// ✅ Bom
interface Repository<TEntity> {
  findById(id: number): Promise<TEntity | null>;
  save(entity: TEntity): Promise<TEntity>;
}

// ❌ Evite
interface Repository<T> {
  findById(id: number): Promise<T | null>;
  save(entity: T): Promise<T>;
}

3. Convenções Back-end ​

3.1 Rotas Express ​

Use Router para organizar rotas:

typescript
// ✅ Bom
// src/routes/items.ts
import { Router } from 'express';
import { itemController } from '@/controllers/item';
import { validateRequest } from '@/middleware/validation';
import { createItemSchema, updateItemSchema } from '@/validators/item';

const router = Router();

router.get('/', itemController.list);
router.get('/:id', itemController.getById);
router.post('/', validateRequest(createItemSchema), itemController.create);
router.put('/:id', validateRequest(updateItemSchema), itemController.update);
router.delete('/:id', itemController.remove);

export default router;

Nomenclatura RESTful:

typescript
// ✅ Bom
GET    /api/items         // Lista
GET    /api/items/:id     // Detalhes
POST   /api/items         // Criar
PUT    /api/items/:id     // Atualizar
DELETE /api/items/:id     // Excluir

// ❌ Evite
GET    /api/getItems
POST   /api/createItem
POST   /api/items/delete/:id

3.2 Controllers ​

Mantenha os controllers simples:

typescript
// ✅ Bom
export const itemController = {
  async list(req: Request, res: Response, next: NextFunction) {
    try {
      const items = await itemService.findAll();
      res.json({ success: true, data: items });
    } catch (error) {
      next(error);
    }
  },

  async create(req: Request, res: Response, next: NextFunction) {
    try {
      const item = await itemService.create(req.body);
      res.status(201).json({ success: true, data: item });
    } catch (error) {
      next(error);
    }
  },
};

3.3 Camada de Serviço ​

Lógica de negócio na camada de serviço:

typescript
// ✅ Bom
// src/services/item.ts
export const itemService = {
  async findAll() {
    return prisma.item.findMany({
      orderBy: { createdAt: 'desc' },
    });
  },

  async findById(id: number) {
    const item = await prisma.item.findUnique({ where: { id } });
    if (!item) {
      throw new AppError(404, 'Item não encontrado');
    }
    return item;
  },

  async create(data: CreateItemDto) {
    return prisma.item.create({ data });
  },
};

3.4 Tratamento de Erros ​

Use uma classe de erro unificada:

typescript
// src/lib/errors.ts
export class AppError extends Error {
  constructor(
    public statusCode: number,
    public message: string,
    public details?: unknown
  ) {
    super(message);
    this.name = 'AppError';
  }
}

// Uso
throw new AppError(404, 'Item não encontrado');
throw new AppError(400, 'Validação falhou', errors);

Middleware global de tratamento de erros:

typescript
// src/middleware/errorHandler.ts
export function errorHandler(
  error: Error,
  req: Request,
  res: Response,
  next: NextFunction
) {
  if (error instanceof AppError) {
    return res.status(error.statusCode).json({
      success: false,
      error: {
        message: error.message,
        details: error.details,
      },
    });
  }

  // Ocultar erros internos em produção
  const message =
    process.env.NODE_ENV === 'production'
      ? 'Erro interno do servidor'
      : error.message;

  res.status(500).json({
    success: false,
    error: { message },
  });
}

4. Convenções Front-end ​

4.1 Estrutura de Componentes ​

Formato de componente funcional:

tsx
// ✅ Bom
interface ButtonProps {
  children: React.ReactNode;
  onPress: () => void;
  loading?: boolean;
  disabled?: boolean;
}

export function Button({
  children,
  onPress,
  loading = false,
  disabled = false,
}: ButtonProps) {
  return (
    <TouchableOpacity
      onPress={onPress}
      disabled={loading || disabled}
      style={styles.container}
    >
      {loading ? (
        <ActivityIndicator />
      ) : (
        <Text style={styles.text}>{children}</Text>
      )}
    </TouchableOpacity>
  );
}

const styles = StyleSheet.create({
  container: {
    // ...
  },
  text: {
    // ...
  },
});

4.2 Convenções de Hooks ​

Hooks personalizados retornam objetos:

typescript
// ✅ Bom
export function useItems() {
  const [items, setItems] = useState<Item[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const refresh = async () => {
    // ...
  };

  const create = async (data: CreateItemDto) => {
    // ...
  };

  return {
    items,
    loading,
    error,
    refresh,
    create,
  };
}

4.3 Convenções de Estilos ​

Use StyleSheet:

typescript
// ✅ Bom
const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 16,
  },
  title: {
    fontSize: 18,
    fontWeight: 'bold',
  },
});

// ❌ Evite estilos inline
<View style={{ flex: 1, padding: 16 }}>

Use sistema de temas:

typescript
// src/styles/theme.ts
export const theme = {
  colors: {
    primary: '#2563eb',
    text: {
      primary: '#1e293b',
      secondary: '#64748b',
    },
    background: '#ffffff',
  },
  spacing: {
    xs: 4,
    sm: 8,
    md: 16,
    lg: 24,
    xl: 32,
  },
  fontSize: {
    sm: 14,
    base: 16,
    lg: 18,
    xl: 20,
  },
};

4.4 Navegação ​

Parâmetros de navegação com type safety:

typescript
// src/navigation/types.ts
export type RootStackParamList = {
  Home: undefined;
  Detail: { id: number };
  Create: undefined;
};

// Uso
const navigation = useNavigation<NativeStackNavigationProp<RootStackParamList>>();
navigation.navigate('Detail', { id: 1 });

5. Convenções Prisma ​

5.1 Definição de Schema ​

Nomes de modelos em PascalCase singular:

prisma
// ✅ Bom
model User {
  id        Int      @id @default(autoincrement())
  email     String   @unique
  name      String
  posts     Post[]
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

model Post {
  id        Int      @id @default(autoincrement())
  title     String
  content   String?
  author    User     @relation(fields: [authorId], references: [id])
  authorId  Int
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

5.2 Convenções de Consulta ​

Use select para limitar campos retornados:

typescript
// ✅ Bom (retorna apenas campos necessários)
const users = await prisma.user.findMany({
  select: {
    id: true,
    name: true,
    email: true,
  },
});

// ❌ Evite (retorna todos os campos incluindo informações sensíveis)
const users = await prisma.user.findMany();

6. Convenções de Comentários ​

6.1 Quando Adicionar Comentários ​

Cenários que precisam de comentários:

  • Lógica de negócio complexa
  • Decisões de design não óbvias
  • Razões para otimização de desempenho
  • Interfaces públicas de API

Cenários que não precisam de comentários:

  • Código autoexplicativo
  • Getters/setters simples
  • Implementações óbvias

6.2 Formato de Comentários ​

typescript
// ✅ Bom - explica o porquê
// Usa atualização otimista para melhorar UX, reverte em caso de falha
const optimisticUpdate = async (id: number, data: UpdateDto) => {
  const previousData = items;
  setItems(prev => prev.map(item => item.id === id ? { ...item, ...data } : item));

  try {
    await api.update(id, data);
  } catch {
    setItems(previousData); // reverte
    throw new Error('Atualização falhou');
  }
};

// ❌ Evite - explica o quê (o código já diz)
// Define items
setItems(newItems);

Princípio de Comentários

Comentários devem explicar por quê e não o quê. Bom código deve ser autoexplicativo, comentários apenas complementam informações que não podem ser vistas diretamente no código.


7. Convenções de Códigos de Erro ​

7.1 Estrutura do Código de Erro ​

Definição do formato:

[MÓDULO_NEGÓCIO]_[TIPO_ERRO]_[ERRO_ESPECÍFICO]

Exemplo: AUTH_VALIDATION_INVALID_EMAIL

Convenções de nomenclatura:

  • Maiúsculas: Use SCREAMING_SNAKE_CASE
  • Módulo de negócio: 2-4 caracteres, representa o módulo funcional (ex: AUTH, USER, ITEM)
  • Tipo de erro: Tipo genérico de erro (ex: VALIDATION, NOT_FOUND, FORBIDDEN)
  • Erro específico: Descrição detalhada (opcional)

7.2 Tipos de Erro Padrão ​

1. Erros de Validação (VALIDATION) ​

Código HTTP: 400

Código de ErroDescriçãoCenário de Exemplo
[MODULE]_VALIDATION_REQUIREDCampo obrigatório ausenteNão forneceu title ao criar
[MODULE]_VALIDATION_INVALID_FORMATFormato incorretoFormato de email inválido
[MODULE]_VALIDATION_OUT_OF_RANGEFora do intervaloamount < 0 ou > 10000
[MODULE]_VALIDATION_DUPLICATEValor duplicadoEmail já existe

Exemplos:

typescript
AUTH_VALIDATION_REQUIRED       // Campo obrigatório ausente
AUTH_VALIDATION_INVALID_EMAIL  // Formato de email inválido
ITEM_VALIDATION_OUT_OF_RANGE   // Valor fora do intervalo

2. Erros de Não Encontrado (NOT_FOUND) ​

Código HTTP: 404

Código de ErroDescriçãoCenário de Exemplo
[MODULE]_NOT_FOUNDRecurso não existeID consultado não existe
[MODULE]_ROUTE_NOT_FOUNDRota não existeAcesso a endpoint não definido

Exemplos:

typescript
ITEM_NOT_FOUND   // Item ID não existe
USER_NOT_FOUND   // User ID não existe

3. Erros de Permissão (FORBIDDEN / UNAUTHORIZED) ​

Código HTTP: 401 (não autenticado), 403 (sem permissão)

Código de ErroDescriçãoCenário de Exemplo
AUTH_UNAUTHORIZEDNão logado ou Token inválidoJWT expirado
[MODULE]_FORBIDDENSem permissão de acessoTentativa de acessar dados de outro usuário

Exemplos:

typescript
AUTH_UNAUTHORIZED     // Token expirado ou ausente
ITEM_FORBIDDEN        // Tentativa de excluir Item de outro usuário

4. Erros de Conflito (CONFLICT) ​

Código HTTP: 409

Código de ErroDescriçãoCenário de Exemplo
[MODULE]_CONFLICT_DUPLICATEConflito de recursoCriar recurso já existente
[MODULE]_CONFLICT_STATEConflito de estadoOperação não compatível com estado atual

Exemplos:

typescript
USER_CONFLICT_DUPLICATE   // Email já registrado
ITEM_CONFLICT_STATE       // Projeto concluído não pode ser excluído

5. Erros de Servidor (INTERNAL_ERROR) ​

Código HTTP: 500

Código de ErroDescriçãoCenário de Exemplo
INTERNAL_ERRORErro interno desconhecidoFalha na conexão com banco de dados
DATABASE_ERRORErro de banco de dadosFalha na consulta Prisma
EXTERNAL_SERVICE_ERRORErro de serviço externoFalha em API de terceiros

Exemplos:

typescript
INTERNAL_ERROR             // Erro genérico do servidor
DATABASE_ERROR             // Falha na operação do banco de dados
EXTERNAL_SERVICE_ERROR     // Falha na chamada de API de terceiros

6. Erros de Rate Limit (RATE_LIMIT) ​

Código HTTP: 429

Código de ErroDescriçãoCenário de Exemplo
RATE_LIMIT_EXCEEDEDLimite de frequência excedidoMais de 100 requisições em 1 minuto

7.3 Formato de Resposta de Erro ​

Estrutura de resposta padrão:

typescript
interface ErrorResponse {
  success: false;
  error: {
    code: string;           // Código de erro
    message: string;        // Mensagem amigável ao usuário
    details?: unknown;      // Detalhes (opcional, apenas em desenvolvimento)
    timestamp?: string;     // Timestamp (opcional)
    path?: string;          // Caminho da requisição (opcional)
  };
}

Exemplos de resposta:

Erro de validação:

json
{
  "success": false,
  "error": {
    "code": "ITEM_VALIDATION_REQUIRED",
    "message": "Campo obrigatório ausente: title",
    "details": {
      "field": "title",
      "constraint": "required"
    }
  }
}

Erro de não encontrado:

json
{
  "success": false,
  "error": {
    "code": "ITEM_NOT_FOUND",
    "message": "Item com ID 123 não encontrado"
  }
}

Erro de servidor:

json
{
  "success": false,
  "error": {
    "code": "DATABASE_ERROR",
    "message": "Operação no banco de dados falhou, tente novamente mais tarde"
  }
}

7.4 Definição de Classes de Erro ​

src/lib/errors.ts:

typescript
export class AppError extends Error {
  constructor(
    public statusCode: number,
    public code: string,
    public message: string,
    public details?: unknown
  ) {
    super(message);
    this.name = 'AppError';
  }
}

// Erro de validação
export class ValidationError extends AppError {
  constructor(code: string, message: string, details?: unknown) {
    super(400, code, message, details);
  }
}

// Erro de não encontrado
export class NotFoundError extends AppError {
  constructor(code: string, message: string) {
    super(404, code, message);
  }
}

// Erro de permissão
export class UnauthorizedError extends AppError {
  constructor(message: string = 'Acesso não autorizado') {
    super(401, 'AUTH_UNAUTHORIZED', message);
  }
}

export class ForbiddenError extends AppError {
  constructor(code: string, message: string) {
    super(403, code, message);
  }
}

// Erro de conflito
export class ConflictError extends AppError {
  constructor(code: string, message: string) {
    super(409, code, message);
  }
}

// Erro de servidor
export class InternalError extends AppError {
  constructor(message: string = 'Erro interno do servidor') {
    super(500, 'INTERNAL_ERROR', message);
  }
}

7.5 Constantes de Códigos de Erro ​

src/constants/error-codes.ts:

typescript
// Códigos de erro do módulo de itens
export const ITEM_ERRORS = {
  NOT_FOUND: 'ITEM_NOT_FOUND',
  VALIDATION_REQUIRED: 'ITEM_VALIDATION_REQUIRED',
  VALIDATION_INVALID_AMOUNT: 'ITEM_VALIDATION_INVALID_AMOUNT',
  FORBIDDEN: 'ITEM_FORBIDDEN',
} as const;

// Códigos de erro do módulo de usuários
export const USER_ERRORS = {
  NOT_FOUND: 'USER_NOT_FOUND',
  CONFLICT_DUPLICATE: 'USER_CONFLICT_DUPLICATE',
  VALIDATION_INVALID_EMAIL: 'USER_VALIDATION_INVALID_EMAIL',
} as const;

// Códigos de erro de autenticação
export const AUTH_ERRORS = {
  UNAUTHORIZED: 'AUTH_UNAUTHORIZED',
  VALIDATION_INVALID_EMAIL: 'AUTH_VALIDATION_INVALID_EMAIL',
  VALIDATION_REQUIRED: 'AUTH_VALIDATION_REQUIRED',
} as const;

7.6 Exemplo de Uso ​

Camada de Serviço:

typescript
import { NotFoundError, ValidationError } from '@/lib/errors';
import { ITEM_ERRORS } from '@/constants/error-codes';

export const itemService = {
  async findById(id: number) {
    const item = await prisma.item.findUnique({ where: { id } });

    if (!item) {
      throw new NotFoundError(
        ITEM_ERRORS.NOT_FOUND,
        `Item com ID ${id} não encontrado`
      );
    }

    return item;
  },

  async create(data: CreateItemDto) {
    if (!data.title) {
      throw new ValidationError(
        ITEM_ERRORS.VALIDATION_REQUIRED,
        'Campo obrigatório ausente: title',
        { field: 'title' }
      );
    }

    if (data.amount < 0) {
      throw new ValidationError(
        ITEM_ERRORS.VALIDATION_INVALID_AMOUNT,
        'O valor não pode ser negativo',
        { field: 'amount', value: data.amount }
      );
    }

    return prisma.item.create({ data });
  },
};

7.7 Tratamento de Erros no Front-end ​

Mapeamento de códigos de erro:

typescript
// client/src/constants/error-messages.ts
export const ERROR_MESSAGES: Record<string, string> = {
  // Erros de item
  ITEM_NOT_FOUND: 'Item não existe',
  ITEM_VALIDATION_REQUIRED: 'Por favor, preencha os campos obrigatórios',
  ITEM_VALIDATION_INVALID_AMOUNT: 'O valor deve ser maior que 0',

  // Erros de usuário
  USER_NOT_FOUND: 'Usuário não existe',
  USER_CONFLICT_DUPLICATE: 'Este email já está registrado',
  USER_VALIDATION_INVALID_EMAIL: 'Formato de email inválido',

  // Erros de autenticação
  AUTH_UNAUTHORIZED: 'Por favor, faça login primeiro',

  // Erros genéricos
  INTERNAL_ERROR: 'Erro no servidor, tente novamente mais tarde',
  RATE_LIMIT_EXCEEDED: 'Muitas requisições, tente novamente mais tarde',

  // Erro padrão
  DEFAULT: 'Operação falhou, tente novamente mais tarde',
};

export function getErrorMessage(code: string): string {
  return ERROR_MESSAGES[code] || ERROR_MESSAGES.DEFAULT;
}

Cliente API:

typescript
// client/src/api/client.ts
import axios, { AxiosError } from 'axios';
import { getErrorMessage } from '@/constants/error-messages';

const apiClient = axios.create({
  baseURL: process.env.EXPO_PUBLIC_API_URL,
});

// Interceptor de resposta
apiClient.interceptors.response.use(
  (response) => response,
  (error: AxiosError<ErrorResponse>) => {
    const errorCode = error.response?.data?.error?.code || 'DEFAULT';
    const errorMessage = getErrorMessage(errorCode);

    // Retorna erro padronizado
    return Promise.reject({
      code: errorCode,
      message: errorMessage,
      originalError: error,
    });
  }
);

8. Práticas Proibidas ​

As seguintes práticas são absolutamente proibidas no código gerado:

  1. Usar tipo any - Use unknown e adicione type guards
  2. Hardcode de informações sensíveis - Use variáveis de ambiente
  3. Ignorar tratamento de erros - Todas as operações async precisam de try-catch
  4. Usar console.log para debug - Use logs estruturados
  5. Estilos inline - Use StyleSheet
  6. Pular definição de tipos - Todas as interfaces públicas precisam de tipos
  7. Usar var - Use const ou let
  8. Usar == - Use ===
  9. Modificar parâmetros de função - Crie novos objetos/arrays
  10. Aninhamento de if maior que 3 níveis - Retorne antecipadamente ou divida em funções

Perguntas Frequentes ​

1. Por que é proibido usar o tipo any? ​

Segurança de Tipos

O tipo any ignora a verificação de tipos do TypeScript, causando erros em tempo de execução. Usar unknown e adicionar type guards mantém a flexibilidade enquanto garante segurança de tipos.

Comparação de exemplos:

typescript
// ❌ Perigoso
function processData(data: any) {
  return data.value; // Se data não tiver propriedade value, só dará erro em runtime
}

// ✅ Seguro
function processData(data: unknown) {
  if (typeof data === 'object' && data !== null && 'value' in data) {
    return (data as { value: string }).value;
  }
  throw new Error('Formato de dados inválido');
}

2. Como compartilhar definições de códigos de erro entre front-end e back-end? ​

Pode ser compartilhado das seguintes formas:

  1. Compartilhamento de arquivos de tipos: Exporte tipos de códigos de erro no projeto back-end, front-end obtém via API ou sincroniza manualmente
  2. Monorepo: Front-end e back-end no mesmo repositório, pode referenciar diretamente
  3. OpenAPI/Swagger: Defina códigos de erro na documentação da API, front-end gera tipos automaticamente

3. Como suportar múltiplos idiomas nos códigos de erro? ​

Abordagem recomendada:

typescript
// Back-end: retorna código de erro e parâmetros
{
  "success": false,
  "error": {
    "code": "ITEM_VALIDATION_REQUIRED",
    "message": "Missing required field",
    "details": { "field": "title" }
  }
}

// Front-end: mapeia código de erro para mensagem localizada
export const ERROR_MESSAGES = {
  en: { ITEM_VALIDATION_REQUIRED: 'Missing required field' },
  pt: { ITEM_VALIDATION_REQUIRED: 'Campo obrigatório ausente' },
};

4. Como debugar problemas relacionados a códigos de erro? ​

  1. Verifique logs do back-end: Confirme se o código de erro está sendo lançado corretamente
  2. Verifique mapeamento no front-end: Confirme se há entrada correspondente em ERROR_MESSAGES
  3. Use painel de rede: Veja a resposta completa de erro da API
  4. Mostre details em desenvolvimento: Em ambiente de desenvolvimento, informações detalhadas de erro são retornadas

Resumo da Aula ​

Nesta aula, explicamos detalhadamente as convenções que o código gerado pelo AI App Factory deve seguir:

  • ✅ Convenções gerais: Formatação de linguagem, convenções de nomenclatura, organização de arquivos
  • ✅ Convenções TypeScript: Definição de tipos, asserção de tipos, generics
  • ✅ Convenções back-end: Rotas Express, controllers, camada de serviço, tratamento de erros
  • ✅ Convenções front-end: Estrutura de componentes, convenções de hooks, convenções de estilos, navegação
  • ✅ Convenções Prisma: Definição de schema, convenções de consulta
  • ✅ Convenções de comentários: Quando adicionar comentários, formato de comentários
  • ✅ Convenções de códigos de erro: Estrutura de códigos de erro, tipos de erro padrão, formato de resposta de erro
  • ✅ Práticas proibidas: 10 práticas absolutamente proibidas

Seguir essas convenções garante que o código gerado tenha qualidade consistente, seja manutenível e fácil de entender.


Próxima Aula ​

Na próxima aula aprenderemos Detalhes da Stack Tecnológica.

Você aprenderá:

  • A stack tecnológica usada nos aplicativos gerados
  • A combinação Node.js + Express + Prisma + React Native
  • Características e melhores práticas de cada tecnologia

Apêndice: Referência de Código Fonte ​

Clique para expandir e ver localização do código fonte

Atualizado em: 2026-01-29

FuncionalidadeCaminho do ArquivoLinhas
Documentação de padrões de códigosource/hyz1992/agent-app-factory/policies/code-standards.md1-604
Convenções de códigos de errosource/hyz1992/agent-app-factory/policies/error-codes.md1-469

Convenções principais:

  • Padrões de código: Convenções gerais, convenções TypeScript, convenções back-end, convenções front-end, convenções Prisma, convenções de comentários, configuração ESLint, práticas proibidas
  • Convenções de códigos de erro: Estrutura de códigos de erro, tipos de erro padrão (VALIDATION, NOT_FOUND, FORBIDDEN, CONFLICT, INTERNAL_ERROR, RATE_LIMIT), formato de resposta de erro, tratamento de erros front-end e back-end

Configurações principais:

  • ESLint back-end: Regra @typescript-eslint/no-explicit-any definida como error
  • ESLint front-end: Regra @typescript-eslint/no-explicit-any definida como error
  • Formato de código de erro: [MODULE]_[ERROR_TYPE]_[SPECIFIC]
  • Estrutura de resposta de erro: Contém success, error.code, error.message, error.details