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)
FROM → JOIN → WHERE → GROUP BY → HAVING → SELECT → DISTINCT → ORDER BY → LIMIT
-- Í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?
SELECT … FOR 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 interactivophp
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:8000python
# 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 inittypescript
@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 migratetypescript
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-compilego
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 sqlxrust
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 testjava
@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 usadodockerfile
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.lognginx
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)
| Stack | Comando |
|---|---|
| Laravel | php artisan test |
| Flask/FastAPI | pytest |
| NestJS | npm test / npm run test:e2e |
| Elysia | bun test |
| Go | go test ./... |
| Rust | cargo 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 3typescript
// 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 # e2etsx
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/subbash
# 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=3bash
# Terraform (apéndice R)
terraform init terraform plan terraform apply
terraform fmt terraform state list terraform destroybash
# 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:9092javascript
// 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