Skip to content

Comandos y snippets rápidos de todos los stacks. Para cuando "sé lo que quiero pero no recuerdo la sintaxis exacta".


🗄️ SQL / PostgreSQL

sql
-- psql
\l            \c basedatos      \dt        \d tabla      \q

-- CRUD
SELECT * FROM t WHERE x = 1 ORDER BY y DESC LIMIT 10;
INSERT INTO t (a, b) VALUES (1, 2) RETURNING id;
UPDATE t SET a = 1 WHERE id = 5;          -- ¡nunca sin WHERE!
DELETE FROM t WHERE id = 5;

-- JOIN
SELECT * FROM a INNER JOIN b ON b.a_id = a.id;
SELECT * FROM a LEFT  JOIN b ON b.a_id = a.id;   -- todos los de a

-- Agregación
SELECT cat, COUNT(*), SUM(precio) FROM p GROUP BY cat HAVING SUM(precio) > 100;

-- Índice / transacción / EXPLAIN
CREATE INDEX idx_t_email ON t(email);
BEGIN; ... COMMIT;   -- o ROLLBACK;
EXPLAIN ANALYZE SELECT ...;

sql
-- NULL: nunca se compara con = (ver cap. 1.5)
WHERE col IS NULL / IS NOT NULL          -- ✅        WHERE col = NULL  -- ❌ nunca devuelve nada
NOT EXISTS (SELECT 1 FROM …)             -- ✅        NOT IN (subconsulta con NULL) -- ❌ 0 filas
COALESCE(a, b, 'defecto')                NULLIF(x, 0)      ORDER BY f ASC NULLS LAST

-- Orden REAL de ejecución (por eso el alias del SELECT no vale en el WHERE)
FROMJOINWHEREGROUP BYHAVINGSELECTDISTINCTORDER BYLIMIT

-- Índices
CREATE INDEX CONCURRENTLY i ON t (a, b DESC);     -- 📌 CONCURRENTLY en producción, SIEMPRE
CREATE INDEX i ON t (fecha) WHERE estado='activo';        -- parcial: más pequeño y rápido
CREATE INDEX i ON t (a) INCLUDE (b, c);                   -- de cobertura → Index Only Scan
CREATE INDEX i ON t USING GIN (datos_jsonb);              -- JSONB, arrays, texto completo
-- Regla del prefijo izquierdo: un índice (a,b,c) sirve para a · a,b · a,b,c — NO para b ni c
SELECT relname, indexrelname, idx_scan FROM pg_stat_user_indexes WHERE idx_scan = 0;  -- sin usar

-- Diagnóstico
EXPLAIN (ANALYZE, BUFFERS) SELECT …;     -- mira rows= (estimado) vs actual rows= (real)
ANALYZE tabla;                            -- si difieren en órdenes de magnitud
-- Seq Scan (lee todo) · Index Scan (👍) · Index Only Scan (🏆) · Sort caro (falta índice)

-- Paginación: por cursor, no por OFFSET
SELECT * FROM t WHERE id < 4821 ORDER BY id DESC LIMIT 20;   -- ✅ constante
SELECT * FROM t ORDER BY id DESC LIMIT 20 OFFSET 100000;     -- ❌ lee y descarta 100.000

-- Concurrencia (cap. 26.1): comprobar-y-actuar NUNCA es seguro
UPDATE asientos SET estado='vendido' WHERE id=42 AND estado='libre';  -- ✅ atómico. ¿0 filas?
SELECTFOR UPDATE;                                                  -- ✅ bloqueo pesimista

-- Borrado seguro
BEGIN; DELETE FROM t WHERE …;   -- ¿el número de filas es el esperado?
COMMIT;   -- o ROLLBACK;

🐘 PHP + Laravel

bash
composer create-project laravel/laravel app
php artisan serve
php artisan make:model Producto -mcr      # modelo + migración + controller + resource
php artisan migrate                       # migrate:fresh --seed
php artisan make:request ProductoRequest
php artisan test                          # --coverage
php artisan tinker                        # REPL interactivo
php
Route::apiResource('productos', ProductoController::class);
Producto::where('activo', true)->with('categoria')->paginate(15);
Producto::create($request->validated());

🐍 Python (Flask / FastAPI)

bash
python -m venv .venv && source .venv/bin/activate   # Win: .venv\Scripts\Activate.ps1
pip install -r requirements.txt         # o: uv add <paquete>
pytest -v                               # --cov=app

# Flask
flask --app app run --debug
flask db migrate -m "msg" && flask db upgrade

# FastAPI
fastapi dev main.py                     # docs en /docs
gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8000
python
# FastAPI endpoint tipado
@app.post("/productos", response_model=ProductoSalida, status_code=201)
def crear(datos: ProductoCrear, session: Session = Depends(get_session)):
    ...

🟢 Node + NestJS

bash
npm i -g @nestjs/cli
nest new app
nest g resource productos        # CRUD completo
npm run start:dev
npm test                         # test:e2e / test:cov
npx prisma migrate dev --name init
typescript
@Controller('productos')
export class C {
  constructor(private readonly svc: Service) {}
  @Get() listar() { return this.svc.listar(); }
  @Post() crear(@Body() dto: Dto) { return this.svc.crear(dto); }
}

🥟 Bun + Elysia

bash
curl -fsSL https://bun.sh/install | bash
bun create elysia app
bun run dev
bun test                         # --coverage
bun add drizzle-orm postgres
bunx drizzle-kit generate && bunx drizzle-kit migrate
typescript
new Elysia()
  .post('/productos', ({ body }) => ({ ...body }),
    { body: t.Object({ nombre: t.String(), precio: t.Number({ minimum: 0 }) }) })
  .listen(3000)

🐹 Go

bash
go mod init app
go run .          go build          go test ./...    # -v -cover -race
go fmt ./...      go vet ./...
GOOS=linux GOARCH=amd64 go build -o servidor .        # cross-compile
go
mux := http.NewServeMux()
mux.HandleFunc("GET /productos/{id}", h.Ver)
log.Fatal(http.ListenAndServe(":8080", mux))

if err != nil { return fmt.Errorf("contexto: %w", err) }   // wrap de errores
go func() { ... }()                                        // goroutine

🦀 Rust + Axum

bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
cargo new app       cargo run       cargo build --release
cargo test          cargo clippy    cargo fmt
cargo add axum tokio serde sqlx
rust
let app = Router::new().route("/productos/{id}", get(ver));
async fn ver(Path(id): Path<i64>) -> Result<Json<Producto>, StatusCode> { ... }
fn dividir(a: f64, b: f64) -> Result<f64, String> { ... }   // sin excepciones ni null

☕ Java + Spring Boot

bash
# Genera el proyecto en start.spring.io (Web, JPA, PostgreSQL, Validation)
./mvnw spring-boot:run        ./mvnw test
java
@RestController @RequestMapping("/api/productos")
class C {
  private final Service svc;
  C(Service svc) { this.svc = svc; }           // DI por constructor
  @GetMapping("/{id}") Producto ver(@PathVariable Long id) { return svc.buscar(id); }
  @PostMapping @ResponseStatus(CREATED)
  Producto crear(@Valid @RequestBody Dto dto) { return svc.crear(dto); }
}
interface Repo extends JpaRepository<Producto, Long> { List<Producto> findByActivoTrue(); }

🐳 Docker

bash
docker build -t app .
docker run -p 8000:8000 app
docker ps            docker logs -f <id>       docker exec -it <id> sh
docker compose up -d       docker compose down [-v]      docker compose logs -f
docker system prune -a     # limpiar todo lo no usado
dockerfile
FROM node:24-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:24-alpine
COPY --from=build /app/dist ./dist
CMD ["node","dist/main.js"]

🌐 Nginx

bash
sudo nginx -t                # validar config ANTES de recargar
sudo nginx -s reload
sudo tail -f /var/log/nginx/error.log
nginx
server {
    listen 80;
    server_name api.sitio.com;
    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
# HTTPS gratis: sudo certbot --nginx -d api.sitio.com

🖥️ Linux / Servidor

bash
systemctl status|restart|enable <servicio>
journalctl -u <servicio> -f          # logs de un servicio
tail -f archivo.log                  # seguir un log
htop            ss -tlnp             # procesos / puertos
ufw allow 443   ufw enable           # firewall
chmod 640 f     chown user:grp f     # permisos

# SSH seguro
ssh-keygen -t ed25519
ssh-copy-id deploy@ip
# /etc/ssh/sshd_config: PermitRootLogin no · PasswordAuthentication no

🐚 Bash scripting

bash
#!/usr/bin/env bash
set -euo pipefail                       # aborta al fallar · variable no definida · pipe roto

"$var"                                  # SIEMPRE entre comillas
"${var:-por_defecto}"                   # valor por defecto si está vacía
"${var:?falta esta variable}"            # aborta con mensaje si falta
"$(comando)"                             # sustitución de comandos
$(( a + b ))                             # aritmética
"$1" "$@" "$#"                           # argumentos · todos · cuántos

[[ -f "$f" ]]  [[ -d "$d" ]]  [[ -s "$f" ]]      # archivo · directorio · no vacío
[[ -z "$s" ]]  [[ -n "$s" ]]                      # cadena vacía · no vacía
[[ "$a" == "$b" ]]   [[ $n -gt 5 ]]   [[ "$x" =~ ^re ]]   # texto · número · regex

for x in "${arr[@]}"; do done                   # bucle sobre array
while IFS= read -r linea; do done < archivo     # leer líneas (la forma correcta)

f() { local x="$1"; echo "resultado"; }           # función: echo devuelve DATOS
r=$(f "arg")                                       #          return devuelve ÉXITO/FALLO

cmd > out 2>&1     cmd &>/dev/null     cmd | tee log        # redirección
cat <<'EOF' EOF                                  # here-doc SIN expandir variables
cat <<EOF   … EOF                                  # here-doc expandiendo variables

trap 'rm -rf "$TMP"' EXIT                          # limpieza pase lo que pase
trap 'echo "error en línea $LINENO" >&2' ERR

bash -x script.sh          shellcheck script.sh    # depurar · linter (obligatorio)

🔧 grep · find · sed · awk · jq · curl

bash
grep -rn "TODO" ./src            grep -C 3 "Exception" app.log     # recursivo+línea · contexto
grep -oE "[0-9]{1,3}(\.[0-9]{1,3}){3}" log     # extraer SOLO lo que coincide
grep -c "ERROR" app.log          grep -v "DEBUG" app.log           # contar · invertir

find . -name "*.log" -mtime +30 -delete        # ⚠️ ejecútalo SIN -delete primero
find . -name "*.sh" -exec chmod +x {} +        # "+" agrupa (rápido) · "\;" uno a uno

sed 's/viejo/nuevo/g' f          sed -i.bak 's|/ruta/a|/ruta/b|g' f  # cambia el delimitador
sed -n '10,20p' f                sed '/^#/d' f                       # rango · borrar comentarios

awk '{print $1, $7}' log                       # columnas
awk -F',' '$3 > 100 {print $1}' datos.csv      # separador + filtro
awk '{s += $10} END {printf "%.2f MB\n", s/1048576}' log

jq -r '.token' resp.json         jq '.items[] | select(.activo)' f
jq -n --arg n "$N" '{nombre: $n}'              # 📌 construir JSON con escapado correcto

curl -fsS --max-time 10 https://api/salud      # 📌 en scripts: -f falla ante 4xx/5xx
curl -X POST url -H 'Content-Type: application/json' -d '{"a":1}'

# El idiom más útil de la terminal: ¿qué es lo que más se repite?
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -10

🔁 Git (flujo diario)

bash
git status / diff / log --oneline
git checkout -b feature/x
git add -p            # añadir por trozos (revisa lo que subes)
git commit -m "feat: ..."
git push -u origin feature/x
git pull --rebase     # actualizar sin merge sucio

🧪 Testing (comando por stack)

StackComando
Laravelphp artisan test
Flask/FastAPIpytest
NestJSnpm test / npm run test:e2e
Elysiabun test
Gogo test ./...
Rustcargo test
Spring Boot./mvnw test

📊 Códigos HTTP (los que memorizar)

200 OK           201 Created      204 No Content
301 Moved        304 Not Modified
400 Bad Request  401 Unauthorized 403 Forbidden    404 Not Found
422 Unprocessable  429 Too Many Requests
500 Server Error   502 Bad Gateway  503 Unavailable

🔤 REST (diseño)

GET    /recursos        listar
POST   /recursos        crear         → 201
GET    /recursos/{id}   ver           → 200 / 404
PUT    /recursos/{id}   reemplazar
PATCH  /recursos/{id}   modificar
DELETE /recursos/{id}   borrar        → 204

🎨 Frontend — Vite / npm

bash
npm create vite@latest app -- --template react-ts   # o vue-ts, vanilla-ts
npm run dev          # dev server :5173
npm run build        # dist/ optimizado
npm run preview      # probar el build
npx create-next-app@latest app                      # Next.js 16
npm create vue@latest app                           # Vue 3
typescript
// Proxy dev (vite.config.ts): '/api' → backend sin CORS
server: { proxy: { '/api': { target: 'http://localhost:8000', changeOrigin: true } } }
// Variables: solo VITE_* llegan al navegador → import.meta.env.VITE_API_URL

⚡ HTMX 2 (estable · 2.0.9)

html
<button hx-get="/ruta" hx-target="#destino" hx-swap="innerHTML">…</button>
<!-- swaps: innerHTML | outerHTML | beforeend | afterbegin | delete | none -->
<input hx-get="/buscar" hx-trigger="input changed delay:300ms" hx-target="#res">
<div hx-get="/estado" hx-trigger="every 5s">…</div>
<form hx-post="/items" hx-target="#lista" hx-swap="beforeend">…</form>
<button hx-delete="/items/1" hx-confirm="¿Seguro?" hx-target="closest li"
        hx-swap="outerHTML">🗑</button>
<body hx-boost="true">           <!-- links/forms normales → AJAX -->
<!-- Servidor: HX-Request (detectar) · HX-Redirect · HX-Retarget · HX-Trigger -->

⚛️ React 19

tsx
const [x, setX] = useState(0);            setX(v => v + 1);   // nunca mutar
useEffect(() => { const id = setInterval(f, 1000); return () => clearInterval(id); }, []);
const ref = useRef<HTMLInputElement>(null);                    // DOM / mutable
const v = useContext(MiContexto);                              // sin prop drilling
const [estado, action, pending] = useActionState(fnAsync, null);  // <form action={action}>
const [opt, addOpt] = useOptimistic(valor, reducer);           // UI optimista
const datos = use(promesa);                                    // con <Suspense>

// Query + Router
const { data, isPending, error } = useQuery({ queryKey: ['k'], queryFn: fn });
const mut = useMutation({ mutationFn: fn, onSuccess: () => qc.invalidateQueries({ queryKey: ['k'] }) });
const { id } = useParams();  const navigate = useNavigate();   // react-router

💚 Vue 3

vue
<script setup lang="ts">
const x = ref(0);            x.value++;                  // script: .value
const total = computed(() => items.value.length);        // derivado con caché
watch(fuente, (nuevo, viejo) => { … });
onMounted(() => { … });
const props = defineProps<{ nombre: string }>();
const emit = defineEmits<{ crear: [dato: string] }>();
</script>
<template>
  {{ x }}                                  <!-- template: sin .value -->
  <li v-for="p in lista" :key="p.id" v-if="visible" @click="f" :class="{ activo: ok }">
  <input v-model.trim="nombre">
</template>
typescript
// Pinia
export const useStore = defineStore('id', () => {
  const items = ref([]); const total = computed(…); function añadir(){…}
  return { items, total, añadir };
});
const { total } = storeToRefs(useStore());    // ¡storeToRefs o pierdes reactividad!

▲ Next.js 16

tsx
// app/ruta/page.tsx — Server Component (async, sin JS al cliente)
export default async function Page({ params }: { params: Promise<{ id: string }> }) {
  const { id } = await params;               // Next 16: params es Promise
}
'use client'                                  // isla interactiva (hooks, eventos)
'use server'                                  // Server Action (validar + autorizar SIEMPRE)
'use cache'; cacheLife('hours'); cacheTag('t')  // Cache Components
revalidateTag('t');  updateTag('t');  refresh();
// Archivos: page · layout · loading · error · not-found · route.ts (API) · proxy.ts

🧪 Testing frontend

bash
npm i -D vitest jsdom @testing-library/react @testing-library/user-event  # o /vue
npx playwright test          # e2e
tsx
render(<Comp />); await userEvent.click(screen.getByRole('button', { name: /crear/i }));
expect(screen.getByText('ok')).toBeInTheDocument();

🧰 Apéndices — referencia rápida

bash
# Redis (apéndice B)
redis-cli SET clave valor EX 3600      # caché con expiración
redis-cli LPUSH cola tarea             # cola simple
redis-cli PUBLISH canal "mensaje"      # pub/sub
bash
# Kubernetes (apéndice G)
kubectl get pods -A            kubectl logs -f <pod>
kubectl apply -f deploy.yaml   kubectl rollout status deploy/app
kubectl scale deploy/app --replicas=3
bash
# Terraform (apéndice R)
terraform init      terraform plan      terraform apply
terraform fmt        terraform state list       terraform destroy
bash
# Kafka / RabbitMQ (apéndice S)
kafka-topics.sh --create --topic pedidos --partitions 3 --bootstrap-server localhost:9092
kafka-console-consumer.sh --topic pedidos --from-beginning --bootstrap-server localhost:9092
javascript
// MongoDB (apéndice Q)
db.productos.insertOne({ nombre: "Teclado", precio: 89.9 })
db.productos.find({ precio: { $lt: 100 } }).sort({ precio: 1 })
db.productos.aggregate([{ $group: { _id: "$categoria", total: { $sum: 1 } } }])
typescript
// TypeScript utility types (apéndice A)
type Parcial = Partial<Producto>;              // todas las props opcionales
type Reducido = Pick<Producto, 'id' | 'nombre'>;
type SinPrecio = Omit<Producto, 'precio'>;
type SoloLectura = Readonly<Producto>;
bash
# Stripe (apéndice P)
stripe listen --forward-to localhost:8000/webhooks/stripe   # probar webhooks en local
stripe trigger payment_intent.succeeded                     # simular un evento