@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,216 @@
|
|
|
1
|
+
# React Native — Ejemplos Completos
|
|
2
|
+
|
|
3
|
+
## React Navigation (proyectos existentes)
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
// navigation/AppNavigator.tsx
|
|
7
|
+
import { createNativeStackNavigator } from '@react-navigation/native-stack';
|
|
8
|
+
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
|
|
9
|
+
|
|
10
|
+
const Stack = createNativeStackNavigator<RootStackParamList>();
|
|
11
|
+
const Tab = createBottomTabNavigator<TabParamList>();
|
|
12
|
+
|
|
13
|
+
// Tipos tipados para navegación segura
|
|
14
|
+
export type RootStackParamList = {
|
|
15
|
+
Home: undefined;
|
|
16
|
+
DetalleUsuario: { id: string; nombre: string };
|
|
17
|
+
Modal: { contenido: string };
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
// Hook tipado
|
|
21
|
+
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
|
|
22
|
+
type NavProp = NativeStackNavigationProp<RootStackParamList, 'Home'>;
|
|
23
|
+
|
|
24
|
+
function HomeScreen() {
|
|
25
|
+
const navigation = useNavigation<NavProp>();
|
|
26
|
+
return (
|
|
27
|
+
<Button onPress={() => navigation.navigate('DetalleUsuario', { id: '1', nombre: 'Ana' })} />
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Redux Toolkit (proyectos con equipo grande)
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
// store/slices/carrito.slice.ts
|
|
38
|
+
import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit';
|
|
39
|
+
|
|
40
|
+
export const obtenerProductos = createAsyncThunk(
|
|
41
|
+
'carrito/obtenerProductos',
|
|
42
|
+
async (categoriaId: string) => {
|
|
43
|
+
const respuesta = await api.get(`/productos?categoria=${categoriaId}`);
|
|
44
|
+
return respuesta.data;
|
|
45
|
+
}
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
const carritoSlice = createSlice({
|
|
49
|
+
name: 'carrito',
|
|
50
|
+
initialState: { items: [], cargando: false } as CarritoState,
|
|
51
|
+
reducers: {
|
|
52
|
+
agregarItem: (state, action: PayloadAction<Producto>) => {
|
|
53
|
+
state.items.push(action.payload);
|
|
54
|
+
},
|
|
55
|
+
eliminarItem: (state, action: PayloadAction<string>) => {
|
|
56
|
+
state.items = state.items.filter(i => i.id !== action.payload);
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
extraReducers: (builder) => {
|
|
60
|
+
builder
|
|
61
|
+
.addCase(obtenerProductos.pending, state => { state.cargando = true; })
|
|
62
|
+
.addCase(obtenerProductos.fulfilled, (state, action) => {
|
|
63
|
+
state.cargando = false;
|
|
64
|
+
state.items = action.payload;
|
|
65
|
+
});
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Native Modules — Turbo Module y Expo Modules API
|
|
73
|
+
|
|
74
|
+
### Turbo Module (Nueva Arquitectura)
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
// NativeModules/BiometricModule.ts
|
|
78
|
+
import type { TurboModule } from 'react-native';
|
|
79
|
+
import { TurboModuleRegistry } from 'react-native';
|
|
80
|
+
|
|
81
|
+
export interface Spec extends TurboModule {
|
|
82
|
+
readonly autenticar: (motivo: string) => Promise<boolean>;
|
|
83
|
+
readonly estaDisponible: () => boolean;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export default TurboModuleRegistry.getEnforcing<Spec>('BiometricModule');
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Expo Modules API (forma más fácil)
|
|
90
|
+
|
|
91
|
+
```swift
|
|
92
|
+
// ios/ExpoFingerprint.swift
|
|
93
|
+
import ExpoModulesCore
|
|
94
|
+
import LocalAuthentication
|
|
95
|
+
|
|
96
|
+
public class ExpoFingerprintModule: Module {
|
|
97
|
+
public func definition() -> ModuleDefinition {
|
|
98
|
+
Name("ExpoFingerprint")
|
|
99
|
+
AsyncFunction("autenticar") { (motivo: String) -> Bool in
|
|
100
|
+
let context = LAContext()
|
|
101
|
+
var error: NSError?
|
|
102
|
+
guard context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) else {
|
|
103
|
+
throw Exception(name: "NO_BIOMETRICS", description: error?.localizedDescription ?? "")
|
|
104
|
+
}
|
|
105
|
+
return try await context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: motivo)
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Gesture Handler + Reanimated
|
|
114
|
+
|
|
115
|
+
```tsx
|
|
116
|
+
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
|
|
117
|
+
|
|
118
|
+
function TarjetaDeslizable() {
|
|
119
|
+
const translateX = useSharedValue(0);
|
|
120
|
+
|
|
121
|
+
const gesture = Gesture.Pan()
|
|
122
|
+
.onUpdate(event => {
|
|
123
|
+
translateX.value = event.translationX;
|
|
124
|
+
})
|
|
125
|
+
.onEnd(event => {
|
|
126
|
+
const umbral = 150;
|
|
127
|
+
if (Math.abs(event.translationX) > umbral) {
|
|
128
|
+
translateX.value = withTiming(event.translationX > 0 ? 400 : -400);
|
|
129
|
+
} else {
|
|
130
|
+
translateX.value = withSpring(0);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
const estiloAnimado = useAnimatedStyle(() => ({
|
|
135
|
+
transform: [{ translateX: translateX.value }],
|
|
136
|
+
}));
|
|
137
|
+
|
|
138
|
+
return (
|
|
139
|
+
<GestureDetector gesture={gesture}>
|
|
140
|
+
<Animated.View style={[styles.tarjeta, estiloAnimado]} />
|
|
141
|
+
</GestureDetector>
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Styling: NativeWind v4 (Tailwind en React Native)
|
|
149
|
+
|
|
150
|
+
```tsx
|
|
151
|
+
// Con NativeWind, usar className como en web
|
|
152
|
+
import { View, Text, Pressable } from 'react-native';
|
|
153
|
+
|
|
154
|
+
function TarjetaUsuario({ usuario }: Props) {
|
|
155
|
+
return (
|
|
156
|
+
<View className="bg-white rounded-xl p-4 mb-3 shadow-sm border border-slate-200">
|
|
157
|
+
<Text className="text-lg font-semibold text-slate-900 mb-1">
|
|
158
|
+
{usuario.nombre}
|
|
159
|
+
</Text>
|
|
160
|
+
<Text className="text-sm text-slate-500">
|
|
161
|
+
{usuario.email}
|
|
162
|
+
</Text>
|
|
163
|
+
<Pressable className="mt-3 bg-blue-600 rounded-lg py-2 active:bg-blue-700">
|
|
164
|
+
<Text className="text-white text-center font-medium">Ver perfil</Text>
|
|
165
|
+
</Pressable>
|
|
166
|
+
</View>
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Testing — Jest + RNTL y Detox
|
|
174
|
+
|
|
175
|
+
### Jest + React Native Testing Library
|
|
176
|
+
|
|
177
|
+
```tsx
|
|
178
|
+
// __tests__/TarjetaUsuario.test.tsx
|
|
179
|
+
import { render, screen, fireEvent } from '@testing-library/react-native';
|
|
180
|
+
import { TarjetaUsuario } from '../components/TarjetaUsuario';
|
|
181
|
+
|
|
182
|
+
const usuarioMock = { id: '1', nombre: 'Ana López', email: 'ana@ejemplo.com' };
|
|
183
|
+
|
|
184
|
+
describe('TarjetaUsuario', () => {
|
|
185
|
+
it('muestra el nombre y email del usuario', () => {
|
|
186
|
+
render(<TarjetaUsuario usuario={usuarioMock} onPress={jest.fn()} />);
|
|
187
|
+
expect(screen.getByText('Ana López')).toBeTruthy();
|
|
188
|
+
expect(screen.getByText('ana@ejemplo.com')).toBeTruthy();
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it('llama onPress al presionar', () => {
|
|
192
|
+
const onPress = jest.fn();
|
|
193
|
+
render(<TarjetaUsuario usuario={usuarioMock} onPress={onPress} />);
|
|
194
|
+
fireEvent.press(screen.getByText('Ver perfil'));
|
|
195
|
+
expect(onPress).toHaveBeenCalledWith(usuarioMock.id);
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Detox para E2E
|
|
201
|
+
|
|
202
|
+
```javascript
|
|
203
|
+
// e2e/login.test.js
|
|
204
|
+
describe('Flujo de Login', () => {
|
|
205
|
+
beforeAll(async () => {
|
|
206
|
+
await device.launchApp({ newInstance: true });
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it('permite iniciar sesión con credenciales válidas', async () => {
|
|
210
|
+
await element(by.id('input-email')).typeText('usuario@ejemplo.com');
|
|
211
|
+
await element(by.id('input-password')).typeText('password123');
|
|
212
|
+
await element(by.id('btn-login')).tap();
|
|
213
|
+
await expect(element(by.id('pantalla-home'))).toBeVisible();
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
```
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mongodb-experto
|
|
3
|
+
description: >
|
|
4
|
+
MongoDB: schema design patterns, aggregation pipeline, indexes, transactions
|
|
5
|
+
y Mongoose ODM. Cargar cuando se diseñen schemas MongoDB, se optimicen queries,
|
|
6
|
+
se usen aggregations complejas o se implementen change streams.
|
|
7
|
+
version: "1.0.0"
|
|
8
|
+
herramientasPermitidas: [Read, Grep]
|
|
9
|
+
evolvable: true # default para skill estandar
|
|
10
|
+
exclusiones:
|
|
11
|
+
- "No cargar para diseño de esquemas en bases de datos relacionales (PostgreSQL, MySQL) — para bases de datos SQL cargar `postgresql-experto`."
|
|
12
|
+
- "No cargar para caching con Redis aunque el proyecto también use MongoDB — para Redis cargar `redis-experto`."
|
|
13
|
+
- "No cargar para búsqueda full-text avanzada (relevance scoring, facets, sinónimos) aunque MongoDB Atlas Search lo soporte — para búsqueda avanzada cargar el skill de Elasticsearch o Typesense."
|
|
14
|
+
- "No cargar para pipelines ETL de ingestión masiva hacia MongoDB desde fuentes externas — para ETL cargar `datos-etl`."
|
|
15
|
+
---
|
|
16
|
+
# MongoDB Experto — Schema Design y Aggregation
|
|
17
|
+
|
|
18
|
+
MongoDB no tiene schema, pero el diseño del schema importa más que en SQL porque
|
|
19
|
+
las consultas determinan cómo organizar los datos. Este skill cubre los patrones
|
|
20
|
+
de diseño (embedded vs referenced), el aggregation pipeline, tipos de indexes y
|
|
21
|
+
transacciones con sesiones.
|
|
22
|
+
|
|
23
|
+
## Cuándo NO cargar
|
|
24
|
+
|
|
25
|
+
- La base de datos es relacional (PostgreSQL, MySQL, SQLite): cargar `postgresql-experto`.
|
|
26
|
+
- La tarea es caching con Redis aunque el proyecto también use MongoDB: cargar `redis-experto`.
|
|
27
|
+
- La búsqueda requiere relevance scoring, facets o sinónimos avanzados: cargar el skill de Elasticsearch o Typesense.
|
|
28
|
+
- La tarea es ingestión masiva desde fuentes externas como ETL: cargar `datos-etl`.
|
|
29
|
+
|
|
30
|
+
## Cuándo cargar este skill
|
|
31
|
+
|
|
32
|
+
Invoca `Skill("mongodb-experto")` cuando:
|
|
33
|
+
|
|
34
|
+
- Se diseñe la estructura de documentos de una colección nueva
|
|
35
|
+
- Se escriban aggregation pipelines con `$lookup`, `$group` o `$unwind`
|
|
36
|
+
- Se creen índices para optimizar queries
|
|
37
|
+
- Se implementen transacciones multi-documento
|
|
38
|
+
- Se usen change streams para reactividad
|
|
39
|
+
- Se configuren modelos con Mongoose ODM
|
|
40
|
+
|
|
41
|
+
## Conceptos clave
|
|
42
|
+
|
|
43
|
+
### Embedded vs Referenced
|
|
44
|
+
|
|
45
|
+
Embeber documentos (subdocumentos) es idiomático en MongoDB. La regla de oro:
|
|
46
|
+
si siempre lees A junto con B, embedear B en A. Si B se consulta independientemente
|
|
47
|
+
o crece sin límite, referenciar con un ID. Un array de subdocumentos que crece
|
|
48
|
+
sin límite (outlier pattern) destruye el rendimiento.
|
|
49
|
+
|
|
50
|
+
### Aggregation Pipeline
|
|
51
|
+
|
|
52
|
+
El pipeline procesa documentos en etapas. Cada etapa recibe documentos de la
|
|
53
|
+
anterior y entrega documentos a la siguiente. El orden importa: `$match` y
|
|
54
|
+
`$limit` primero para reducir el volumen antes de operaciones costosas.
|
|
55
|
+
|
|
56
|
+
### Indexes en MongoDB
|
|
57
|
+
|
|
58
|
+
Los índices funcionan igual que en SQL: aceleran lecturas a costa de escrituras.
|
|
59
|
+
Los compound indexes siguen las reglas ESR (Equality, Sort, Range). Los partial
|
|
60
|
+
indexes indexan solo los documentos que cumplen una condición — ideales para
|
|
61
|
+
colecciones con campos opcionales o estados.
|
|
62
|
+
|
|
63
|
+
## Reglas obligatorias
|
|
64
|
+
|
|
65
|
+
### $match PRIMERO en el pipeline para usar indexes
|
|
66
|
+
|
|
67
|
+
```javascript
|
|
68
|
+
// MAL — $group antes de $match: procesa TODOS los documentos
|
|
69
|
+
db.pedidos.aggregate([
|
|
70
|
+
{ $group: { _id: '$usuarioId', total: { $sum: '$monto' } } },
|
|
71
|
+
{ $match: { total: { $gt: 1000 } } }, // demasiado tarde
|
|
72
|
+
]);
|
|
73
|
+
|
|
74
|
+
// BIEN — $match primero, reduce el dataset antes de operaciones costosas
|
|
75
|
+
db.pedidos.aggregate([
|
|
76
|
+
{ $match: { estatus: 'pagado', creadoEn: { $gte: new Date('2026-01-01') } } },
|
|
77
|
+
{ $group: { _id: '$usuarioId', total: { $sum: '$monto' } } },
|
|
78
|
+
{ $match: { total: { $gt: 1000 } } },
|
|
79
|
+
{ $sort: { total: -1 } },
|
|
80
|
+
{ $limit: 10 },
|
|
81
|
+
]);
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### NUNCA arrays sin límite en documentos de alta escritura
|
|
85
|
+
|
|
86
|
+
```javascript
|
|
87
|
+
// MAL — array que crece sin limite (outlier pattern)
|
|
88
|
+
// Un documento puede exceder 16MB y las queries por el array seran lentas
|
|
89
|
+
{
|
|
90
|
+
_id: ObjectId("..."),
|
|
91
|
+
nombre: "Juan",
|
|
92
|
+
actividades: [ /* puede ser miles de entradas */ ]
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// BIEN — coleccion separada con referencia
|
|
96
|
+
// actividades/{usuarioId, tipo, fecha, detalle}
|
|
97
|
+
// Consultar con: db.actividades.find({ usuarioId: ObjectId("...") })
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Indexes compound con orden ESR (Equality, Sort, Range)
|
|
101
|
+
|
|
102
|
+
```javascript
|
|
103
|
+
// Para la query: { estatus: "activo", precio: { $gte: 100, $lte: 500 } }
|
|
104
|
+
// ordenada por: { creadoEn: -1 }
|
|
105
|
+
|
|
106
|
+
// MAL — orden incorrecto, no usa el index eficientemente
|
|
107
|
+
db.productos.createIndex({ precio: 1, estatus: 1, creadoEn: -1 });
|
|
108
|
+
|
|
109
|
+
// BIEN — ESR: primero igualdad (estatus), luego sort (creadoEn), luego rango (precio)
|
|
110
|
+
db.productos.createIndex({ estatus: 1, creadoEn: -1, precio: 1 });
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Transacciones solo cuando son necesarias — tiene costo de rendimiento
|
|
114
|
+
|
|
115
|
+
Las transacciones en MongoDB tienen overhead significativo. Para operaciones
|
|
116
|
+
que se pueden modelar con un solo documento (actualización atómica), usar
|
|
117
|
+
operadores atómicos: `$set`, `$push`, `$inc`, `findOneAndUpdate`.
|
|
118
|
+
|
|
119
|
+
## Patrones recomendados
|
|
120
|
+
|
|
121
|
+
### Schema Design: Bucket Pattern para series de tiempo
|
|
122
|
+
|
|
123
|
+
```javascript
|
|
124
|
+
// MAL — un documento por medicion (millones de documentos)
|
|
125
|
+
{ sensorId: "s1", temperatura: 22.5, timestamp: ISODate("2026-01-01T00:00:00Z") }
|
|
126
|
+
{ sensorId: "s1", temperatura: 22.6, timestamp: ISODate("2026-01-01T00:01:00Z") }
|
|
127
|
+
|
|
128
|
+
// BIEN — bucket de 1 hora (60 mediciones por documento)
|
|
129
|
+
{
|
|
130
|
+
sensorId: "s1",
|
|
131
|
+
inicio: ISODate("2026-01-01T00:00:00Z"),
|
|
132
|
+
fin: ISODate("2026-01-01T00:59:59Z"),
|
|
133
|
+
count: 60,
|
|
134
|
+
sum: 1353.0,
|
|
135
|
+
min: 22.1,
|
|
136
|
+
max: 23.2,
|
|
137
|
+
mediciones: [22.5, 22.6, 22.7, ...] // array acotado
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Aggregation Pipeline con $lookup optimizado
|
|
142
|
+
|
|
143
|
+
```javascript
|
|
144
|
+
// $lookup con pipeline para filtrar ANTES del join (mas eficiente)
|
|
145
|
+
db.pedidos.aggregate([
|
|
146
|
+
{ $match: { estatus: 'pendiente' } },
|
|
147
|
+
{
|
|
148
|
+
$lookup: {
|
|
149
|
+
from: 'usuarios',
|
|
150
|
+
let: { usuarioId: '$usuarioId' },
|
|
151
|
+
pipeline: [
|
|
152
|
+
{ $match: { $expr: { $eq: ['$_id', '$$usuarioId'] } } },
|
|
153
|
+
{ $project: { nombre: 1, email: 1 } }, // solo campos necesarios
|
|
154
|
+
],
|
|
155
|
+
as: 'usuario',
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
{ $unwind: '$usuario' },
|
|
159
|
+
{ $project: { monto: 1, 'usuario.nombre': 1, 'usuario.email': 1 } },
|
|
160
|
+
]);
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Mongoose — Model con virtuals y métodos
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
import { Schema, model, Document } from 'mongoose';
|
|
167
|
+
|
|
168
|
+
interface IProducto extends Document {
|
|
169
|
+
nombre: string;
|
|
170
|
+
precio: number;
|
|
171
|
+
stock: number;
|
|
172
|
+
estaDisponible(): boolean;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const productoSchema = new Schema<IProducto>({
|
|
176
|
+
nombre: { type: String, required: true, trim: true, maxlength: 200 },
|
|
177
|
+
precio: { type: Number, required: true, min: 0 },
|
|
178
|
+
stock: { type: Number, required: true, default: 0, min: 0 },
|
|
179
|
+
}, {
|
|
180
|
+
timestamps: true, // agrega createdAt y updatedAt automáticamente
|
|
181
|
+
versionKey: false,
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// Método de instancia
|
|
185
|
+
productoSchema.methods.estaDisponible = function(): boolean {
|
|
186
|
+
return this.stock > 0;
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
// Virtual (no se persiste en BD)
|
|
190
|
+
productoSchema.virtual('precioConIVA').get(function() {
|
|
191
|
+
return this.precio * 1.16;
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
// Índice compuesto con partial filter
|
|
195
|
+
productoSchema.index(
|
|
196
|
+
{ nombre: 1, categoria: 1 },
|
|
197
|
+
{ unique: true, partialFilterExpression: { activo: true } }
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
export const Producto = model<IProducto>('Producto', productoSchema);
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Transacciones multi-documento
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
const sesion = await mongoose.startSession();
|
|
207
|
+
try {
|
|
208
|
+
sesion.startTransaction();
|
|
209
|
+
|
|
210
|
+
const pedido = await Pedido.create([{
|
|
211
|
+
usuarioId, items, total,
|
|
212
|
+
}], { session: sesion });
|
|
213
|
+
|
|
214
|
+
await Promise.all(items.map(item =>
|
|
215
|
+
Producto.findByIdAndUpdate(
|
|
216
|
+
item.productoId,
|
|
217
|
+
{ $inc: { stock: -item.cantidad } },
|
|
218
|
+
{ session: sesion, new: true }
|
|
219
|
+
)
|
|
220
|
+
));
|
|
221
|
+
|
|
222
|
+
await sesion.commitTransaction();
|
|
223
|
+
return pedido[0];
|
|
224
|
+
} catch (error) {
|
|
225
|
+
await sesion.abortTransaction();
|
|
226
|
+
throw error;
|
|
227
|
+
} finally {
|
|
228
|
+
sesion.endSession();
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Change Streams para reactividad
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
// Escuchar cambios en pedidos nuevos
|
|
236
|
+
const changeStream = Pedido.watch([
|
|
237
|
+
{ $match: { operationType: 'insert' } },
|
|
238
|
+
]);
|
|
239
|
+
|
|
240
|
+
changeStream.on('change', (cambio) => {
|
|
241
|
+
const nuevoPedido = cambio.fullDocument;
|
|
242
|
+
// notificar, actualizar cache, etc.
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
// Limpiar al terminar el proceso
|
|
246
|
+
process.on('SIGINT', async () => {
|
|
247
|
+
await changeStream.close();
|
|
248
|
+
});
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## Anti-patrones conocidos
|
|
252
|
+
|
|
253
|
+
### $lookup en colecciones grandes sin index en el campo join
|
|
254
|
+
|
|
255
|
+
```javascript
|
|
256
|
+
// Antes de usar $lookup, verificar que existe un index en el campo referenciado
|
|
257
|
+
// db.usuarios.createIndex({ _id: 1 }) — ya existe por defecto
|
|
258
|
+
// Pero para campos custom: db.pedidos.createIndex({ clienteId: 1 })
|
|
259
|
+
db.explain("executionStats").aggregate([...]);
|
|
260
|
+
// Buscar IXSCAN, no COLLSCAN en la etapa de lookup
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### findOne().then() en un loop — usar $in o $lookup
|
|
264
|
+
|
|
265
|
+
```typescript
|
|
266
|
+
// MAL — N+1 en MongoDB
|
|
267
|
+
for (const pedido of pedidos) {
|
|
268
|
+
pedido.usuario = await Usuario.findById(pedido.usuarioId); // query por cada pedido
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// BIEN — una query con $in
|
|
272
|
+
const ids = pedidos.map(p => p.usuarioId);
|
|
273
|
+
const usuarios = await Usuario.find({ _id: { $in: ids } });
|
|
274
|
+
const mapaUsuarios = new Map(usuarios.map(u => [u._id.toString(), u]));
|
|
275
|
+
pedidos.forEach(p => { p.usuario = mapaUsuarios.get(p.usuarioId.toString()); });
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## Checklist de verificación
|
|
279
|
+
|
|
280
|
+
- [ ] Arrays en documentos tienen límite definido (no crecen sin cota)
|
|
281
|
+
- [ ] `$match` es la primera etapa del pipeline cuando filtra por campo indexado
|
|
282
|
+
- [ ] Compound indexes siguen orden ESR para queries con igualdad + sort + rango
|
|
283
|
+
- [ ] `$lookup` filtra con pipeline interno antes de hacer el join
|
|
284
|
+
- [ ] Transacciones solo para operaciones verdaderamente multi-documento
|
|
285
|
+
- [ ] Mongoose models con `timestamps: true` y validaciones en el schema
|
|
286
|
+
- [ ] Indexes documentados con la query que los justifica
|
|
287
|
+
|
|
288
|
+
## Referencias
|
|
289
|
+
|
|
290
|
+
- [MongoDB Schema Design Patterns](https://www.mongodb.com/developer/products/mongodb/schema-design-anti-pattern-summary/)
|
|
291
|
+
- [Aggregation Pipeline](https://www.mongodb.com/docs/manual/core/aggregation-pipeline/)
|
|
292
|
+
- [Mongoose Docs](https://mongoosejs.com/docs/)
|
|
293
|
+
|
|
294
|
+
## Gotchas / Errores comunes no obvios
|
|
295
|
+
|
|
296
|
+
**Un `$lookup` entre colecciones en diferentes databases no es posible con MongoDB nativo y falla silenciosamente devolviendo arrays vacíos**: si `pedidos` está en `db_ventas` y `usuarios` en `db_usuarios`, el `$lookup` produce `usuario: []` en todos los documentos sin error. Causa: `$lookup` solo funciona dentro de la misma base de datos. Fix: para colecciones en diferentes bases de datos, materializar la relación duplicando el subconjunto de datos necesario en la misma BD (patrón de denormalización explícita), o realizar dos queries separadas en la aplicación y hacer el join en memoria.
|
|
297
|
+
|
|
298
|
+
**`findOneAndUpdate` con `{ upsert: true }` crea un documento duplicado cuando dos requests concurrentes llegan al mismo tiempo y no hay índice único en el campo de búsqueda**: sin un índice único, MongoDB puede insertar dos documentos porque ambas requests evalúan "no existe" antes de que cualquiera complete el insert. Causa: `upsert: true` no garantiza atomicidad cross-process sin un índice único de respaldo. Fix: crear un índice único en el campo usado en el filtro de `findOneAndUpdate` antes de usar `upsert: true`. El índice garantiza que el segundo insert falle con `E11000 duplicate key error` en lugar de crear un duplicado.
|
|
299
|
+
|
|
300
|
+
**Change streams en versiones de MongoDB < 6.0 se desconectan silenciosamente después de 30 minutos si el `resumeToken` no se persiste y la aplicación no reconecta automáticamente**: el `changeStream.on('change', ...)` deja de recibir eventos sin emitir un error visible. La aplicación sigue corriendo pero ya no procesa cambios. Causa: los change streams tienen un timeout de cursor configurable y requieren reconexión explícita con el `resumeToken`. Fix: implementar `changeStream.on('error', ...)` y reconexión automática: guardar el último `resumeToken` procesado en una colección de estado y recrear el change stream con `{ resumeAfter: ultimoToken }` cuando detecte la desconexión.
|
|
301
|
+
|
|
302
|
+
**El `$group` con `$sum` sobre un campo que puede ser `null` en algunos documentos produce resultados incorrectos porque MongoDB trata `null` como `0` en operaciones aritméticas**: si `monto` es `null` en el 30% de los documentos y el resto son valores positivos, `$sum: '$monto'` subestima el total ignorando silenciosamente los nulos en lugar de reportarlos. Causa: MongoDB sigue las reglas de BSON donde `null` en operaciones numéricas equivale a ausencia (no propaga `null` como lo haría SQL con `SUM`). Fix: antes del `$group`, agregar una etapa `$addFields: { monto: { $ifNull: ['$monto', 0] } }` para hacer explícito el tratamiento de nulos, o usar `$cond` para distinguir documentos sin monto de documentos con monto cero.
|