@saulwade/swl-ses 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +238 -0
- package/README.md +560 -0
- package/_userland/agentes/.gitkeep +0 -0
- package/_userland/habilidades/.gitkeep +0 -0
- package/agentes/.evolved.json +9 -0
- package/agentes/accesibilidad-wcag-swl.md +692 -0
- package/agentes/arquitecto-swl.md +238 -0
- package/agentes/auto-evolucion-swl.md +854 -0
- package/agentes/backend-api-swl.md +470 -0
- package/agentes/backend-csharp-swl.md +418 -0
- package/agentes/backend-go-swl.md +388 -0
- package/agentes/backend-java-swl.md +279 -0
- package/agentes/backend-node-swl.md +477 -0
- package/agentes/backend-python-swl.md +608 -0
- package/agentes/backend-rust-swl.md +362 -0
- package/agentes/backend-workers-swl.md +480 -0
- package/agentes/cloud-infra-swl.md +485 -0
- package/agentes/consolidador-swl.md +539 -0
- package/agentes/datos-swl.md +584 -0
- package/agentes/depurador-swl.md +349 -0
- package/agentes/devops-ci-swl.md +374 -0
- package/agentes/disenador-ui-swl.md +558 -0
- package/agentes/documentador-swl.md +343 -0
- package/agentes/evals/arquitecto-swl.evals.json +56 -0
- package/agentes/evals/auto-evolucion-swl.evals.json +68 -0
- package/agentes/evals/implementador-swl.evals.json +56 -0
- package/agentes/evals/orquestador-swl.evals.json +60 -0
- package/agentes/evals/perfilador-usuario-swl.evals.json +60 -0
- package/agentes/evals/red-team-swl.evals.json +59 -0
- package/agentes/evals/revisor-codigo-swl.evals.json +59 -0
- package/agentes/frontend-angular-swl.md +627 -0
- package/agentes/frontend-css-swl.md +720 -0
- package/agentes/frontend-react-swl.md +696 -0
- package/agentes/frontend-swl.md +500 -0
- package/agentes/frontend-tailwind-swl.md +830 -0
- package/agentes/implementador-swl.md +328 -0
- package/agentes/investigador-swl.md +430 -0
- package/agentes/investigador-ux-swl.md +500 -0
- package/agentes/llm-apps-swl.md +276 -0
- package/agentes/migrador-swl.md +417 -0
- package/agentes/mobile-android-swl.md +509 -0
- package/agentes/mobile-cross-swl.md +539 -0
- package/agentes/mobile-ios-swl.md +500 -0
- package/agentes/mobile-testing-swl.md +300 -0
- package/agentes/notificador-swl.md +916 -0
- package/agentes/observabilidad-swl.md +436 -0
- package/agentes/orquestador-swl.md +884 -0
- package/agentes/pagos-swl.md +283 -0
- package/agentes/perfilador-usuario-swl.md +306 -0
- package/agentes/planificador-swl.md +402 -0
- package/agentes/producto-prd-swl.md +587 -0
- package/agentes/red-team-swl.md +216 -0
- package/agentes/release-manager-swl.md +568 -0
- package/agentes/rendimiento-swl.md +714 -0
- package/agentes/resolutor-build-swl.md +243 -0
- package/agentes/revisor-angular-swl.md +276 -0
- package/agentes/revisor-codigo-swl.md +348 -0
- package/agentes/revisor-csharp-swl.md +262 -0
- package/agentes/revisor-go-swl.md +257 -0
- package/agentes/revisor-java-swl.md +255 -0
- package/agentes/revisor-kotlin-swl.md +271 -0
- package/agentes/revisor-nextjs-swl.md +279 -0
- package/agentes/revisor-php-swl.md +269 -0
- package/agentes/revisor-react-swl.md +276 -0
- package/agentes/revisor-rust-swl.md +344 -0
- package/agentes/revisor-seguridad-swl.md +390 -0
- package/agentes/revisor-swift-swl.md +266 -0
- package/agentes/revisor-typescript-swl.md +344 -0
- package/agentes/sre-swl.md +265 -0
- package/agentes/tdd-qa-swl.md +354 -0
- package/agentes/ux-disenador-swl.md +501 -0
- package/bin/lib/bot-comandos.js +1030 -0
- package/bin/lib/bot-discovery.js +182 -0
- package/bin/lib/bot-git.js +142 -0
- package/bin/swl-ses.js +325 -0
- package/bin/swl-telegram-bot.js +442 -0
- package/bin/swl-telegram-bot.plist +21 -0
- package/bin/swl-telegram-bot.service +14 -0
- package/comandos/swl/.evolved.json +23 -0
- package/comandos/swl/actualizar.md +174 -0
- package/comandos/swl/adoptar-proyecto.md +207 -0
- package/comandos/swl/aprender.md +701 -0
- package/comandos/swl/auditar-deps.md +134 -0
- package/comandos/swl/autoresearch.md +170 -0
- package/comandos/swl/ayuda.md +224 -0
- package/comandos/swl/brainstorm.md +50 -0
- package/comandos/swl/checkpoint.md +330 -0
- package/comandos/swl/compactar.md +283 -0
- package/comandos/swl/configurar-ci.md +227 -0
- package/comandos/swl/contexto.md +112 -0
- package/comandos/swl/contribuir.md +233 -0
- package/comandos/swl/crear-skill.md +292 -0
- package/comandos/swl/cron.md +196 -0
- package/comandos/swl/dashboard.md +146 -0
- package/comandos/swl/discutir-fase.md +230 -0
- package/comandos/swl/ejecutar-fase.md +135 -0
- package/comandos/swl/evaluar-skill.md +487 -0
- package/comandos/swl/evolucion-estado.md +142 -0
- package/comandos/swl/evolucionar.md +259 -0
- package/comandos/swl/exportar-vault.md +189 -0
- package/comandos/swl/gateway.md +158 -0
- package/comandos/swl/inbox.md +116 -0
- package/comandos/swl/instalar.md +220 -0
- package/comandos/swl/instintos.md +86 -0
- package/comandos/swl/mapear-codebase.md +312 -0
- package/comandos/swl/mcp-status.md +175 -0
- package/comandos/swl/metricas.md +270 -0
- package/comandos/swl/modelo.md +102 -0
- package/comandos/swl/notificaciones.md +396 -0
- package/comandos/swl/nuevo-proyecto.md +154 -0
- package/comandos/swl/planear-fase.md +221 -0
- package/comandos/swl/plugins.md +256 -0
- package/comandos/swl/reflect-skills.md +125 -0
- package/comandos/swl/release.md +217 -0
- package/comandos/swl/revisar-impacto.md +206 -0
- package/comandos/swl/revisar.md +330 -0
- package/comandos/swl/salud.md +363 -0
- package/comandos/swl/sesiones.md +200 -0
- package/comandos/swl/skill-search.md +113 -0
- package/comandos/swl/verificar.md +585 -0
- package/comandos/swl/wiki.md +620 -0
- package/contextos/dev.md +32 -0
- package/contextos/research.md +30 -0
- package/contextos/review.md +31 -0
- package/habilidades/accesibilidad-a11y/SKILL.md +201 -0
- package/habilidades/accesibilidad-a11y/evals/evals.json +56 -0
- package/habilidades/accesibilidad-a11y/recursos/ejemplos-y-checklist-completo.md +441 -0
- package/habilidades/agent-browser/SKILL.md +218 -0
- package/habilidades/agentes-como-servicio/SKILL.md +218 -0
- package/habilidades/ai-runtime-security/SKILL.md +273 -0
- package/habilidades/angular-avanzado/SKILL.md +164 -0
- package/habilidades/angular-avanzado/recursos/ejemplos-avanzados.md +219 -0
- package/habilidades/angular-moderno/SKILL.md +186 -0
- package/habilidades/angular-moderno/evals/evals.json +45 -0
- package/habilidades/angular-moderno/recursos/ejemplos-avanzados.md +106 -0
- package/habilidades/api-rest-diseno/SKILL.md +191 -0
- package/habilidades/api-rest-diseno/recursos/openapi-template.yaml +506 -0
- package/habilidades/api-rest-diseno/recursos/referencia-api.md +140 -0
- package/habilidades/aprendizaje-continuo/SKILL.md +151 -0
- package/habilidades/aprendizaje-continuo/evals/evals.json +53 -0
- package/habilidades/aprendizaje-continuo/recursos/referencia-instintos.md +290 -0
- package/habilidades/async-python/SKILL.md +149 -0
- package/habilidades/async-python/evals/evals.json +47 -0
- package/habilidades/async-python/recursos/patrones-y-ejemplos-completos.md +292 -0
- package/habilidades/auth-patrones/.evolved.json +9 -0
- package/habilidades/auth-patrones/SKILL.md +413 -0
- package/habilidades/auth-patrones/recursos/implementaciones-completas.md +229 -0
- package/habilidades/auto-evolucion-protocolo/SKILL.md +276 -0
- package/habilidades/auto-evolucion-protocolo/evals/evals.json +55 -0
- package/habilidades/auto-evolucion-protocolo/recursos/referencia-completa.md +145 -0
- package/habilidades/autoresearch/SKILL.md +268 -0
- package/habilidades/autoresearch/evals/evals.json +41 -0
- package/habilidades/autoresearch/recursos/checklist-template.md +191 -0
- package/habilidades/autoresearch/scripts/calcular-score.js +88 -0
- package/habilidades/azure-cloud/SKILL.md +308 -0
- package/habilidades/azure-cloud/recursos/aks.md +327 -0
- package/habilidades/backend-mcp-servidor/SKILL.md +270 -0
- package/habilidades/backend-production-resilience/SKILL.md +288 -0
- package/habilidades/brainstorming/SKILL.md +295 -0
- package/habilidades/brainstorming/recursos/componentes-html.md +247 -0
- package/habilidades/build-errors-cpp/SKILL.md +270 -0
- package/habilidades/build-errors-csharp/SKILL.md +265 -0
- package/habilidades/build-errors-go/SKILL.md +306 -0
- package/habilidades/build-errors-java/SKILL.md +278 -0
- package/habilidades/build-errors-kotlin/SKILL.md +303 -0
- package/habilidades/build-errors-nextjs/SKILL.md +312 -0
- package/habilidades/build-errors-php/SKILL.md +270 -0
- package/habilidades/build-errors-python/SKILL.md +292 -0
- package/habilidades/build-errors-rust/SKILL.md +284 -0
- package/habilidades/build-errors-swift/SKILL.md +272 -0
- package/habilidades/build-errors-typescript/SKILL.md +369 -0
- package/habilidades/checklist-calidad/SKILL.md +271 -0
- package/habilidades/checklist-calidad/recursos/quality-report-template.md +148 -0
- package/habilidades/checklist-seguridad/SKILL.md +285 -0
- package/habilidades/checkpoints-verificacion/SKILL.md +298 -0
- package/habilidades/checkpoints-verificacion/recursos/checkpoint-templates.md +360 -0
- package/habilidades/ci-cd-pipelines/SKILL.md +157 -0
- package/habilidades/ci-cd-pipelines/recursos/github-actions-template.yaml +403 -0
- package/habilidades/ci-cd-pipelines/recursos/pipelines-completos.md +487 -0
- package/habilidades/cloud-aws/SKILL.md +142 -0
- package/habilidades/cloud-aws/recursos/servicios-aws-referencia.md +321 -0
- package/habilidades/compactacion-contexto/SKILL.md +247 -0
- package/habilidades/contenedores-docker/SKILL.md +137 -0
- package/habilidades/contenedores-docker/recursos/dockerfile-template.dockerfile +160 -0
- package/habilidades/contenedores-docker/recursos/ejemplos-y-configuraciones.md +327 -0
- package/habilidades/context-builder/SKILL.md +170 -0
- package/habilidades/control-profundidad/SKILL.md +128 -0
- package/habilidades/csharp-experto/SKILL.md +322 -0
- package/habilidades/csharp-patrones/SKILL.md +316 -0
- package/habilidades/csharp-testing/SKILL.md +286 -0
- package/habilidades/css-moderno/SKILL.md +166 -0
- package/habilidades/css-moderno/evals/evals.json +43 -0
- package/habilidades/css-moderno/recursos/ejemplos-y-patrones-completos.md +337 -0
- package/habilidades/datos-etl/SKILL.md +129 -0
- package/habilidades/datos-etl/recursos/implementaciones-completas.md +322 -0
- package/habilidades/dbml-experto/SKILL.md +339 -0
- package/habilidades/dbml-experto/evals/evals.json +56 -0
- package/habilidades/dependencias-auditoria/SKILL.md +320 -0
- package/habilidades/deprecacion-migracion/SKILL.md +169 -0
- package/habilidades/deprecacion-migracion/recursos/implementaciones-completas.md +220 -0
- package/habilidades/design-tokens/SKILL.md +158 -0
- package/habilidades/design-tokens/recursos/tokens-y-configuracion.md +363 -0
- package/habilidades/devsecops-pipeline-security/SKILL.md +309 -0
- package/habilidades/diagrama-arquitectura/SKILL.md +165 -0
- package/habilidades/diagrama-arquitectura/assets/template.html +276 -0
- package/habilidades/discutir-fase/SKILL.md +188 -0
- package/habilidades/diseno-herramientas-agente/SKILL.md +199 -0
- package/habilidades/diseno-responsivo/SKILL.md +186 -0
- package/habilidades/diseno-responsivo/recursos/ejemplos-layouts.md +156 -0
- package/habilidades/django-experto/SKILL.md +205 -0
- package/habilidades/django-experto/recursos/async-django.md +390 -0
- package/habilidades/django-experto/recursos/drf-patrones.md +438 -0
- package/habilidades/django-experto/recursos/orm-avanzado.md +382 -0
- package/habilidades/django-experto/recursos/referencia-completa.md +188 -0
- package/habilidades/django-experto/recursos/testing-django.md +415 -0
- package/habilidades/doc-sync/SKILL.md +280 -0
- package/habilidades/drift-detection/SKILL.md +179 -0
- package/habilidades/ejecutar-fase/SKILL.md +468 -0
- package/habilidades/estilo-sin-ai-isms/SKILL.md +775 -0
- package/habilidades/estilo-sin-ai-isms/evals/evals.json +63 -0
- package/habilidades/estilo-sin-ai-isms/scripts/detectar_aiisms.py +500 -0
- package/habilidades/estructura-proyecto-claude/SKILL.md +215 -0
- package/habilidades/estructura-proyecto-claude/recursos/claude-md-template.md +261 -0
- package/habilidades/estructura-proyecto-claude/recursos/configuracion-y-extensiones.md +176 -0
- package/habilidades/estructura-proyecto-claude/recursos/frontmatter-y-hooks-referencia.md +289 -0
- package/habilidades/estructura-proyecto-claude/recursos/mcp-json-template.json +77 -0
- package/habilidades/estructura-proyecto-claude/recursos/variantes-por-stack.md +177 -0
- package/habilidades/evaluacion-agentes/SKILL.md +314 -0
- package/habilidades/event-driven/SKILL.md +153 -0
- package/habilidades/event-driven/recursos/implementaciones-completas.md +423 -0
- package/habilidades/extraccion-documentos/SKILL.md +221 -0
- package/habilidades/extractor-de-aprendizajes/.evolved.json +9 -0
- package/habilidades/extractor-de-aprendizajes/SKILL.md +311 -0
- package/habilidades/extractor-de-aprendizajes/evals/evals.json +55 -0
- package/habilidades/fastapi-experto/SKILL.md +221 -0
- package/habilidades/fastapi-experto/recursos/async-patterns.md +438 -0
- package/habilidades/fastapi-experto/recursos/dependency-injection.md +330 -0
- package/habilidades/fastapi-experto/recursos/referencia-completa.md +79 -0
- package/habilidades/fastapi-experto/recursos/testing-httpx.md +420 -0
- package/habilidades/filament-admin/SKILL.md +290 -0
- package/habilidades/frontend-avanzado/SKILL.md +257 -0
- package/habilidades/frontend-avanzado/recursos/apis-nativas-ejemplos.md +341 -0
- package/habilidades/gcp-cloud/SKILL.md +260 -0
- package/habilidades/gcp-cloud/recursos/gke.md +234 -0
- package/habilidades/gcp-cloud/recursos/terraform-gcp.md +307 -0
- package/habilidades/generacion-mermaid/SKILL.md +229 -0
- package/habilidades/git-worktrees-paralelo/SKILL.md +270 -0
- package/habilidades/go-experto/SKILL.md +305 -0
- package/habilidades/go-patrones/SKILL.md +299 -0
- package/habilidades/go-testing/SKILL.md +291 -0
- package/habilidades/graphql-experto/SKILL.md +323 -0
- package/habilidades/guardrail-semantico/SKILL.md +282 -0
- package/habilidades/harness-claude-code/SKILL.md +299 -0
- package/habilidades/iam-secretos/SKILL.md +265 -0
- package/habilidades/iam-secretos/recursos/implementaciones-completas.md +356 -0
- package/habilidades/infra-github-actions/SKILL.md +166 -0
- package/habilidades/instalar-sistema/.evolved.json +9 -0
- package/habilidades/instalar-sistema/SKILL.md +221 -0
- package/habilidades/java-experto/SKILL.md +290 -0
- package/habilidades/java-patrones/SKILL.md +275 -0
- package/habilidades/java-testing/SKILL.md +288 -0
- package/habilidades/kotlin-compose/SKILL.md +278 -0
- package/habilidades/kotlin-compose/recursos/animaciones-performance.md +93 -0
- package/habilidades/kotlin-experto/SKILL.md +318 -0
- package/habilidades/kotlin-testing/SKILL.md +267 -0
- package/habilidades/kotlin-testing/recursos/testing-avanzado.md +74 -0
- package/habilidades/kubernetes-orquestacion/SKILL.md +152 -0
- package/habilidades/kubernetes-orquestacion/recursos/manifiestos-completos.md +452 -0
- package/habilidades/langchain-langraph/SKILL.md +386 -0
- package/habilidades/langchain-langraph/recursos/evaluacion-rag.md +321 -0
- package/habilidades/langchain-langraph/recursos/rag-maturity-model.md +225 -0
- package/habilidades/langchain-langraph/recursos/vectorstores.md +306 -0
- package/habilidades/legacy-code-rescue/SKILL.md +267 -0
- package/habilidades/likec4-experto/SKILL.md +412 -0
- package/habilidades/likec4-experto/evals/evals.json +69 -0
- package/habilidades/manejo-errores/.evolved.json +9 -0
- package/habilidades/manejo-errores/SKILL.md +407 -0
- package/habilidades/manejo-errores/recursos/implementaciones-completas.md +248 -0
- package/habilidades/mapear-codebase/SKILL.md +275 -0
- package/habilidades/memoria-busqueda/SKILL.md +194 -0
- package/habilidades/memoria-busqueda/evals/evals.json +44 -0
- package/habilidades/meta-skills-estandar/SKILL.md +298 -0
- package/habilidades/meta-skills-estandar/recursos/anti-patrones-y-leyes.md +205 -0
- package/habilidades/meta-skills-estandar/recursos/frameworks-seguridad.md +107 -0
- package/habilidades/meta-skills-estandar/recursos/idiomas-framework.md +60 -0
- package/habilidades/meta-skills-estandar/recursos/skills-as-agents.md +163 -0
- package/habilidades/microservicios/SKILL.md +155 -0
- package/habilidades/microservicios/recursos/patrones-y-ejemplos-completos.md +325 -0
- package/habilidades/mobile-flutter/SKILL.md +199 -0
- package/habilidades/mobile-flutter/recursos/ejemplos-completos.md +319 -0
- package/habilidades/mobile-react-native/SKILL.md +176 -0
- package/habilidades/mobile-react-native/recursos/ejemplos-completos.md +216 -0
- package/habilidades/mongodb-experto/SKILL.md +302 -0
- package/habilidades/monitoring-alertas/SKILL.md +201 -0
- package/habilidades/monitoring-alertas/recursos/instrumentacion-y-alertas.md +301 -0
- package/habilidades/nestjs-experto/SKILL.md +307 -0
- package/habilidades/nestjs-experto/recursos/guards-interceptors.md +339 -0
- package/habilidades/nestjs-experto/recursos/modulos-di.md +287 -0
- package/habilidades/nestjs-experto/recursos/testing-nestjs.md +354 -0
- package/habilidades/nextjs-experto/SKILL.md +335 -0
- package/habilidades/nextjs-patrones/SKILL.md +303 -0
- package/habilidades/nextjs-testing/SKILL.md +331 -0
- package/habilidades/node-experto/.evolved.json +9 -0
- package/habilidades/node-experto/SKILL.md +266 -0
- package/habilidades/node-experto/recursos/patrones-completos.md +283 -0
- package/habilidades/notificaciones-multicanal/SKILL.md +159 -0
- package/habilidades/notificaciones-multicanal/recursos/config-template.json +115 -0
- package/habilidades/notificaciones-multicanal/recursos/configuracion-y-templates.md +303 -0
- package/habilidades/nuevo-proyecto/SKILL.md +204 -0
- package/habilidades/orquestacion-async/SKILL.md +303 -0
- package/habilidades/paid-media-tracking/SKILL.md +269 -0
- package/habilidades/paid-media-tracking/recursos/auditoria-tracking.md +220 -0
- package/habilidades/paid-media-tracking/recursos/google-ads-api.md +215 -0
- package/habilidades/patrones-python/SKILL.md +228 -0
- package/habilidades/patrones-python/evals/evals.json +56 -0
- package/habilidades/patrones-python/recursos/patrones-avanzados.md +469 -0
- package/habilidades/patrones-python/recursos/referencia-completa.md +202 -0
- package/habilidades/perfil-usuario/SKILL.md +200 -0
- package/habilidades/perfil-usuario/evals/evals.json +55 -0
- package/habilidades/performance-baseline/SKILL.md +297 -0
- package/habilidades/php-experto/SKILL.md +291 -0
- package/habilidades/php-patrones/SKILL.md +306 -0
- package/habilidades/php-testing/SKILL.md +280 -0
- package/habilidades/planear-fase/SKILL.md +269 -0
- package/habilidades/postgresql-experto/SKILL.md +151 -0
- package/habilidades/postgresql-experto/evals/evals.json +53 -0
- package/habilidades/postgresql-experto/recursos/referencia-completa.md +215 -0
- package/habilidades/prevencion-racionalizacion/SKILL.md +175 -0
- package/habilidades/prevencion-sobreingenieria/SKILL.md +323 -0
- package/habilidades/privacy-memoria/SKILL.md +141 -0
- package/habilidades/privacy-memoria/evals/evals.json +43 -0
- package/habilidades/prompt-engineering/SKILL.md +518 -0
- package/habilidades/prompt-engineering/recursos/patrones-avanzados.md +467 -0
- package/habilidades/rag-arquitectura/SKILL.md +338 -0
- package/habilidades/rails-experto/SKILL.md +237 -0
- package/habilidades/rails-experto/recursos/active-record.md +260 -0
- package/habilidades/rails-experto/recursos/hotwire-turbo.md +293 -0
- package/habilidades/rails-experto/recursos/testing-rspec.md +362 -0
- package/habilidades/react-experto/SKILL.md +209 -0
- package/habilidades/react-experto/evals/evals.json +55 -0
- package/habilidades/react-experto/recursos/patrones-y-ejemplos-completos.md +240 -0
- package/habilidades/react-optimizacion/SKILL.md +174 -0
- package/habilidades/react-optimizacion/recursos/patrones-avanzados.md +138 -0
- package/habilidades/redis-experto/SKILL.md +305 -0
- package/habilidades/release-semver/.evolved.json +9 -0
- package/habilidades/release-semver/SKILL.md +248 -0
- package/habilidades/release-semver/scripts/generar-changelog.sh +238 -0
- package/habilidades/rust-experto/SKILL.md +400 -0
- package/habilidades/rust-patrones/SKILL.md +296 -0
- package/habilidades/rust-testing/SKILL.md +311 -0
- package/habilidades/seguridad-skills-ia/SKILL.md +262 -0
- package/habilidades/sql-optimizacion/SKILL.md +200 -0
- package/habilidades/sql-optimizacion/evals/evals.json +54 -0
- package/habilidades/sql-optimizacion/recursos/patrones-sql-avanzados.md +131 -0
- package/habilidades/sre-patrones/SKILL.md +333 -0
- package/habilidades/sre-patrones/recursos/chaos-engineering.md +241 -0
- package/habilidades/sre-patrones/recursos/oncall-design.md +236 -0
- package/habilidades/stripe-pagos/SKILL.md +550 -0
- package/habilidades/stripe-pagos/recursos/errores-reintentos.md +390 -0
- package/habilidades/stripe-pagos/recursos/stripe-connect.md +290 -0
- package/habilidades/structured-outputs/SKILL.md +343 -0
- package/habilidades/swift-experto/SKILL.md +320 -0
- package/habilidades/swift-experto/recursos/keychain-y-wrappers.md +110 -0
- package/habilidades/swift-patrones/SKILL.md +313 -0
- package/habilidades/swift-patrones/recursos/tca-ejemplo-completo.md +113 -0
- package/habilidades/swift-testing/SKILL.md +254 -0
- package/habilidades/swift-testing/recursos/xcuitest-planes.md +143 -0
- package/habilidades/swl-dashboard/SKILL.md +370 -0
- package/habilidades/swl-markitdown/SKILL.md +285 -0
- package/habilidades/swl-markitdown/evals/evals.json +52 -0
- package/habilidades/swl-revisar-impacto/SKILL.md +233 -0
- package/habilidades/tailwind-experto/SKILL.md +240 -0
- package/habilidades/tailwind-experto/recursos/referencia-completa.md +184 -0
- package/habilidades/tdd-workflow/SKILL.md +293 -0
- package/habilidades/terraform-experto/SKILL.md +321 -0
- package/habilidades/testing-python/SKILL.md +340 -0
- package/habilidades/testing-python/recursos/ejemplos-completos.md +167 -0
- package/habilidades/threat-model-lite/SKILL.md +246 -0
- package/habilidades/tracing-processor/SKILL.md +212 -0
- package/habilidades/tracking-measurement/SKILL.md +239 -0
- package/habilidades/tracking-measurement/recursos/consent-mode.md +231 -0
- package/habilidades/tracking-measurement/recursos/gtm-datalayer.md +216 -0
- package/habilidades/tracking-measurement/recursos/meta-capi.md +262 -0
- package/habilidades/typescript-avanzado/SKILL.md +144 -0
- package/habilidades/typescript-avanzado/evals/evals.json +55 -0
- package/habilidades/typescript-avanzado/recursos/patrones-y-ejemplos-completos.md +298 -0
- package/habilidades/typescript-diagnosticos/SKILL.md +513 -0
- package/habilidades/ux-diseno/SKILL.md +116 -0
- package/habilidades/ux-diseno/evals/evals.json +43 -0
- package/habilidades/ux-diseno/recursos/patrones-ux-referencia.md +214 -0
- package/habilidades/validacion-ci-sistema/SKILL.md +136 -0
- package/habilidades/validacion-ci-sistema/recursos/validadores-completos.md +369 -0
- package/habilidades/validacion-ci-sistema/scripts/validar-sistema.sh +286 -0
- package/habilidades/verificacion-evidencia/SKILL.md +160 -0
- package/habilidades/verificar-trabajo/SKILL.md +303 -0
- package/habilidades/verificar-trabajo/recursos/plantilla-verificacion.md +60 -0
- package/habilidades/wiki-conocimiento/SKILL.md +276 -0
- package/habilidades/wireframes-flujos/SKILL.md +212 -0
- package/habilidades/wireframes-flujos/recursos/referencia-completa.md +192 -0
- package/habilidades/workflow-claude-code/SKILL.md +260 -0
- package/habilidades/workflow-claude-code/recursos/referencia-completa.md +109 -0
- package/hooks/_run-hook.sh +57 -0
- package/hooks/actualizar-perfil-usuario.js +364 -0
- package/hooks/agente-lifecycle.js +71 -0
- package/hooks/aiisms-detector.js +173 -0
- package/hooks/audit-trail.js +204 -0
- package/hooks/auto-background.js +97 -0
- package/hooks/auto-consolidacion.js +178 -0
- package/hooks/auto-evolucion.js +666 -0
- package/hooks/auto-restaurar-settings.js +360 -0
- package/hooks/calidad-pre-commit.js +929 -0
- package/hooks/calidad-typescript.js +511 -0
- package/hooks/captura-feedback-usuario.js +148 -0
- package/hooks/check-update.js +211 -0
- package/hooks/clasificador-mensajes.js +271 -0
- package/hooks/degradacion-instintos.js +272 -0
- package/hooks/escaneo-secretos.js +389 -0
- package/hooks/extraccion-aprendizajes.js +763 -0
- package/hooks/grafo-contexto.js +129 -0
- package/hooks/graph-update.js +67 -0
- package/hooks/guardrail-modelo.js +247 -0
- package/hooks/inbox-aviso.js +75 -0
- package/hooks/inyeccion-contexto.js +246 -0
- package/hooks/lib/abort-registry.js +214 -0
- package/hooks/lib/agent-backend.js +210 -0
- package/hooks/lib/agent-comms.js +263 -0
- package/hooks/lib/agent-issue-codes.js +284 -0
- package/hooks/lib/agent-matcher.js +189 -0
- package/hooks/lib/async-hook-registry.js +252 -0
- package/hooks/lib/atomic-write.js +130 -0
- package/hooks/lib/auto-consolidator.js +335 -0
- package/hooks/lib/canary-skills.js +187 -0
- package/hooks/lib/consolidation-lock.js +291 -0
- package/hooks/lib/context-builder.js +430 -0
- package/hooks/lib/context-compressor.js +657 -0
- package/hooks/lib/convergence-detector.js +105 -0
- package/hooks/lib/delegation-tracker.js +198 -0
- package/hooks/lib/detectar-package-manager.js +423 -0
- package/hooks/lib/edit-accumulator.js +171 -0
- package/hooks/lib/error-classifier.js +308 -0
- package/hooks/lib/event-bus.js +112 -0
- package/hooks/lib/evolution-tracker.js +442 -0
- package/hooks/lib/execution-state.js +316 -0
- package/hooks/lib/fingerprint-id.js +135 -0
- package/hooks/lib/gateway-notify.js +116 -0
- package/hooks/lib/graph-security.js +75 -0
- package/hooks/lib/guardrail-metrics.js +202 -0
- package/hooks/lib/hook-circuit-breaker.js +206 -0
- package/hooks/lib/loop-detector.js +267 -0
- package/hooks/lib/mcp-health.js +184 -0
- package/hooks/lib/mcp-pool.js +436 -0
- package/hooks/lib/memory-search.js +506 -0
- package/hooks/lib/merkle-audit.js +96 -0
- package/hooks/lib/model-router.js +222 -0
- package/hooks/lib/normalize-error.js +324 -0
- package/hooks/lib/normalize-input.js +65 -0
- package/hooks/lib/nudge-tracker.js +306 -0
- package/hooks/lib/otlp-exporter.js +365 -0
- package/hooks/lib/performance-marks.js +239 -0
- package/hooks/lib/privacy-filter.js +128 -0
- package/hooks/lib/prompt-injection-scanner.js +209 -0
- package/hooks/lib/provenance-tracker.js +183 -0
- package/hooks/lib/rate-limit-tracker.js +253 -0
- package/hooks/lib/reflect-classifier.js +164 -0
- package/hooks/lib/resource-quota.js +122 -0
- package/hooks/lib/retry-jitter.js +165 -0
- package/hooks/lib/risk-engine.js +368 -0
- package/hooks/lib/run-log.js +408 -0
- package/hooks/lib/session-fts.js +379 -0
- package/hooks/lib/session-store.js +293 -0
- package/hooks/lib/singleton-guard.js +159 -0
- package/hooks/lib/skill-auditor.js +588 -0
- package/hooks/lib/sync-status.js +228 -0
- package/hooks/lib/taint-tracker.js +107 -0
- package/hooks/lib/task-service.js +295 -0
- package/hooks/lib/tech-skills-map.js +146 -0
- package/hooks/lib/telegram-cliente.js +159 -0
- package/hooks/lib/telegram-config.js +170 -0
- package/hooks/lib/token-budget.js +156 -0
- package/hooks/lib/token-estimator.js +420 -0
- package/hooks/lib/toon-compressor.js +245 -0
- package/hooks/lib/usage-model.js +183 -0
- package/hooks/lib/variable-resolver.js +230 -0
- package/hooks/linea-estado.js +324 -0
- package/hooks/metricas-evolucion.js +209 -0
- package/hooks/monitor-contexto.js +325 -0
- package/hooks/notificacion-sesion-stop.js +198 -0
- package/hooks/notificacion-telegram-notification.js +4 -0
- package/hooks/notificacion-telegram-subagent.js +4 -0
- package/hooks/notificacion-telegram.js +267 -0
- package/hooks/preservar-estado-pre-compact.js +150 -0
- package/hooks/proteccion-rutas.js +366 -0
- package/hooks/registro-turnos.js +209 -0
- package/hooks/resumen-sesion.js +249 -0
- package/hooks/risk-scoring.js +323 -0
- package/hooks/rotar-audit-auto.js +122 -0
- package/hooks/sugerir-regenerar-inventario.js +170 -0
- package/hooks/telemetria-agentes.js +167 -0
- package/hooks/tracking-costos.js +688 -0
- package/instintos/global.yaml +8 -0
- package/instintos/perfil-usuario.yaml +53 -0
- package/instintos/prompt-appendices.yaml +57 -0
- package/instintos/proyecto.yaml +372 -0
- package/manifiestos/gateway-config.json +77 -0
- package/manifiestos/handoff-context.json +223 -0
- package/manifiestos/hook-profiles.json +44 -0
- package/manifiestos/hooks-config.json +360 -0
- package/manifiestos/modulos.json +1173 -0
- package/manifiestos/perfiles.json +404 -0
- package/package.json +86 -0
- package/plantillas/ESTADO.md +109 -0
- package/plantillas/HOJA-RUTA.md +143 -0
- package/plantillas/PROYECTO.md +122 -0
- package/plantillas/REQUISITOS.md +132 -0
- package/plantillas/auditor-veto-template.md +105 -0
- package/plantillas/github-workflows/README.md +47 -0
- package/plantillas/github-workflows/release-please.yml +44 -0
- package/plantillas/github-workflows/swl-ci.yml +107 -0
- package/plantillas/github-workflows/swl-security.yml +51 -0
- package/plantillas/mcp-mineru.json +13 -0
- package/plantillas/research/ARQUITECTURA.md +220 -0
- package/plantillas/research/FUNCIONALIDADES.md +175 -0
- package/plantillas/research/RESUMEN.md +165 -0
- package/plantillas/research/STACK.md +233 -0
- package/plantillas/research/TRAMPAS.md +299 -0
- package/plantillas/skill-evals-template.json +44 -0
- package/plugin.json +343 -0
- package/reglas/accesibilidad.md +269 -0
- package/reglas/api-diseno.md +400 -0
- package/reglas/arquitectura.md +352 -0
- package/reglas/brevedad-output.md +124 -0
- package/reglas/cloud-infra.md +247 -0
- package/reglas/docs.md +245 -0
- package/reglas/estilo-codigo.md +201 -0
- package/reglas/git-workflow.md +245 -0
- package/reglas/gobernanza.md +271 -0
- package/reglas/harness-claude-code.md +213 -0
- package/reglas/hooks.md +186 -0
- package/reglas/lenguajes/csharp/estilo-codigo.md +231 -0
- package/reglas/lenguajes/csharp/hooks.md +281 -0
- package/reglas/lenguajes/csharp/patrones.md +226 -0
- package/reglas/lenguajes/csharp/seguridad.md +258 -0
- package/reglas/lenguajes/csharp/testing.md +176 -0
- package/reglas/lenguajes/go/estilo-codigo.md +195 -0
- package/reglas/lenguajes/go/hooks.md +249 -0
- package/reglas/lenguajes/go/patrones.md +249 -0
- package/reglas/lenguajes/go/seguridad.md +225 -0
- package/reglas/lenguajes/go/testing.md +272 -0
- package/reglas/lenguajes/java/estilo-codigo.md +217 -0
- package/reglas/lenguajes/java/hooks.md +251 -0
- package/reglas/lenguajes/java/patrones.md +226 -0
- package/reglas/lenguajes/java/seguridad.md +233 -0
- package/reglas/lenguajes/java/testing.md +238 -0
- package/reglas/lenguajes/kotlin/estilo-codigo.md +208 -0
- package/reglas/lenguajes/kotlin/hooks.md +245 -0
- package/reglas/lenguajes/kotlin/patrones.md +201 -0
- package/reglas/lenguajes/kotlin/seguridad.md +202 -0
- package/reglas/lenguajes/kotlin/testing.md +236 -0
- package/reglas/lenguajes/nextjs/estilo-codigo.md +175 -0
- package/reglas/lenguajes/nextjs/hooks.md +186 -0
- package/reglas/lenguajes/nextjs/patrones.md +225 -0
- package/reglas/lenguajes/nextjs/seguridad.md +216 -0
- package/reglas/lenguajes/nextjs/testing.md +193 -0
- package/reglas/lenguajes/php/estilo-codigo.md +228 -0
- package/reglas/lenguajes/php/hooks.md +165 -0
- package/reglas/lenguajes/php/patrones.md +233 -0
- package/reglas/lenguajes/php/seguridad.md +186 -0
- package/reglas/lenguajes/php/testing.md +205 -0
- package/reglas/lenguajes/rust/estilo-codigo.md +207 -0
- package/reglas/lenguajes/rust/hooks.md +240 -0
- package/reglas/lenguajes/rust/patrones.md +250 -0
- package/reglas/lenguajes/rust/seguridad.md +221 -0
- package/reglas/lenguajes/rust/testing.md +194 -0
- package/reglas/lenguajes/swift/estilo-codigo.md +238 -0
- package/reglas/lenguajes/swift/hooks.md +257 -0
- package/reglas/lenguajes/swift/patrones.md +235 -0
- package/reglas/lenguajes/swift/seguridad.md +248 -0
- package/reglas/lenguajes/swift/testing.md +242 -0
- package/reglas/markitdown.md +60 -0
- package/reglas/memoria-consolidada.md +209 -0
- package/reglas/patrones.md +225 -0
- package/reglas/performance.md +195 -0
- package/reglas/pruebas.md +159 -0
- package/reglas/seguridad-agentes.md +351 -0
- package/reglas/seguridad.md +151 -0
- package/reglas/skills-estandar.md +373 -0
- package/reglas/testing.md +193 -0
- package/schemas/agent-contract.json +176 -0
- package/schemas/agent-frontmatter.schema.json +149 -0
- package/schemas/agent-message.schema.json +53 -0
- package/schemas/agent-output-implementacion.schema.json +85 -0
- package/schemas/agent-output-planificacion.schema.json +113 -0
- package/schemas/agent-output-review.schema.json +78 -0
- package/schemas/diary-entry.schema.json +80 -0
- package/schemas/hook-profiles.schema.json +39 -0
- package/schemas/hooks-config.schema.json +74 -0
- package/schemas/instinct.schema.json +115 -0
- package/schemas/modulos.schema.json +29 -0
- package/schemas/perfiles.schema.json +28 -0
- package/schemas/plugin.schema.json +64 -0
- package/schemas/skill-evals.schema.json +95 -0
- package/schemas/skill-frontmatter.schema.json +170 -0
- package/scripts/actualizar.js +145 -0
- package/scripts/audit-skills.sh +78 -0
- package/scripts/auditar-agentes-gaps.js +149 -0
- package/scripts/auditar-cobertura-frameworks.js +241 -0
- package/scripts/auditar-skills-gaps.js +206 -0
- package/scripts/bootstrap-instintos.js +259 -0
- package/scripts/check-update.js +109 -0
- package/scripts/comandos/agents.js +105 -0
- package/scripts/comandos/info.js +108 -0
- package/scripts/comandos/install-asistido.js +186 -0
- package/scripts/comandos/skills.js +211 -0
- package/scripts/configurar-branch-protection.js +418 -0
- package/scripts/daemon-swl.py +388 -0
- package/scripts/desinstalar.js +130 -0
- package/scripts/doctor.js +559 -0
- package/scripts/field-report.js +199 -0
- package/scripts/generar-inventario.js +317 -0
- package/scripts/inbox-tmux-inject.js +161 -0
- package/scripts/inferir-herramientas-permitidas.js +586 -0
- package/scripts/inicializar.js +133 -0
- package/scripts/instalador.js +1031 -0
- package/scripts/instalar-git-hook.js +122 -0
- package/scripts/lib/agp-frontmatter.js +222 -0
- package/scripts/lib/append-con-marcadores.js +199 -0
- package/scripts/lib/artefactos-python.js +43 -0
- package/scripts/lib/audit-query.js +221 -0
- package/scripts/lib/autostart-linux.js +347 -0
- package/scripts/lib/autostart-macos.js +360 -0
- package/scripts/lib/autostart-windows.js +307 -0
- package/scripts/lib/budget-enforcer.js +252 -0
- package/scripts/lib/claude-sessions.js +285 -0
- package/scripts/lib/configurar-ci.js +380 -0
- package/scripts/lib/console-span-exporter.js +92 -0
- package/scripts/lib/contadores-inventario.js +217 -0
- package/scripts/lib/dashboard-widgets.js +290 -0
- package/scripts/lib/detectar-runtime.js +279 -0
- package/scripts/lib/detectar-stack.js +187 -0
- package/scripts/lib/diary-entry.js +234 -0
- package/scripts/lib/drift-detector.js +545 -0
- package/scripts/lib/estado.js +124 -0
- package/scripts/lib/gestor-componentes.js +243 -0
- package/scripts/lib/gitignore-manifest.js +305 -0
- package/scripts/lib/graph-analyze.py +556 -0
- package/scripts/lib/graph-builder.py +485 -0
- package/scripts/lib/graph-cluster.py +259 -0
- package/scripts/lib/health-row.js +168 -0
- package/scripts/lib/hooks-settings.js +789 -0
- package/scripts/lib/manifiestos.js +138 -0
- package/scripts/lib/mc-client.js +137 -0
- package/scripts/lib/notificaciones-telegram.js +1107 -0
- package/scripts/lib/npm-version.js +261 -0
- package/scripts/lib/paquetes-conocidos.js +50 -0
- package/scripts/lib/preservar-usuario.js +586 -0
- package/scripts/lib/prompt-builder.js +264 -0
- package/scripts/lib/resolver-externo.js +332 -0
- package/scripts/lib/schedule-parser.js +305 -0
- package/scripts/lib/scoring-instintos.js +240 -0
- package/scripts/lib/seguridad.js +160 -0
- package/scripts/lib/selector-interactivo.js +152 -0
- package/scripts/lib/semantic-search.js +242 -0
- package/scripts/lib/skill-discovery.js +234 -0
- package/scripts/lib/skill-metrics.js +246 -0
- package/scripts/lib/skill-normalizer.js +112 -0
- package/scripts/lib/skills-hub.js +340 -0
- package/scripts/lib/span-schema.js +134 -0
- package/scripts/lib/tool-cost-analyzer.js +255 -0
- package/scripts/lib/tracing-processor-interface.js +286 -0
- package/scripts/lib/transformadores/base.js +80 -0
- package/scripts/lib/transformadores/claude.js +124 -0
- package/scripts/lib/transformadores/codex.js +115 -0
- package/scripts/lib/transformadores/copilot.js +106 -0
- package/scripts/lib/transformadores/gemini.js +74 -0
- package/scripts/lib/transformadores/index.js +35 -0
- package/scripts/lib/transformadores/opencode.js +75 -0
- package/scripts/lib/ui.js +259 -0
- package/scripts/limpiar-artefactos-python.js +131 -0
- package/scripts/mcp-orchestrator.py +386 -0
- package/scripts/mcp-pool-manager.py +352 -0
- package/scripts/mcp-telemetry.py +378 -0
- package/scripts/poblar-evolvable.js +226 -0
- package/scripts/publicar.js +287 -0
- package/scripts/reflect-skills.js +403 -0
- package/scripts/rotar-audit-logs.js +185 -0
- package/scripts/run-skill-evals.js +242 -0
- package/scripts/smoke-test.js +374 -0
- package/scripts/token-analysis.py +471 -0
- package/scripts/validar-manifest.js +195 -0
- package/scripts/validar-memoria.js +321 -0
- package/scripts/validar-tests-aislamiento.js +184 -0
- package/scripts/validar-tokens-test.js +208 -0
- package/scripts/validar.js +147 -0
- package/scripts/validate-markdown.py +339 -0
- package/scripts/validate-skills.py +385 -0
- package/scripts/vendor/claude-usage/README.md +116 -0
- package/scripts/vendor/claude-usage/cli.py +334 -0
- package/scripts/vendor/claude-usage/dashboard.py +795 -0
- package/scripts/vendor/claude-usage/scanner.py +467 -0
- package/scripts/vendor/markitdown/cli.py +194 -0
- package/scripts/verificar-evolucion.js +289 -0
- package/scripts/verificar-release.js +494 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
# React Experto — Patrones y Ejemplos Completos
|
|
2
|
+
|
|
3
|
+
Referencia extendida de la skill `react-experto`. Contiene ejemplos completos
|
|
4
|
+
de data fetching, state management, performance patterns y Next.js App Router.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## React Query — Ejemplo completo
|
|
9
|
+
|
|
10
|
+
```tsx
|
|
11
|
+
"use client";
|
|
12
|
+
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
|
13
|
+
|
|
14
|
+
export function ListaUsuarios() {
|
|
15
|
+
const { data, isPending, error } = useQuery({
|
|
16
|
+
queryKey: ['usuarios'],
|
|
17
|
+
queryFn: () => fetch('/api/usuarios').then(r => r.json()),
|
|
18
|
+
staleTime: 5 * 60 * 1000, // 5 minutos
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
if (isPending) return <Skeleton />;
|
|
22
|
+
if (error) return <ErrorMessage error={error} />;
|
|
23
|
+
|
|
24
|
+
return <ul>{data.map(u => <li key={u.id}>{u.nombre}</li>)}</ul>;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Mutacion con invalidacion de cache
|
|
28
|
+
export function CrearUsuario() {
|
|
29
|
+
const queryClient = useQueryClient();
|
|
30
|
+
const mutation = useMutation({
|
|
31
|
+
mutationFn: (nuevoUsuario) =>
|
|
32
|
+
fetch('/api/usuarios', {
|
|
33
|
+
method: 'POST',
|
|
34
|
+
body: JSON.stringify(nuevoUsuario),
|
|
35
|
+
}).then(r => r.json()),
|
|
36
|
+
onSuccess: () => {
|
|
37
|
+
queryClient.invalidateQueries({ queryKey: ['usuarios'] });
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<button onClick={() => mutation.mutate({ nombre: 'Ana' })}>
|
|
43
|
+
Crear usuario
|
|
44
|
+
</button>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Server Actions — Formularios y mutaciones desde RSC
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
// app/actions/usuario.ts
|
|
55
|
+
"use server";
|
|
56
|
+
import { revalidatePath } from 'next/cache';
|
|
57
|
+
import { db } from '@/lib/db';
|
|
58
|
+
import { z } from 'zod';
|
|
59
|
+
|
|
60
|
+
const UsuarioSchema = z.object({
|
|
61
|
+
nombre: z.string().min(2),
|
|
62
|
+
email: z.string().email(),
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
export async function crearUsuario(formData: FormData) {
|
|
66
|
+
const resultado = UsuarioSchema.safeParse({
|
|
67
|
+
nombre: formData.get('nombre'),
|
|
68
|
+
email: formData.get('email'),
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
if (!resultado.success) {
|
|
72
|
+
return { error: resultado.error.flatten() };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
await db.usuario.create({ data: resultado.data });
|
|
76
|
+
revalidatePath('/usuarios');
|
|
77
|
+
return { success: true };
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Uso en un form (Server Component)
|
|
81
|
+
export default function FormularioUsuario() {
|
|
82
|
+
return (
|
|
83
|
+
<form action={crearUsuario}>
|
|
84
|
+
<input name="nombre" required />
|
|
85
|
+
<input name="email" type="email" required />
|
|
86
|
+
<button type="submit">Crear</button>
|
|
87
|
+
</form>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## State Management — Zustand
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
// lib/store/usuario.store.ts
|
|
98
|
+
import { create } from 'zustand';
|
|
99
|
+
import { immer } from 'zustand/middleware/immer';
|
|
100
|
+
|
|
101
|
+
interface UsuarioStore {
|
|
102
|
+
usuarios: Usuario[];
|
|
103
|
+
filtro: string;
|
|
104
|
+
setFiltro: (filtro: string) => void;
|
|
105
|
+
agregarUsuario: (usuario: Usuario) => void;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export const useUsuarioStore = create<UsuarioStore>()(
|
|
109
|
+
immer((set) => ({
|
|
110
|
+
usuarios: [],
|
|
111
|
+
filtro: '',
|
|
112
|
+
setFiltro: (filtro) => set(state => { state.filtro = filtro; }),
|
|
113
|
+
agregarUsuario: (usuario) => set(state => {
|
|
114
|
+
state.usuarios.push(usuario);
|
|
115
|
+
}),
|
|
116
|
+
}))
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
// Selectores especificos para evitar re-renders
|
|
120
|
+
export const useFiltroDatos = () =>
|
|
121
|
+
useUsuarioStore(state => state.filtro);
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## State Management — Jotai
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
// lib/atoms/filtros.ts
|
|
130
|
+
import { atom, useAtom, useAtomValue } from 'jotai';
|
|
131
|
+
|
|
132
|
+
const filtroBaseAtom = atom('');
|
|
133
|
+
const usuariosAtom = atom<Usuario[]>([]);
|
|
134
|
+
|
|
135
|
+
// Atomo derivado (computed)
|
|
136
|
+
const usuariosFiltradosAtom = atom(get => {
|
|
137
|
+
const filtro = get(filtroBaseAtom).toLowerCase();
|
|
138
|
+
return get(usuariosAtom).filter(u =>
|
|
139
|
+
u.nombre.toLowerCase().includes(filtro)
|
|
140
|
+
);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// Uso
|
|
144
|
+
function ListaFiltrada() {
|
|
145
|
+
const usuariosFiltrados = useAtomValue(usuariosFiltradosAtom);
|
|
146
|
+
return <ul>{usuariosFiltrados.map(...)}</ul>;
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Next.js App Router — Estructura de directorios
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
app/
|
|
156
|
+
+-- layout.tsx # Layout raiz (Server Component)
|
|
157
|
+
+-- page.tsx # Home
|
|
158
|
+
+-- loading.tsx # UI de carga automatica (Suspense)
|
|
159
|
+
+-- error.tsx # Manejo de errores ('use client')
|
|
160
|
+
+-- not-found.tsx # 404
|
|
161
|
+
+-- (auth)/ # Route Group — no afecta URL
|
|
162
|
+
| +-- login/page.tsx
|
|
163
|
+
| +-- registro/page.tsx
|
|
164
|
+
+-- dashboard/
|
|
165
|
+
| +-- layout.tsx # Layout anidado
|
|
166
|
+
| +-- page.tsx
|
|
167
|
+
| +-- [id]/
|
|
168
|
+
| +-- page.tsx # Ruta dinamica
|
|
169
|
+
+-- api/
|
|
170
|
+
+-- usuarios/
|
|
171
|
+
+-- route.ts # Route Handler
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Route Handlers (API routes)
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
// app/api/usuarios/route.ts
|
|
180
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
181
|
+
import { db } from '@/lib/db';
|
|
182
|
+
|
|
183
|
+
export async function GET(req: NextRequest) {
|
|
184
|
+
const { searchParams } = new URL(req.url);
|
|
185
|
+
const pagina = Number(searchParams.get('pagina') ?? '1');
|
|
186
|
+
|
|
187
|
+
const usuarios = await db.usuario.findMany({
|
|
188
|
+
skip: (pagina - 1) * 20,
|
|
189
|
+
take: 20,
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
return NextResponse.json({ items: usuarios, pagina });
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export async function POST(req: NextRequest) {
|
|
196
|
+
const body = await req.json();
|
|
197
|
+
const usuario = await db.usuario.create({ data: body });
|
|
198
|
+
return NextResponse.json(usuario, { status: 201 });
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## Metadata dinamica
|
|
205
|
+
|
|
206
|
+
```tsx
|
|
207
|
+
// app/usuarios/[id]/page.tsx
|
|
208
|
+
export async function generateMetadata({ params }: Props) {
|
|
209
|
+
const usuario = await getUsuario(params.id);
|
|
210
|
+
return {
|
|
211
|
+
title: `${usuario.nombre} — Mi App`,
|
|
212
|
+
description: `Perfil de ${usuario.nombre}`,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Streaming con Suspense (Next.js App Router)
|
|
220
|
+
|
|
221
|
+
```tsx
|
|
222
|
+
// app/dashboard/page.tsx
|
|
223
|
+
import { Suspense } from 'react';
|
|
224
|
+
|
|
225
|
+
export default function DashboardPage() {
|
|
226
|
+
return (
|
|
227
|
+
<div>
|
|
228
|
+
<Encabezado />
|
|
229
|
+
|
|
230
|
+
<Suspense fallback={<SkeletonGrafica />}>
|
|
231
|
+
<GraficaVentas />
|
|
232
|
+
</Suspense>
|
|
233
|
+
|
|
234
|
+
<Suspense fallback={<SkeletonTabla />}>
|
|
235
|
+
<TablaReciente />
|
|
236
|
+
</Suspense>
|
|
237
|
+
</div>
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
```
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: react-optimizacion
|
|
3
|
+
description: Optimización de rendimiento en React. memo, useMemo, useCallback, code splitting, lazy loading, concurrent features, Suspense y patrones de estado eficiente.
|
|
4
|
+
version: "1.0.0"
|
|
5
|
+
herramientasPermitidas: [Read, Grep]
|
|
6
|
+
exclusiones:
|
|
7
|
+
- "No cargar para patrones generales de React (Server Components, data fetching, state management) — para fundamentos cargar `react-experto`."
|
|
8
|
+
- "No cargar para optimización de rendimiento en Angular — las APIs de signals y OnPush son distintas; cargar `angular-moderno` o `angular-avanzado`."
|
|
9
|
+
- "No cargar para optimización CSS o de imágenes (lazy loading de assets) — para CSS cargar `css-moderno` o `tailwind-experto`."
|
|
10
|
+
- "No cargar para profiling de backend o queries SQL — la optimización aquí es exclusivamente del renderizado y bundling del cliente React."
|
|
11
|
+
evolvable: true # default para skill estandar
|
|
12
|
+
---
|
|
13
|
+
# Optimización de Rendimiento en React
|
|
14
|
+
|
|
15
|
+
## Cuándo NO cargar
|
|
16
|
+
|
|
17
|
+
- La tarea es sobre patrones generales de React: Server Components, data fetching, state management — cargar `react-experto`.
|
|
18
|
+
- La optimización es para Angular — las APIs de signals, OnPush y zoneless son distintas; cargar `angular-moderno` o `angular-avanzado`.
|
|
19
|
+
- El tema es optimización de CSS, imágenes o assets estáticos — cargar `css-moderno` o `tailwind-experto`.
|
|
20
|
+
- El cuello de botella es el backend o queries SQL, no el renderizado del cliente — este skill es exclusivamente de rendimiento React en el cliente.
|
|
21
|
+
|
|
22
|
+
## Principio de optimización prematura
|
|
23
|
+
|
|
24
|
+
**No optimices antes de medir.** La mayoría de los problemas de rendimiento en React
|
|
25
|
+
provienen de re-renders innecesarios o de carga inicial pesada. Primero identifica
|
|
26
|
+
el cuello de botella con React DevTools Profiler, luego aplica la solución correcta.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Re-renders: cuándo ocurren y cómo controlarlos
|
|
31
|
+
|
|
32
|
+
Un componente se re-renderiza cuando:
|
|
33
|
+
1. Su propio estado cambia (`useState`, `useReducer`).
|
|
34
|
+
2. Su componente padre se re-renderiza (incluso si las props no cambiaron).
|
|
35
|
+
3. Un contexto del que consume cambia.
|
|
36
|
+
|
|
37
|
+
### React.memo — evitar re-renders por props iguales
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
import React, { memo } from 'react';
|
|
41
|
+
|
|
42
|
+
const FacturaCard = memo(function FacturaCard({
|
|
43
|
+
factura,
|
|
44
|
+
onCancelar,
|
|
45
|
+
}: {
|
|
46
|
+
factura: Factura;
|
|
47
|
+
onCancelar: (id: string) => void;
|
|
48
|
+
}) {
|
|
49
|
+
return (
|
|
50
|
+
<div className="border rounded-lg p-4">
|
|
51
|
+
<h3>{factura.folio}</h3>
|
|
52
|
+
<button onClick={() => onCancelar(factura.id)}>Cancelar</button>
|
|
53
|
+
</div>
|
|
54
|
+
);
|
|
55
|
+
});
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### useMemo — memorizar cálculos costosos
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
const estadisticas = useMemo(() => ({
|
|
62
|
+
total: facturas.reduce((sum, f) => sum + f.monto, 0),
|
|
63
|
+
emitidas: facturas.filter(f => f.estatus === 'emitida').length,
|
|
64
|
+
}), [facturas]);
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### useCallback — estabilizar referencias de funciones
|
|
68
|
+
|
|
69
|
+
```tsx
|
|
70
|
+
// Sin useCallback, nueva referencia en cada render → memo del hijo no funciona
|
|
71
|
+
const handleCancelar = useCallback((id: string) => {
|
|
72
|
+
setFacturas(prev => prev.map(f =>
|
|
73
|
+
f.id === id ? { ...f, estatus: 'cancelada' } : f
|
|
74
|
+
));
|
|
75
|
+
}, []); // Sin dependencias porque usa setter funcional
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Code Splitting y Lazy Loading
|
|
81
|
+
|
|
82
|
+
### React.lazy + Suspense
|
|
83
|
+
|
|
84
|
+
```tsx
|
|
85
|
+
import React, { lazy, Suspense } from 'react';
|
|
86
|
+
import { Routes, Route } from 'react-router-dom';
|
|
87
|
+
|
|
88
|
+
const FacturasPage = lazy(() => import('./pages/FacturasPage'));
|
|
89
|
+
const ReportesPage = lazy(() => import('./pages/ReportesPage'));
|
|
90
|
+
|
|
91
|
+
function App() {
|
|
92
|
+
return (
|
|
93
|
+
<Suspense fallback={<PageLoader />}>
|
|
94
|
+
<Routes>
|
|
95
|
+
<Route path="/facturas" element={<FacturasPage />} />
|
|
96
|
+
<Route path="/reportes" element={<ReportesPage />} />
|
|
97
|
+
</Routes>
|
|
98
|
+
</Suspense>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Lazy loading de componentes pesados
|
|
104
|
+
|
|
105
|
+
```tsx
|
|
106
|
+
const GraficaVentas = lazy(() => import('./GraficaVentas'));
|
|
107
|
+
|
|
108
|
+
function Dashboard() {
|
|
109
|
+
const [mostrarGrafica, setMostrarGrafica] = useState(false);
|
|
110
|
+
return (
|
|
111
|
+
<div>
|
|
112
|
+
<button onClick={() => setMostrarGrafica(true)}>Ver gráfica</button>
|
|
113
|
+
{mostrarGrafica && (
|
|
114
|
+
<Suspense fallback={<div className="h-64 animate-pulse bg-gray-100" />}>
|
|
115
|
+
<GraficaVentas />
|
|
116
|
+
</Suspense>
|
|
117
|
+
)}
|
|
118
|
+
</div>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Concurrent Features — resumen
|
|
126
|
+
|
|
127
|
+
- **useTransition**: marca actualizaciones como no urgentes. El input responde inmediatamente mientras los resultados se calculan en segundo plano.
|
|
128
|
+
- **useDeferredValue**: crea una versión diferida de un valor para mantener el UI fluido.
|
|
129
|
+
|
|
130
|
+
Para ejemplos completos de useTransition, useDeferredValue, virtualización y optimización de Context, ver [recursos/patrones-avanzados.md](recursos/patrones-avanzados.md).
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Virtualización para listas largas
|
|
135
|
+
|
|
136
|
+
Para listas de >100 elementos, usar `@tanstack/react-virtual` para renderizar solo los elementos visibles. Esto reduce el DOM de miles de nodos a decenas.
|
|
137
|
+
|
|
138
|
+
Para implementación completa, ver [recursos/patrones-avanzados.md](recursos/patrones-avanzados.md).
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Optimización de Context
|
|
143
|
+
|
|
144
|
+
El contexto causa re-render en TODOS los consumidores cuando cambia. Reglas:
|
|
145
|
+
- **Separar** contextos por dominio y frecuencia de cambio (Auth, UI, Datos).
|
|
146
|
+
- **Estabilizar** el valor con `useMemo` para evitar objetos nuevos en cada render.
|
|
147
|
+
- NUNCA un solo contexto monolítico con todo el estado de la app.
|
|
148
|
+
|
|
149
|
+
Para ejemplo completo de AuthProvider optimizado, ver [recursos/patrones-avanzados.md](recursos/patrones-avanzados.md).
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Cuándo NO usar memo/useMemo/useCallback
|
|
154
|
+
|
|
155
|
+
Estas optimizaciones tienen un costo: complejidad de código y overhead de comparación.
|
|
156
|
+
No aplicar cuando:
|
|
157
|
+
|
|
158
|
+
- El componente es simple y rápido de renderizar.
|
|
159
|
+
- Las props cambian en casi todos los re-renders de todas formas.
|
|
160
|
+
- El cálculo en `useMemo` es trivial (suma de 3 números).
|
|
161
|
+
- No hay evidencia medida de problema de rendimiento.
|
|
162
|
+
|
|
163
|
+
**Regla práctica**: medir primero con React DevTools Profiler. Si un componente
|
|
164
|
+
aparece en llamas largas o con muchos re-renders no esperados, entonces optimizar.
|
|
165
|
+
|
|
166
|
+
## Gotchas / Errores comunes no obvios
|
|
167
|
+
|
|
168
|
+
**`React.memo` no previene re-renders si alguna prop es una función o array creado inline**: `<Lista onSeleccionar={() => handleSelect(id)} />` crea una nueva referencia de función en cada render del padre — `memo` compara con `===` y siempre detecta cambio. Causa: las funciones y objetos literales tienen identidad diferente en cada render. Fix: estabilizar con `useCallback` la función y con `useMemo` los arrays/objetos antes de pasarlos como props a componentes memoizados.
|
|
169
|
+
|
|
170
|
+
**`useMemo` con dependencias que incluyen objetos del estado no evita recálculos porque el objeto es siempre nuevo**: `useMemo(() => calcular(filtros), [filtros])` recalcula en cada render si `filtros` es `{ texto: '', page: 1 }` definido en el render como literal. Causa: el objeto es una referencia nueva aunque sus valores sean iguales. Fix: usar propiedades primitivas como dependencias (`[filtros.texto, filtros.page]`) en lugar del objeto completo.
|
|
171
|
+
|
|
172
|
+
**`useTransition` marca la actualización como diferida pero no previene el bloqueo del hilo principal si el cálculo es síncrono costoso**: `startTransition(() => setFiltros(nuevoFiltro))` pospone la actualización de UI pero si el componente resultante tarda 200ms en renderizarse síncronamente, el hilo principal sigue bloqueado. Causa: `useTransition` prioriza, no paraleliza — React aún renderiza síncronamente. Fix: combinar con `useDeferredValue` para el valor que dispara el cálculo costoso, o mover el cálculo a un Web Worker.
|
|
173
|
+
|
|
174
|
+
**Virtualización con `@tanstack/react-virtual` falla cuando el contenedor no tiene altura fija**: el virtualizador necesita saber el tamaño del contenedor para calcular qué items son visibles — si el contenedor crece con el contenido (sin `height` o `overflow: auto`), estima incorrectamente y renderiza demasiados o muy pocos items. Causa: `useVirtualizer` lee `scrollElement.clientHeight` para calcular el viewport. Fix: dar al contenedor una altura fija (`height: 400px`) o relativa (`height: 100%` con el padre acotado) y `overflow: auto`.
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# React Optimizacion — Patrones avanzados y ejemplos completos
|
|
2
|
+
|
|
3
|
+
## Concurrent Features
|
|
4
|
+
|
|
5
|
+
### useTransition — marcar actualizaciones como no urgentes
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { useTransition, useState } from 'react';
|
|
9
|
+
|
|
10
|
+
function BuscadorFacturas() {
|
|
11
|
+
const [query, setQuery] = useState('');
|
|
12
|
+
const [resultados, setResultados] = useState<Factura[]>([]);
|
|
13
|
+
const [isPending, startTransition] = useTransition();
|
|
14
|
+
|
|
15
|
+
const handleBusqueda = (valor: string) => {
|
|
16
|
+
// Actualización urgente: el input responde inmediatamente
|
|
17
|
+
setQuery(valor);
|
|
18
|
+
|
|
19
|
+
// Actualización no urgente: los resultados pueden esperar
|
|
20
|
+
startTransition(() => {
|
|
21
|
+
const filtrados = buscarFacturas(valor);
|
|
22
|
+
setResultados(filtrados);
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<div>
|
|
28
|
+
<input
|
|
29
|
+
value={query}
|
|
30
|
+
onChange={e => handleBusqueda(e.target.value)}
|
|
31
|
+
placeholder="Buscar facturas..."
|
|
32
|
+
/>
|
|
33
|
+
{isPending && <span className="text-gray-400">Buscando...</span>}
|
|
34
|
+
<ListaResultados resultados={resultados} />
|
|
35
|
+
</div>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### useDeferredValue — versión diferida de un valor
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
import { useDeferredValue, memo } from 'react';
|
|
44
|
+
|
|
45
|
+
function ListaFiltrada({ items }: { items: string[] }) {
|
|
46
|
+
const [filtro, setFiltro] = useState('');
|
|
47
|
+
// Versión diferida del filtro — permite que el input sea fluido
|
|
48
|
+
const filtroDeferred = useDeferredValue(filtro);
|
|
49
|
+
|
|
50
|
+
// isStale detecta si estamos mostrando resultado desactualizado
|
|
51
|
+
const isStale = filtro !== filtroDeferred;
|
|
52
|
+
|
|
53
|
+
const itemsFiltrados = useMemo(
|
|
54
|
+
() => items.filter(item => item.includes(filtroDeferred)),
|
|
55
|
+
[items, filtroDeferred]
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<div>
|
|
60
|
+
<input value={filtro} onChange={e => setFiltro(e.target.value)} />
|
|
61
|
+
<ul style={{ opacity: isStale ? 0.6 : 1 }}>
|
|
62
|
+
{itemsFiltrados.map(item => <li key={item}>{item}</li>)}
|
|
63
|
+
</ul>
|
|
64
|
+
</div>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Virtualización para listas largas
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
import { useVirtualizer } from '@tanstack/react-virtual';
|
|
75
|
+
import { useRef } from 'react';
|
|
76
|
+
|
|
77
|
+
function ListaVirtualizada({ facturas }: { facturas: Factura[] }) {
|
|
78
|
+
const contenedorRef = useRef<HTMLDivElement>(null);
|
|
79
|
+
|
|
80
|
+
const virtualizer = useVirtualizer({
|
|
81
|
+
count: facturas.length,
|
|
82
|
+
getScrollElement: () => contenedorRef.current,
|
|
83
|
+
estimateSize: () => 80, // altura estimada en px por fila
|
|
84
|
+
overscan: 5, // filas extra fuera del viewport
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<div ref={contenedorRef} style={{ height: '600px', overflow: 'auto' }}>
|
|
89
|
+
<div style={{ height: `${virtualizer.getTotalSize()}px`, position: 'relative' }}>
|
|
90
|
+
{virtualizer.getVirtualItems().map(virtualItem => (
|
|
91
|
+
<div
|
|
92
|
+
key={virtualItem.key}
|
|
93
|
+
style={{
|
|
94
|
+
position: 'absolute',
|
|
95
|
+
top: 0,
|
|
96
|
+
left: 0,
|
|
97
|
+
width: '100%',
|
|
98
|
+
transform: `translateY(${virtualItem.start}px)`,
|
|
99
|
+
}}
|
|
100
|
+
>
|
|
101
|
+
<FacturaCard factura={facturas[virtualItem.index]} />
|
|
102
|
+
</div>
|
|
103
|
+
))}
|
|
104
|
+
</div>
|
|
105
|
+
</div>
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Optimización de Context — ejemplo completo
|
|
113
|
+
|
|
114
|
+
El contexto causa re-render en TODOS los consumidores cuando cambia.
|
|
115
|
+
Dividir en contextos más pequeños o usar selectores:
|
|
116
|
+
|
|
117
|
+
```tsx
|
|
118
|
+
// MAL: un solo contexto con todo el estado
|
|
119
|
+
const AppContext = createContext<AppState>({...});
|
|
120
|
+
|
|
121
|
+
// BIEN: separar por dominio y frecuencia de cambio
|
|
122
|
+
const AuthContext = createContext<AuthState>({...}); // Cambia raramente
|
|
123
|
+
const UIContext = createContext<UIState>({...}); // Cambia frecuentemente
|
|
124
|
+
const FacturasContext = createContext<FacturasState>({...}); // Cambia al interactuar
|
|
125
|
+
|
|
126
|
+
// BIEN: con useMemo para estabilizar el valor del contexto
|
|
127
|
+
function AuthProvider({ children }: { children: React.ReactNode }) {
|
|
128
|
+
const [usuario, setUsuario] = useState<Usuario | null>(null);
|
|
129
|
+
|
|
130
|
+
const value = useMemo(() => ({
|
|
131
|
+
usuario,
|
|
132
|
+
login: async (creds: Credentials) => { ... },
|
|
133
|
+
logout: () => setUsuario(null),
|
|
134
|
+
}), [usuario]); // Solo se crea objeto nuevo cuando usuario cambia
|
|
135
|
+
|
|
136
|
+
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
|
|
137
|
+
}
|
|
138
|
+
```
|