Skip to content

Estándares de Codificación

Esta guía establece los estándares de codificación para contribuir a Hatcher, asegurando consistencia y calidad en todo el codebase.

Configuración General

TypeScript

  • Usar TypeScript para todo el código nuevo
  • Configuración strict habilitada
  • Preferir tipos explícitos sobre any
typescript
// ✅ Correcto
interface User {
  id: string
  name: string
  email: string
}

// ❌ Incorrecto
let user: any = { id: '1', name: 'John' }

Formato

  • Usar Prettier para formato automático
  • Configuración: 2 espacios, sin semicolons, comillas simples
typescript
// ✅ Correcto
const config = {
  name: 'hatcher',
  version: '0.1.0'
}

// ❌ Incorrecto
const config = {
    name: "hatcher",
    version: "0.1.0";
};

Vue.js

Composition API

Preferir Composition API sobre Options API:

vue
<!-- ✅ Correcto -->
<script setup lang="ts">
import { ref, computed } from 'vue'

const count = ref(0)
const doubled = computed(() => count.value * 2)
</script>

<!-- ❌ Incorrecto -->
<script lang="ts">
export default {
  data() {
    return { count: 0 }
  },
  computed: {
    doubled() {
      return this.count * 2
    },
  },
}
</script>

Componentes

  • Usar PascalCase para nombres de componentes
  • Props tipadas con interfaces
  • Emits declarados explícitamente
vue
<script setup lang="ts">
interface Props {
  title: string
  isVisible?: boolean
}

interface Emits {
  close: []
  update: [value: string]
}

defineProps<Props>()
defineEmits<Emits>()
</script>

Electron

IPC Seguro

typescript
// Main Process
ipcMain.handle('safe-operation', async (event, data) => {
  // Validación
  if (!isValidData(data)) {
    throw new Error('Invalid data')
  }

  return await performOperation(data)
})

// Renderer Process
const result = await window.electronAPI.safeOperation(data)

Preload Scripts

typescript
// ✅ Correcto: API controlada
contextBridge.exposeInMainWorld('electronAPI', {
  readFile: (path: string) => ipcRenderer.invoke('read-file', path),
})

// ❌ Incorrecto: Exponer Node.js directamente
contextBridge.exposeInMainWorld('node', {
  fs: require('fs'),
})

Naming Conventions

Variables y Funciones

typescript
// ✅ camelCase para variables y funciones
const userName = 'john'
const calculateTotal = (items: Item[]) => {}

// ✅ PascalCase para clases y componentes
class ProjectManager {}
const UserProfile = defineComponent({})

// ✅ UPPER_SNAKE_CASE para constantes
const MAX_RETRY_ATTEMPTS = 3
const API_BASE_URL = 'https://api.example.com'

Archivos

components/atoms/BaseButton.vue     # PascalCase para componentes
utils/stringHelpers.ts             # camelCase para utilidades
types/apiTypes.ts                  # camelCase con sufijo
constants/appConstants.ts          # camelCase con sufijo

Gestión de Estado

Pinia Stores

typescript
export const useProjectStore = defineStore('project', {
  state: () => ({
    currentProject: null as Project | null,
    isLoading: false,
    error: null as string | null,
  }),

  actions: {
    async loadProject(id: string) {
      this.isLoading = true
      try {
        this.currentProject = await projectApi.get(id)
        this.error = null
      } catch (error) {
        this.error = error.message
      } finally {
        this.isLoading = false
      }
    },
  },
})

Manejo de Errores

Error Boundaries

typescript
// Tipos de error consistentes
interface AppError {
  code: string
  message: string
  details?: unknown
}

// Manejo centralizado
class ErrorHandler {
  static handle(error: AppError) {
    console.error(`[${error.code}] ${error.message}`, error.details)
    // Enviar a servicio de logging
  }
}

Try-Catch

typescript
// ✅ Correcto: Manejo específico
try {
  const result = await riskyOperation()
  return result
} catch (error) {
  if (error instanceof ValidationError) {
    return { error: 'Invalid input' }
  }
  throw error // Re-throw si no podemos manejar
}

Testing

Naming

typescript
// ✅ Descriptivo y específico
describe('ProjectManager', () => {
  describe('loadProject', () => {
    it('should load project when valid ID provided', () => {
      // test implementation
    })

    it('should throw error when project not found', () => {
      // test implementation
    })
  })
})

Mocking

typescript
// ✅ Mock específico
vi.mock('./projectApi', () => ({
  get: vi.fn().mockResolvedValue(mockProject),
}))

// ❌ Mock genérico
vi.mock('./projectApi', () => vi.fn())

Documentación

JSDoc

typescript
/**
 * Calcula el total de items con descuentos aplicados
 * @param items - Lista de items a calcular
 * @param discountRate - Tasa de descuento (0-1)
 * @returns Total calculado con descuentos
 * @throws {ValidationError} Cuando la tasa de descuento es inválida
 */
function calculateTotal(items: Item[], discountRate: number): number {
  if (discountRate < 0 || discountRate > 1) {
    throw new ValidationError('Discount rate must be between 0 and 1')
  }
  // implementación
}

README

Cada módulo debe tener documentación clara:

markdown
# ProjectManager

Gestiona la carga y manipulación de proyectos.

## Usage

```typescript
const manager = new ProjectManager()
await manager.loadProject('project-id')
```

API

  • loadProject(id: string): Promise<Project>
  • saveProject(project: Project): Promise<void>

## Performance

### Lazy Loading

```typescript
// ✅ Componentes lazy
const HeavyComponent = defineAsyncComponent(
  () => import('./HeavyComponent.vue')
)

// ✅ Módulos lazy
const heavyModule = await import('./heavyModule')

Memoria

typescript
// ✅ Cleanup en composables
export function useApiData() {
  const abortController = new AbortController()

  onUnmounted(() => {
    abortController.abort()
  })

  return {
    /* API data */
  }
}

Git

Commits

Usar Conventional Commits:

bash
feat: add visual element selection
fix: resolve memory leak in AI service
docs: update API documentation
refactor: simplify project loading logic

Branches

bash
feature/visual-selection    # Nuevas características
fix/memory-leak             # Corrección de bugs
hotfix/security-patch       # Parches urgentes

Herramientas

Scripts

bash
pnpm lint          # Ejecutar ESLint
pnpm lint:fix      # Corregir automáticamente
pnpm type-check    # Verificar tipos TypeScript
pnpm test          # Ejecutar tests
pnpm build         # Build de producción

VSCode

Configuración recomendada (.vscode/settings.json):

json
{
  "editor.formatOnSave": true,
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  },
  "typescript.preferences.importModuleSpecifier": "relative"
}

Enforzamiento

Estas reglas se enfozan automáticamente a través de:

  • ESLint: Reglas de código
  • Prettier: Formato consistente
  • TypeScript: Verificación de tipos
  • Husky: Hooks de pre-commit
  • CI/CD: Verificación en pull requests

Released under the MIT License. Built with ❤️ by Chriss Mejía and the Hatcher community.