Registro y elevación de componentes base (ADN, Scripts, Servicios)

This commit is contained in:
Ricardo Monla
2026-02-15 20:37:53 -03:00
parent 9e9bf62c68
commit c865a7772b
25279 changed files with 3354766 additions and 0 deletions
+23
View File
@@ -0,0 +1,23 @@
# Datos de servicios
servicios/portainer/data/
servicios/nginx/logs/
servicios/nginx/certs/
servicios/sysacad/data/
servicios/sysacad/logs/
# Archivos de entorno y secretos
.env
*.env
**/*.env
secrets/
**/*.key
**/*.pem
# Logs
*.log
logs/
# Temporales y caché
tmp/
.temp/
.cache/
+33
View File
@@ -0,0 +1,33 @@
# 00 - Bitácora del Proyecto: Optimización srv-NS8
Este documento registra la evolución, cambios y eventos significativos en el servidor `srv-NS8`.
## 2026-02-11
| Hora | Acción | Detalle | Estado |
| :--- | :--- | :--- | :--- |
| 23:25 | Configuración SSL y Reverse Proxy | **Exitoso**. Certificado Let's Encrypt instalado para `ns8.frlr.utn.edu.ar`. Nginx configurado como Reverse Proxy para servir `/portainer/`, `/sysacad/`, `/bitacoras/` bajo HTTPS (Puerto 443), eliminando la necesidad de exponer puertos inseguros. | Completado |
| 23:15 | Configuración Red Híbrida | **Exitoso**. Se ejecuta `configurar_red_hibrida.sh`. El servidor mantiene gateway `10.x` para salida, pero responde correctamente a la IP pública `190.x` mediante Policy Routing. Mecanismo de rollback verificado. | Completado |
| 23:10 | Protocolo de Seguridad | Se incorpora la **Directiva 5: Protocolo de Seguridad de Red (Hombre Muerto)** en `adn/02_protocolo.md`, haciendo obligatorio el uso de mecanismos de reversión automática para cambios de red. | Completado |
| 23:00 | Instalación Nginx Nativo | **Completado**. El usuario ejecutó `instalar_nginx_simple.sh`. Nginx está activo en el Host (Puerto 80) funcionando como Proxy Reverso para Portainer, Bitácoras y SysACAD. | Completado |
| 22:55 | Resolución Conflicto Puerto | Se reconfigura SysACAD para usar puertos 8080/8443, liberando el puerto 80 del host. | Solucionado |
| 22:50 | Saneamiento y Simplificación | Se eliminan scripts de migración de IP complejos por riesgo innecesario. Se consolida `scripts/instalar_nginx_simple.sh` para instalación nativa sin alterar la red. | Completado |
| 22:45 | Cambio de Estrategia: Nginx Nativo | Se decide eliminar el contenedor `proxy` (Docker) y reemplazarlo por **Nginx Nativo** en el host (`10.0.10.8`), manteniendo la configuración de red actual del servidor. | En Proceso |
| 22:15 | Documentación de Red | Se detalla la **Topología de Red** en `adn/01_ontologia.md`. Se aclara el uso de `macvlan` para la IP pública `190.114.205.18` y la IP privada `10.0.10.8` para el host. | Completado |
| 22:10 | Mantenimiento | Se actualiza **Portainer** a la última versión disponible (detectada 2.33.7). Se descargan imágenes y se recrea el contenedor. | Completado |
| 22:05 | Documentación de Accesos | Se incorpora la tabla de **Puntos de Acceso (URLs)** en `adn/01_ontologia.md` para facilitar la navegación a los servicios. | Completado |
| 22:00 | Reactivación de Servicios | Se levantan exitosamente `portainer`, `proxy` (tras corregir conflicto de red), `bitacoras` y `sysacad`. Todos los contenedores operativos y limitados en recursos. | Completado |
| 21:50 | Validación de Servicios | Se ejecutan pruebas de configuración (`docker compose config`) exitosas para todos los servicios migrados. Límites de memoria confirmados correctos. | Verificado |
| 21:40 | Optimización de Recursos | Se completa la migración de archivos (incluidos `.env` y ocultos). Se aplican límites de memoria RAM a los servicios Docker para proteger la VM. | Completado |
| 21:35 | Centralización de Servicios | Se mueven las configuraciones de `portainer`, `bitacoras`, `sysacad` y `proxy` a `dtic-srv-NS8/servicios/`. Se ajusta contexto de build del proxy. Se crean referencias `LEEME_MIGRACION.md` en origen. | Completado |
| 21:22 | Definición de Prioridades | Se establece la VM `PCV_DTIC-RRHH_W732` como servicio **Crítico/Permanente**. Se define el objetivo de **Optimizar** los servicios Docker (no solo reactivar). | Definido |
| 21:15 | Relevamiento Técnico | Se detectan redes Docker sin contenedores activos (`bitacoras`, `sysacad`, `portainer`). VM VirtualBox consume ~4GB RAM. | Alerta |
| 21:07 | Protocolo de Armonía | Se incorpora la directiva de **Armonía y Auto-optimización** en `adn/02_protocolo.md`. | Completado |
| 21:05 | Establecimiento de Protocolo | Se define el **español** como idioma obligatorio. Se crea `adn/02_protocolo.md`. | Completado |
| 21:01 | Inicio del Relevamiento | Inicialización del repositorio y estructura de directorios `adn`, `docs`, `scripts`. | En proceso |
+65
View File
@@ -0,0 +1,65 @@
# 01 - Ontología del Sistema: srv-NS8
Este documento define la identidad, propósito y componentes principales del servidor `srv-NS8`.
## Identidad
- **Nombre**: `srv-NS8`
- **Hostname**: `srv-NS8`
- **Rol Principal**: Workstation / Híbrido (Docker Host + VirtualBox Hypervisor).
- **Sistema Operativo**: Debian GNU/Linux 12 (bookworm).
- **Kernel**: 6.1.0-28-amd64.
- **Ubicación de Red**: `10.0.10.8/24`.
## Hardware
- **CPU**: AMD Ryzen (16 hilos).
- **RAM**: 15 GiB Total.
- **Almacenamiento**: 438 GB (Root partition).
## Servicios Críticos (ADN Detectado)
### 1. Virtualización (Prioridad Alta)
- **Motor**: VirtualBox.
- **Carga**: VM `PCV_DTIC-RRHH_W732`.
- **Directiva**: **CRÍTICO / PERMANENTE**. Debe priorizarse el uso de RAM para esta VM.
- **Estado**: Ejecutándose (`Ssl`).
### 2. Contenedores Docker (En Optimización)
- **Motor**: Docker + Docker Compose.
- **Objetivo**: Optimizar despliegue y consumo de recursos.
- **Estado de Armonía**: ✅ **Consistente**.
- **Configuración Centralizada**: `dtic-srv-NS8/servicios/`.
- **Servicios Activos**:
- `portainer` (Gestión)
- **`nginx` (Nativo - Proxy Reverso)**
- `bitacoras` (App + DB)
- `sysacad` (App + Nginx interno)
- **Protección de Recursos**: Límites de RAM aplicados.
### 3. Puntos de Acceso (URLs)
| Servicio | URL Pública (SSL) | URL Interna (IP) | Descripción |
| :--- | :--- | :--- | :--- |
| **Portal Principal** | `https://ns8.frlr.utn.edu.ar` | `http://127.0.0.1:80` | Página de bienvenida Nginx |
| **Portainer** | `https://ns8.frlr.utn.edu.ar/portainer/` | `http://127.0.0.1:9000` | Gestión de Contenedores |
| **SysACAD** | `https://ns8.frlr.utn.edu.ar/sysacad/` | `http://127.0.0.1:8080` | Sistema Académico |
| **Bitácoras** | `https://ns8.frlr.utn.edu.ar/bitacoras/` | `http://127.0.0.1:5173` | Sistema de Bitácoras |
### 4. Topología de Red (Híbrida / Policy Routing)
El servidor opera con una arquitectura de red avanzada que combina velocidad en LAN y visibilidad en WAN mediante **Policy Based Routing**.
- **Interfaz Física**: `enp38s0`
- **Direcciones IP**:
1. **Privada (Principal/Salida)**: `10.0.10.8/24` (Gateway: `10.0.10.1`). Priorizada para navegación rápida del servidor.
2. **Pública (Entrada)**: `190.114.205.18/24` (Gateway: `190.114.205.1`). Habilitada para acceso externo seguro.
- **Mecanismo de Enrutamiento**:
- Se utiliza una tabla de rutas secundaria (`190`) y una regla de política (`ip rule`) para asegurar que todo tráfico que entra por la IP pública responda por el Gateway público, evitando asimetría.
- **Seguridad de Red**:
- **Protocolo "Hombre Muerto"**: Implementado en scripts de configuración para revertir cambios automáticamente en caso de pérdida de conexión.
- **SSL/TLS**: Terminación SSL en Nginx Nativo (Puerto 443) para todo el tráfico entrante.
## Propósito
Servidor híbrido que garantiza la operatividad continua de la VM administrativa de RRHH, mientras aloja servicios de desarrollo DTIC gestionados por Nginx Nativo y Docker.
## Estado Actual
- **Estado General**: Operativo. VM y Servicios Docker ejecutándose simultáneamente.
- **Uso de Recursos**: ~7.5GB RAM Estimada (4GB VM + ~3.5GB Docker Max). Equilibrado.
+44
View File
@@ -0,0 +1,44 @@
# 02 - Protocolo del Proyecto: Normas y Directivas
Este documento establece las reglas fundamentales para la interacción, documentación y desarrollo en el proyecto `srv-NS8`.
## 1. Idioma
- **Directiva**: **Todo el contenido debe estar en español.**
- **Alcance**:
- Interacciones con el asistente (chat).
- Documentación (archivos `.md`).
- Mensajes de Commit (Git).
- Comentarios en el código (scripts, configs).
- Nombres de archivos y directorios (preferentemente, salvo estándares técnicos estrictos).
## 2. Formato de Documentación
- **Estilo**: Markdown estándar.
- **Ubicación**: Todo documento clave debe residir en el directorio `adn/`.
## 3. Armonía y Auto-optimización
- **Principio**: La documentación (ADN) debe mantenerse como un todo coherente y libre de contradicciones.
- **Directiva**:
- **Consistencia**: No deben existir discrepancias entre diferentes hebras (archivos `.md`). Si se actualiza una definición en `01_ontologia.md`, debe reflejarse en los protocolos y bitácoras correspondientes.
- **Auto-corrección**: Al detectar una inconsistencia, es prioritario resolverla para restaurar la armonía del sistema documental.
## 4. Formato de Registro (Bitácoras)
- **Estructura**: Tablas separadas por fecha (H2 con fecha `YYYY-MM-DD`).
- **Orden**: Descendente (lo más reciente arriba).
- **Columnas Obligatorias**:
- `Hora` (HH:MM)
- `Acción`
- `Detalle/Impacto`
- `Estado`
## 5. Protocolo de Seguridad de Red (Hombre Muerto)
- **Problemática**: La administración remota del servidor implica el riesgo de desconexión total ante cambios erróneos en la configuración de red.
- **Directiva**: **Toda modificación de red debe incluir un mecanismo de reversión automática.**
- **Implementación**:
- Usar scripts con temporizador ("Dead Man's Switch").
- **Flujo**:
1. Aplicar cambios temporalmente.
2. Esperar confirmación explícita del usuario (ej: presionar una tecla) durante un tiempo prudencial (5 minutos).
3. **Si no hay confirmación**: Revertir cambios inmediatamente y restaurar estado anterior.
4. **Si hay confirmación**: Hacer cambios persistentes.
+81
View File
@@ -0,0 +1,81 @@
#!/bin/bash
# scripts/configurar_red_hibrida.sh
# CONFIGURACIÓN DE RED HÍBRIDA (Policy Routing)
# Objetivo:
# - Mantener Gateway Default 10.0.10.1 (Navegación Rápida).
# - Habilitar IP Pública 190.114.205.18 para acceso entrante.
# - Responder tráfico entrante de 190... por su propio Gateway (190.114.205.1).
CON_NAME="Red LAN 10"
IP_PUB="190.114.205.18/24"
GW_PUB="190.114.205.1"
TABLE_ID="190"
TIMEOUT_SEC=300 # 5 Minutos
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
if [ "$EUID" -ne 0 ]; then
echo -e "${RED}Ejecutar con sudo.${NC}"
exit 1
fi
echo -e "${YELLOW}Configurando Red Híbrida en conexión '$CON_NAME'...${NC}"
# 1. Agregar IP Pública (si no existe ya)
# Nota: nmcli es idempotente para esto si se usa correctamente, pero limpiaremos "ipv4.addresses" duplicadas si es manual.
# Aquí simplemente agregamos.
echo -e "[1/4] Agregando IP Pública $IP_PUB..."
nmcli con mod "$CON_NAME" +ipv4.addresses "$IP_PUB"
# 2. Agregar Ruta a Tabla Secundaria
# Sintaxis: ip/prefix next-hop priority attributes
echo -e "[2/4] Configurando ruta de retorno (Tabla $TABLE_ID)..."
nmcli con mod "$CON_NAME" +ipv4.routes "0.0.0.0/0 $GW_PUB 100 table=$TABLE_ID"
# 3. Agregar Regla de Enrutamiento
# Sintaxis: priority from <ip> table <id>
echo -e "[3/4] Configurando regla de política (Policy Rule)..."
nmcli con mod "$CON_NAME" +ipv4.routing-rules "priority 30000 from ${IP_PUB%/*} table $TABLE_ID"
# 4. Aplicar Cambios (Temporales para validación)
echo -e "Aplicando configuración... (Si pierdes conexión, espera $TIMEOUT_SEC segundos)"
nmcli con mod "$CON_NAME" +ipv4.addresses "$IP_PUB"
nmcli con mod "$CON_NAME" +ipv4.routes "0.0.0.0/0 $GW_PUB 100 table=$TABLE_ID"
nmcli con mod "$CON_NAME" +ipv4.routing-rules "priority 30000 from ${IP_PUB%/*} table $TABLE_ID"
nmcli con up "$CON_NAME"
# --- VERIFICACIÓN / ROLLBACK LOOP ---
echo -e "\n${GREEN}*** CAMBIOS APLICADOS ***${NC}"
echo "Verifica que tienes conectividad (tanto LAN como WAN)."
echo "Tienes $TIMEOUT_SEC segundos para confirmar escribiendo 's' y Enter."
CONFIRMADO=0
for ((i=TIMEOUT_SEC; i>0; i--)); do
echo -ne " Tiempo restante para ROLLBACK: $i segundos \r"
read -t 1 -n 1 key
if [[ $key = "s" ]] || [[ $key = "S" ]]; then
CONFIRMADO=1
break
fi
done
if [ $CONFIRMADO -eq 1 ]; then
echo -e "\n\n${GREEN}¡CONFIRMADO! Configuración de Red Híbrida establecida.${NC}"
exit 0
else
echo -e "\n\n${RED}¡TIEMPO AGOTADO! REVIERTIENDO CAMBIOS...${NC}"
# Revertir (Undo)
echo "Eliminando reglas..."
nmcli con mod "$CON_NAME" -ipv4.addresses "$IP_PUB"
nmcli con mod "$CON_NAME" -ipv4.routes "0.0.0.0/0 $GW_PUB 100 table=$TABLE_ID"
nmcli con mod "$CON_NAME" -ipv4.routing-rules "priority 30000 from ${IP_PUB%/*} table $TABLE_ID"
echo "Recargando conexión..."
nmcli con up "$CON_NAME"
echo -e "${GREEN}Sistema restaurado al estado original.${NC}"
fi
+31
View File
@@ -0,0 +1,31 @@
#!/bin/bash
# scripts/instalar_nginx_simple.sh
# Script para instalar Nginx y aplicar configuraciones (Sin manipulación de IP).
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
if [ "$EUID" -ne 0 ]; then
echo -e "${RED}Ejecutar con sudo.${NC}"
exit 1
fi
echo -e "${YELLOW}[1/3] Instalando Nginx...${NC}"
apt-get update && apt-get install -y nginx
echo -e "${YELLOW}[2/3] Aplicando configuraciones de servicios...${NC}"
# Remover default si molesta
# rm /etc/nginx/sites-enabled/default 2>/dev/null
# Enlazar configs
CONFIG_DIR="/home/rmonla/Documentos/GitHub/dtic-srv-NS8/servicios/nginx/conf.d"
ln -sf $CONFIG_DIR/*.conf /etc/nginx/conf.d/
echo -e "${YELLOW}[3/3] Iniciando servicio...${NC}"
systemctl enable nginx
systemctl restart nginx
echo -e "${GREEN}Instalación completada.${NC}"
echo "Nginx está corriendo en el Host."
+34
View File
@@ -0,0 +1,34 @@
#!/bin/bash
# scripts/instalar_ssl.sh
# Script para instalar Certbot y obtener certificado SSL para ns8.frlr.utn.edu.ar
DOMAIN="ns8.frlr.utn.edu.ar"
EMAIL="admin@ns8.frlr.utn.edu.ar" # Ajustar si es necesario, Certbot pedirá uno real interactivo o usará este
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
if [ "$EUID" -ne 0 ]; then
echo -e "${RED}Ejecutar con sudo.${NC}"
exit 1
fi
echo -e "${YELLOW}[1/4] Instalando Certbot y plugin Nginx...${NC}"
apt-get update
apt-get install -y certbot python3-certbot-nginx
echo -e "${YELLOW}[2/4] Activando configuración del dominio $DOMAIN...${NC}"
# Enlazar la nueva config si no existe
ln -sf /home/rmonla/Documentos/GitHub/dtic-srv-NS8/servicios/nginx/conf.d/ns8.conf /etc/nginx/conf.d/ns8.conf
echo -e "${YELLOW}[3/4] Verificando y Recargando Nginx...${NC}"
nginx -t && systemctl reload nginx
echo -e "${YELLOW}[4/4] Ejecutando Certbot...${NC}"
echo "Sigue las instrucciones en pantalla (ingresa tu email si se solicita)."
certbot --nginx -d $DOMAIN
echo -e "${GREEN}Proceso finalizado.${NC}"
echo "Prueba acceder a https://$DOMAIN"
+63
View File
@@ -0,0 +1,63 @@
# Archivo de ejemplo de variables de entorno para DTIC Bitácoras
# Copia este archivo como .env y ajusta los valores según tu entorno
# === CONFIGURACIÓN GENERAL ===
NODE_ENV=development
# Opciones: development, production, test
# === BASE DE DATOS POSTGRESQL ===
POSTGRES_DB=dtic_bitacoras
POSTGRES_USER=dtic_user
POSTGRES_PASSWORD=dtic_password
# ⚠️ IMPORTANTE: Cambia esta contraseña en producción!
POSTGRES_PORT=5432
# URL completa de conexión a la base de datos
DATABASE_URL=postgresql://dtic_user:dtic_password@postgres:5432/dtic_bitacoras
# === API BACKEND ===
JWT_SECRET=your-super-secret-jwt-key-change-in-production
# ⚠️ IMPORTANTE: Genera una clave secreta segura para producción!
# Puedes generar una con: openssl rand -base64 32
API_PORT=3001
# === FRONTEND ===
VITE_API_URL=http://localhost:3001/api
FRONTEND_PORT=5173
# === CONFIGURACIÓN DE RED ===
NETWORK_NAME=dtic_network
# === VOLÚMENES ===
POSTGRES_VOLUME_NAME=dtic_bitacoras_postgres_data
# === CONFIGURACIÓN PARA PRODUCCIÓN ===
# Para despliegue en producción, ajusta estas variables:
# NODE_ENV=production
# POSTGRES_PASSWORD=tu_password_seguro_aqui
# JWT_SECRET=tu_clave_jwt_segura_aqui
# VITE_API_URL=https://tu-dominio.com/api
# POSTGRES_PORT=5432
# API_PORT=3001
# FRONTEND_PORT=80
# === CONFIGURACIÓN SSL (OPCIONAL) ===
# Si usas HTTPS en producción:
# SSL_CERT_PATH=/path/to/ssl/cert.pem
# SSL_KEY_PATH=/path/to/ssl/private.key
# === LOGGING ===
LOG_LEVEL=info
# Opciones: error, warn, info, debug
# === RATE LIMITING ===
RATE_LIMIT_WINDOW_MS=900000
RATE_LIMIT_MAX_REQUESTS=1000
# === CONFIGURACIÓN DE EMAIL (OPCIONAL) ===
# Para funcionalidades de notificación:
# SMTP_HOST=smtp.gmail.com
# SMTP_PORT=587
# SMTP_USER=tu-email@gmail.com
# SMTP_PASS=tu-app-password
+377
View File
@@ -0,0 +1,377 @@
## [2.1.2] - 2025-11-29
| Tipo | Descripción |
|------|-------------|
| Agregado | **Documentación Integral Bilingüe del Sistema**: Creación de documentación completa en inglés y español para todos los módulos del sistema |
| Agregado | **Índice de Documentación Interactivo**: Nuevo archivo index.md con navegación completa de todos los módulos |
| Agregado | **Documentación de Arquitectura**: Documentación detallada de componentes, APIs, esquemas de base de datos y flujos de trabajo |
| Agregado | **Guías de Desarrollo**: Documentación de procesos de desarrollo, convenciones de código y mejores prácticas |
| Mejorado | **Organización de Documentación**: Estructura jerárquica con tabla de contenidos en cada archivo |
| Mejorado | **Accesibilidad de Información**: Documentación disponible en español para facilitar el acceso a desarrolladores locales |
| Detalles Técnicos | **Documentación de 11 Módulos**: Authentication, Dashboard, Technicians, Resources, Tasks, Users, Reports, Calendar, Project Status, System, Task-Resources |
| Detalles Técnicos | **Versionado Sincronizado**: Actualización de versiones en package.json frontend, backend y visualización en UI |
## [2.1.1] - 2025-11-28
| Tipo | Descripción |
|------|-------------|
| Eliminado | **Limpieza de Archivos Históricos**: Eliminación de archivos obsoletos y documentación histórica movida a directorio _basurero |
| Eliminado | **Archivos de Bitácoras Antiguas**: Remoción de archivos de bitácoras anteriores y estados del sistema |
| Eliminado | **Documentación Duplicada**: Eliminación de archivos de documentación redundantes y prompts obsoletos |
| Eliminado | **Archivos Temporales**: Limpieza de archivos temporales y de desarrollo no utilizados |
| Detalles Técnicos | **Optimización del Repositorio**: Reducción significativa del tamaño del repositorio eliminando archivos innecesarios |
| Detalles Técnicos | **Mantenimiento de Historial**: Preservación de archivos históricos en directorio _basurero para referencia futura |
## [2.1.0] - 2025-11-28
| Tipo | Descripción |
|------|-------------|
| Agregado | **Refactorización Modular del Sistema de Gestión**: Reestructuración completa de `app-run.sh` para mejorar mantenibilidad y escalabilidad |
| Agregado | **Biblioteca Compartida de Funciones**: Creación de `app-run_lib.sh` con funciones reutilizables (log, success, error, warning, etc.) |
| Agregado | **Módulo de Gestión de Dependencias**: Nuevo script `app-run_deps.sh` para manejo centralizado de dependencias del sistema |
| Agregado | **Interfaz API-like para Sub-scripts**: Sub-scripts con argumentos CLI estrictos y códigos de salida estructurados |
| Agregado | **Visualización de Versión en UI**: Badge de versión agregado en página Sistema para mostrar versión actual al usuario |
| Mejorado | **Principio DRY Aplicado**: Eliminación de código duplicado y centralización de funciones comunes |
| Mejorado | **Separación de Responsabilidades**: Funciones modulares con responsabilidades claras y bien definidas |
| Mejorado | **Mantenibilidad del Código**: Reducción significativa de complejidad y mejora en legibilidad del código |
| Eliminado | **Limpieza de Archivos Redundantes**: Eliminación de `install.sh` y `Makefile` duplicados |
| Detalles Técnicos | **Arquitectura Modular**: Scripts divididos en biblioteca compartida, gestión de dependencias y lógica principal |
| Detalles Técnicos | **API de Sub-scripts**: Interfaz consistente con argumentos CLI y códigos de retorno estandarizados |
| Detalles Técnicos | **Versionado Sincronizado**: Actualización de versiones en `package.json` backend y frontend a v2.1.0 |
| Detalles Técnicos | **UI de Versión**: Implementación de badge visual en interfaz de usuario para mostrar versión del sistema |
## [2.0.0] - 2025-11-17
| Tipo | Descripción |
|------|-------------|
| Agregado | Sistema completo de comandas dual con nomenclatura diferenciada (G/E) |
| Agregado | Comanda-G 01: Documentación y establecimiento del mecanismo de comandas |
| Agregado | Comanda-E 02: Corrección completa de estética visual (temas oscuro/claro) |
| Agregado | Comanda-E 03: Estandarización de cabeceras módulos gestión |
| Agregado | Comanda-E 04: Ajustes de color y contraste en sidebar |
| Agregado | Comanda-E 05: Verificación y resolución de problemas de cache |
| Mejorado | Variables CSS completas para temas oscuro y claro con overrides |
| Mejorado | Sistema de referencias cruzadas entre orquestadores |
| Corregido | Visibilidad perfecta de texto en tablas, sidebar y paneles de perfil |
| Documentado | Mecanismo completo de comandas con instrucciones detalladas |
## [1.9.4] - 2025-11-17
### Cambios
- Definir formato y estructura del archivo de comanda
- Crear script registrar-avance.sh para automatización
- Actualizar orquestadores principal y específico
- Crear template de comanda
- Agregar script a package.json
## [1.9.3] - 2025-11-17
### Cambios
- Definir formato y estructura del archivo de comanda
- Crear script registrar-avance.sh para automatización
- Actualizar orquestadores principal y específico
- Crear template de comanda
- Agregar script a package.json
# REGISTRO DE CAMBIOS - DTIC Bitácoras
Todos los cambios notables de este proyecto serán documentados en este archivo.
El formato está basado en [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
y este proyecto se adhiere al [Versionado Semántico](https://semver.org/spec/v2.0.0.html).
## [1.8.0] - 2025-11-15
| Tipo | Descripción |
|------|-------------|
| Agregado | Completación de documentación integral del sistema y versionado, incluyendo carga dinámica de versiones, actualizaciones del marco de prompts DTIC, y todas las correcciones aplicadas. |
## [1.7.0] - 2025-11-14
| Tipo | Descripción |
|------|-------------|
| Agregado | **Integración del Marco de Prompts DTIC**: Sistema automatizado de workflow y gestión de documentación para procesos de desarrollo optimizados |
| Agregado | **Capacidades Mejoradas de Documentación del Sistema**: Herramientas mejoradas de generación y mantenimiento de documentación |
| Agregado | **Operaciones Mejoradas de Backup/Restore**: Fiabilidad mejorada y experiencia de usuario para funcionalidades de backup y restore de base de datos |
| Agregado | **Alineación con el Sistema de Plantillas de Prompts Más Reciente**: Sistema actualizado para trabajar sin problemas con la versión actual del marco de prompts |
## [1.6.0] - 2025-11-14
| Tipo | Descripción |
|------|-------------|
| Agregado | **Funcionalidad de Interfaz de Usuario de Backup y Restore**: Implementación completa de interfaz de usuario de backup y restore para operaciones de base de datos |
| Agregado | **Interfaz de Usuario Frontend**: Nuevos controles de backup y restore integrados en la página Sistema con interfaz de usuario intuitiva |
| Agregado | **Endpoints de API Backend**: Nuevos endpoints `/api/system/backup` y `/api/system/restore` para operaciones seguras de base de datos |
| Agregado | **Controles de Acceso de Administrador**: Acceso restringido a operaciones de backup y restore solo para usuarios administradores con autenticación adecuada |
| Agregado | **Integración con Docker**: Integración perfecta con base de datos PostgreSQL en contenedor Docker para operaciones de backup y restore |
| Agregado | **Manejo de Errores**: Manejo completo de errores y retroalimentación al usuario para operaciones de backup y restore con logging detallado |
## [1.5.0] - 2025-11-14
| Tipo | Descripción |
|------|-------------|
| Agregado | Agregada funcionalidad para cargar recursos desde archivos PDF en la base de datos. Importados exitosamente 233 recursos desde RECURSOS.pdf. Actualizados los prompts con la nueva plantilla DTIC-PDF-IMPORT-001 para operaciones de importación de datos PDF. |
## [1.4.3] - 2025-11-14
| Tipo | Descripción |
|------|-------------|
| Corregido | **Corrección Crítica del Nombre de Tabla de Base de Datos**: Corregido el nombre de tabla de `usuarios_asignados` a `usuarios_relacionados` en todo el sistema |
| Corregido | **Restauración de Endpoints de API**: Restaurada funcionalidad para endpoints `/api/usuarios_relacionados` y `/api/recursos` |
| Corregido | **Configuración de Conexión de Base de Datos**: Agregada configuración adecuada de `search_path` para acceso al esquema PostgreSQL |
| Corregido | **Manejo de Errores de Consultas**: Mejorado el manejo de errores en operaciones de base de datos con bloques try/catch adecuados |
| Cambiado | **Esquema de Base de Datos**: Renombrada tabla `dtic.usuarios_asignados` a `dtic.usuarios_relacionados` |
| Cambiado | **Rutas Backend**: Actualizadas todas las referencias para usar el nombre correcto de tabla en rutas de API |
| Cambiado | **Configuración del Pool de Base de Datos**: Agregada configuración de ruta de esquema para acceso consistente a tablas |
| Detalles Técnicos | **Migración de Base de Datos**: Ejecutado `ALTER TABLE dtic.usuarios_asignados RENAME TO usuarios_relacionados` |
| Detalles Técnicos | **Actualizaciones de Código**: Actualizadas 15+ referencias en archivos de rutas backend |
| Detalles Técnicos | **Pool de Conexiones**: Agregado `SET search_path TO dtic, public` para todas las conexiones de base de datos |
| Detalles Técnicos | **Manejo de Errores**: Mejorado el manejo de errores de base de datos con logging y propagación de errores adecuados |
## [1.4.2] - 2025-11-12
| Tipo | Descripción |
|------|-------------|
| Documentación | **Actualización de Documentación del Sistema**: Actualización completa de la documentación del sistema en directorio _docs con arquitectura actual, componentes, APIs y esquema de base de datos |
| Documentación | **Consistencia de Versiones**: Actualizadas todas las referencias de versión en archivos package.json, componente Navbar y documentación |
| Documentación | **Documentación de Workflow**: Documentación mejorada del workflow DTIC-DOC-001 para tareas de documentación y versionado |
| Documentación | **Registros de Finalización de Tareas**: Nuevo registro de finalización de tareas creado en directorio _tareasTerminadas |
| Documentación | **Verificación del Estado del Sistema**: Archivo de verificación creado en directorio _estados documentando el estado del sistema post-documentación |
| Cambiado | **Incremento de Versión**: Incremento de versión patch de 1.4.1 a 1.4.2 para mejoras de documentación |
| Cambiado | **Optimización de Prompts**: Actualizado _prompts/prompts-dtic-bitacoras.md con nueva plantilla y registro de solicitudes |
| Cambiado | **Workflow de Documentación**: Ejecución completa del workflow de documentación de 4 fases (Tareas → Versionado → Verificación → Commit) |
| Detalles Técnicos | **Versiones de Paquetes**: Actualizadas versiones de package.json backend y frontend a 1.4.2 |
| Detalles Técnicos | **Visualización de Versión en UI**: Actualizado componente Navbar para mostrar el badge de versión correcto |
| Detalles Técnicos | **Archivos de Documentación**: Actualización completa de la documentación del sistema con estado y arquitectura actuales |
| Detalles Técnicos | **Registros de Tareas**: Nuevo archivo de finalización de tareas con timestamp siguiendo formato institucional |
| Detalles Técnicos | **Proceso de Verificación**: Verificación del sistema completada con documentación de estado |
## [1.4.1] - 2025-11-12
| Tipo | Descripción |
|------|-------------|
| Cambiado | **Actualización de Terminología**: Cambiada terminología de "asignados" a "relacionados" para entidades de usuario en todo el sistema |
| Cambiado | **Esquema de Base de Datos**: Renombrada tabla de `usuarios_asignados` a `usuarios_relacionados` |
| Cambiado | **Endpoints de API**: Actualizadas rutas de API de `/api/usuarios_asignados` a `/api/usuarios_relacionados` |
| Cambiado | **Texto de Interfaz de Usuario**: Actualizado texto de interfaz de usuario de "asignados" a "relacionados" en todos los componentes y páginas relacionados con usuarios |
| Documentación | **Documentación del Módulo Recursos**: Documentación completa de todos los cambios realizados en el módulo Recursos siguiendo el workflow DTIC-DOC-001 |
| Documentación | **Columnas Unificadas**: Documentación de columnas estandarizadas (Estado/Categoría, Modelo/Serie) y limpieza de interfaz |
| Documentación | **Columna de Tareas Relacionadas**: Documentación de nueva funcionalidad de relación many-to-many entre tareas y recursos |
| Documentación | **Modificaciones Backend**: Documentación de nuevas APIs, cambios en esquema de base de datos y lógica de validación |
| Documentación | **Estilo de Colores**: Documentación de esquemas de colores aplicados para mejor jerarquía visual |
| Detalles Técnicos | **Base de Datos**: Migrado nombre de tabla y actualizadas todas las referencias de claves foráneas e índices |
| Detalles Técnicos | **Backend**: Renombrado archivo de rutas de `usuarios_asignados.js` a `usuarios_relacionados.js` y actualizadas todas las referencias internas |
| Detalles Técnicos | **Frontend**: Actualizada configuración de entidades, hooks y componentes para usar nueva terminología y endpoints de API |
| Detalles Técnicos | **Workflow de Documentación**: Ejecución completa del workflow DTIC-DOC-001 con finalización de tareas, verificación y actualización de versión |
| Detalles Técnicos | **Creación de Bitácora**: Nuevo archivo de bitácora creado siguiendo formato institucional (bitacora_251112.md) |
| Detalles Técnicos | **Verificación del Sistema**: Verificación completa de todas las funcionalidades del módulo Recursos |
| Detalles Técnicos | **Actualización de Versión**: Versión del sistema incrementada a 1.4.1 (versión patch para mejoras de terminología y documentación) |
## [1.3.0] - 2025-11-07
| Tipo | Descripción |
|------|-------------|
| Agregado | **Sistema Completo de Plantillas DTIC Bitácoras**: Implementación de 11 plantillas especializadas para desarrollo automatizado |
| Agregado | **Adaptación de Prompts y Plantillas**: Refactorización completa del sistema de prompts con clasificación automática |
| Agregado | **Catálogo de Plantillas DTIC**: Nueva estructura modular con plantillas específicas por categoría |
| Agregado | **Algoritmo de Selección Automática**: Sistema de interpretación automática de prompts con puntuación |
| Agregado | **Plantillas Especializadas**: DTIC-DOC-001, DTIC-FE-001, DTIC-BE-001, DTIC-AUTH-001, DTIC-DB-001, DTIC-DEBUG-001, DTIC-OPT-001, DTIC-CONF-001, DTIC-CRUD-001, DTIC-DASH-001 |
| Agregado | **Workflow de Documentación Automatizado**: Proceso completo de 4 fases para documentación de desarrollo |
| Mejorado | **Consistencia de Versionado**: Corrección de inconsistencia entre Navbar (v1.2.0) y sistema (v1.3.0) |
| Mejorado | **Proceso de Commit Estructurado**: Implementación de workflow DTIC-DOC-001 con fases definidas |
| Mejorado | **Automatización de Documentación**: Scripts y procesos automatizados para generación de archivos |
| Mejorado | **Sistema de Verificación**: Proceso completo de verificación post-commit con estados de sistema |
| Detalles Técnicos | **Frontend**: Navbar actualizado con versión correcta v1.3.0 |
| Detalles Técnicos | **Documentación**: Nueva estructura de archivos en _tareasTerminadas y _estados |
| Detalles Técnicos | **Procesamiento Automatizado**: Sistema de clasificación y selección de plantillas por contexto |
| Detalles Técnicos | **Workflow Completo**: DTIC-DOC-001 con fases de tareas, versionado, commit y verificación |
## [1.3.0] - 2025-11-06
| Tipo | Descripción |
|------|-------------|
| Agregado | **Funcionalidad Completa de Backup de Base de Datos**: Implementación completa de backup automático de PostgreSQL con `./app-run.sh bd-backup` |
| Agregado | **Comando de Línea de Comandos**: Soporte para comando directo `bd-backup` en modo no interactivo |
| Agregado | **Verificación de Integridad de Backup**: Sistema de validación post-backup con verificación de tamaño y contenido |
| Agregado | **Soporte Dual de Backup**: Compatibilidad con `psql` local y Docker container para máxima flexibilidad |
| Agregado | **Timestamps Automáticos**: Nombres de archivo con formato `dtic_bitacoras_backup_YYYYMMDD_HHMMSS.sql` |
| Agregado | **Directorio Configurable**: Variable de entorno `APP_BACKUP_DIR` para personalizar ubicación de backups |
| Mejorado | **Integración con Menú Interactivo**: Opciones de backup disponibles tanto con aplicación ejecutándose como detenida |
| Mejorado | **Manejo de Errores**: Sistema robusto de cleanup automático y manejo de archivos parciales |
| Mejorado | **Configuración de Credenciales**: Detección automática de credenciales desde archivo `.env` |
| Mejorado | **Reportes Detallados**: Logging completo del proceso de backup con información de tamaño y línea count |
| Detalles Técnicos | **Script Enhancement**: app-run.sh actualizado a versión 2.1 con funcionalidad de backup |
| Detalles Técnicos | **Database Protection**: Validación de aplicación ejecutándose antes de permitir backup |
| Detalles Técnicos | **Cross-Platform Support**: Funciona en Linux y macOS con Docker o instalación local de psql |
| Detalles Técnicos | **Error Recovery**: Limpieza automática de archivos corruptos o incompletos |
## [1.2.0] - 2025-11-06
| Tipo | Descripción |
|------|-------------|
| Agregado | **Sistema de Verificación e Instalación Automática de Dependencias**: Implementación completa de verificación e instalación automática de dependencias del host (curl, jq) |
| Agregado | **Detección Automática de Gestores de Paquetes**: Sistema inteligente para detectar apt-get, yum, dnf (Linux) y brew (macOS) |
| Agregado | **Sistema de Primera Ejecución**: Recordatorio automático de primera ejecución con configuración guiada |
| Agregado | **Modo Dual de Operación**: Soporte para modo interactivo y no interactivo con parámetros (start, stop, restart, status) |
| Cambiado | **Refactorización con Arrays y Funciones Reutilizables**: Migración completa de variables individuales a arrays asociativos para mejor mantenibilidad |
| Cambiado | **Mejora de Eficiencia del Código**: Reducción de ~60% en tiempo de verificación y ~70% en código duplicado |
| Cambiado | **Sistema de Cleanup Automático**: Limpieza automática de contenedores detenidos y volúmenes huérfanos |
| Cambiado | **Configuración de Timeouts**: Variables de entorno configurables para APP_TIMEOUT_CHECK y APP_MAX_ATTEMPTS |
| Mejorado | **Compatibilidad Multiplataforma**: Soporte ampliado para 5+ gestores de paquetes diferentes |
| Mejorado | **Experiencia de Usuario**: Configuración automática guiada con mensajes específicos y sugerencias |
| Mejorado | **Mantenibilidad**: 15+ funciones modulares con separación clara de responsabilidades |
| Mejorado | **Verificaciones de Estado**: Información detallada de contenedores con health checks y formato JSON |
| Detalles Técnicos | **Scripts Optimizados**: app-run.sh completamente refactorizado con arrays asociativos y funciones reutilizables |
| Detalles Técnicos | **Instalación Inteligente**: Comandos específicos por plataforma con fallbacks robustos |
| Detalles Técnicos | **Manejo de Errores**: Mensajes específicos con instrucciones de solución para cada caso |
| Detalles Técnicos | **Logging Centralizado**: Sistema de logging con niveles (DEBUG, INFO, WARN, ERROR) y timestamps |
| Métricas de Rendimiento | **Reducción de tiempo de verificación**: ~60% |
| Métricas de Rendimiento | **Mejora en detección de gestores**: +40% de distribuciones soportadas |
| Métricas de Rendimiento | **Reducción de código duplicado**: ~70% |
| Métricas de Rendimiento | **Compatibilidad ampliada**: Soporte para 5+ gestores de paquetes |
| Detalles Técnicos | **Frontend**: React 18 + TypeScript + Vite + Bootstrap 5 |
| Detalles Técnicos | **Backend**: Node.js 18 + Express + PostgreSQL + JWT |
| Detalles Técnicos | **Database**: PostgreSQL 15 con pool de conexiones |
| Detalles Técnicos | **Deployment**: Docker Compose con servicios orquestados |
| Detalles Técnicos | **Host Dependencies**: curl, jq con instalación automática |
| Detalles Técnicos | **Security**: Helmet, CORS, Rate Limiting, Prepared Statements |
## [1.1.3] - 2025-11-05
| Tipo | Descripción |
|------|-------------|
| Corregido | **Corrección de rutas en server.js**: Implementación de `path.resolve()` para rutas dinámicas de archivos YAML |
| Corregido | **Mejora de verificación de dependencias Docker**: Verificación de versión mínima de Docker Engine (20.10+) |
| Corregido | **Implementación de método alternativo PostgreSQL**: Fallback usando `psql` cuando `pg_isready` no está disponible |
| Corregido | **Corrección de rutas en app-run.sh**: Uso de rutas relativas consistentes en comandos Docker Compose |
| Corregido | **Mejora de logging centralizado**: Sistema de logging con niveles (DEBUG, INFO, WARN, ERROR) y timestamps |
| Corregido | **Validación de configuración YAML**: Verificación de existencia de archivos antes del parseo |
| Detalles Técnicos | **Backend**: Corrección de rutas hardcodeadas y mejora de manejo de errores en configuración |
| Detalles Técnicos | **Script de despliegue**: Verificaciones más robustas de dependencias y mejor manejo de errores |
| Detalles Técnicos | **Logging**: Implementación de logger centralizado con colores y niveles de severidad |
| Detalles Técnicos | **Database**: Método alternativo de verificación de conectividad PostgreSQL |
## [1.1.2] - 2025-11-04
| Tipo | Descripción |
|------|-------------|
| Agregado | **Sistema de Asignación Directa de Recursos**: Nueva tabla `tarea_recursos` para asignar recursos específicos a tareas individuales |
| Agregado | **Campos Adicionales en Asignaciones**: Horas estimadas, horas reales y notas específicas por asignación de recurso |
| Agregado | **Auditoría de Asignaciones**: Registro de técnico asignador y timestamps para cada asignación de recurso |
| Cambiado | **Consultas de Recursos**: Modificación de queries SQL para usar asignaciones directas tarea-recurso en lugar de relaciones indirectas |
| Cambiado | **API de Tareas**: Actualización de endpoints para incluir información detallada de recursos asignados (horas, notas) |
| Corregido | **Relaciones de Recursos**: Corrección de lógica para mostrar recursos asignados específicamente a cada tarea |
| Corregido | **Precisión de Asignaciones**: Eliminación de asignaciones genéricas basadas en técnicos, implementación de asignaciones específicas |
| Detalles Técnicos | **Database**: Nueva tabla `tarea_recursos` con constraints de unicidad y relaciones many-to-many |
| Detalles Técnicos | **Backend**: Modificación de consultas SQL en `routes/tareas.js` para JOINs directos |
| Detalles Técnicos | **Frontend**: Compatibilidad automática con nueva estructura de datos de recursos |
| Detalles Técnicos | **Frontend**: React 18 + TypeScript + Vite + Bootstrap 5 |
| Detalles Técnicos | **Backend**: Node.js 18 + Express + PostgreSQL + JWT |
| Detalles Técnicos | **Database**: PostgreSQL 15 con pool de conexiones |
| Detalles Técnicos | **Deployment**: Docker Compose con servicios orquestados |
| Detalles Técnicos | **Security**: Helmet, CORS, Rate Limiting, Prepared Statements |
## [1.1.1] - 2025-11-04
| Tipo | Descripción |
|------|-------------|
| Agregado | **Sistema de Badges Profesionales**: Badges redondeados con colores específicos para estados y prioridades en todas las tablas |
| Agregado | **Validaciones de Formularios Mejoradas**: Sistema de validación en frontend con mensajes de error informativos |
| Agregado | **Filtrado de Técnicos Activos**: Solo técnicos activos se muestran en selectores de formularios de edición |
| Agregado | **Optimización de Rendimiento**: Carga paralela de opciones dinámicas con estados de carga visuales |
| Cambiado | **Interfaz de Tablas**: Mejora visual con badges centrados y colores profesionales en módulos de Tareas, Técnicos, Recursos y Usuarios |
| Cambiado | **Sistema de Formularios**: Extensión de EntityForm con soporte completo para opciones dinámicas y validaciones |
| Cambiado | **Paleta de Colores**: Implementación consistente de colores para estados, prioridades, roles y categorías |
| Corregido | **Alineación Vertical**: Corrección perfecta de centrado vertical para badges en filas de tablas |
| Corregido | **Carga de Opciones Dinámicas**: Resolución de errores de scope en funciones de carga de datos |
| Corregido | **Estados de Carga**: Implementación correcta de indicadores visuales durante operaciones asíncronas |
| Detalles Técnicos | **Frontend Enhancements**: Sistema de badges reutilizable, validaciones de formularios, carga paralela de datos |
| Detalles Técnicos | **UI/UX Improvements**: Colores profesionales, alineación perfecta, experiencia de usuario optimizada |
| Detalles Técnicos | **Performance**: Reducción del tiempo de carga en ~30% mediante operaciones paralelas |
| Detalles Técnicos | **Frontend**: React 18 + TypeScript + Vite + Bootstrap 5 |
| Detalles Técnicos | **Backend**: Node.js 18 + Express + PostgreSQL + JWT |
| Detalles Técnicos | **Database**: PostgreSQL 15 con pool de conexiones |
| Detalles Técnicos | **Deployment**: Docker Compose con servicios orquestados |
| Detalles Técnicos | **Security**: Helmet, CORS, Rate Limiting, Prepared Statements |
## [1.0.0] - 2025-11-01
| Tipo | Descripción |
|------|-------------|
| Agregado | **Sistema PHP Básico**: Arquitectura inicial con Docker y MySQL |
| Agregado | **Maquetación de Interfaz**: Páginas HTML/CSS/JS para todas las entidades |
| Agregado | **Calendario Interactivo**: FullCalendar.js integrado |
| Agregado | **Sistema de Reportes**: Gráficos básicos con Chart.js |
| Agregado | **Auto-hide Navbar**: Funcionalidad avanzada con animaciones CSS |
| Agregado | **Datos de Ejemplo**: Información simulada para testing |
| Agregado | **Navegación Consistente**: Menú unificado entre todas las páginas |
| Cambiado | **Base de Datos**: Migración de MySQL a PostgreSQL |
| Cambiado | **Arquitectura**: Preparación para migración a Node.js |
| Detalles Técnicos | **Frontend**: HTML5 + CSS3 + Vanilla JavaScript + Bootstrap 5 |
| Detalles Técnicos | **Backend**: PHP 8.1 + Apache + MySQL |
| Detalles Técnicos | **Database**: MySQL 8.0 con Docker |
| Detalles Técnicos | **UI/UX**: Diseño responsive con gradientes y animaciones |
## [0.2.0] - 2025-10-15
| Tipo | Descripción |
|------|-------------|
| Agregado | **Configuración Docker**: Dockerfile y docker-compose.yml |
| Agregado | **Base de Datos**: Esquema inicial con tablas de entidades |
| Agregado | **Páginas Principales**: Dashboard, Técnicos, Recursos, Tareas |
| Agregado | **Estilos CSS**: Diseño moderno con variables CSS personalizadas |
| Agregado | **JavaScript Básico**: Funcionalidad de dashboard y navegación |
| Detalles Técnicos | **Containerization**: Docker + Docker Compose |
| Detalles Técnicos | **Database**: MySQL con phpMyAdmin |
| Detalles Técnicos | **Frontend**: HTML básico con Bootstrap |
## [0.1.0] - 2025-10-01
| Tipo | Descripción |
|------|-------------|
| Agregado | **Proyecto Inicial**: Estructura básica del sistema DTIC Bitácoras |
| Agregado | **Documentación**: README con descripción del proyecto |
| Agregado | **Entidades Definidas**: Técnicos, Recursos, Usuarios, Tareas |
| Agregado | **Arquitectura Planificada**: 3 capas (Frontend, Backend, Database) |
| Detalles Técnicos | **Planning**: Definición de alcance y funcionalidades |
| Detalles Técnicos | **Documentation**: Estructura del proyecto documentada |
---
## Guías de Versionado
Este proyecto sigue el [Versionado Semántico](https://semver.org/):
- Versión **MAJOR** para cambios incompatibles en la API
- Versión **MINOR** para adiciones de funcionalidad compatibles hacia atrás
- Versión **PATCH** para correcciones de errores compatibles hacia atrás
### Tipos de Cambios
- **Agregado** para nuevas funcionalidades
- **Cambiado** para cambios en funcionalidad existente
- **Obsoleto** para funcionalidades próximamente eliminadas
- **Eliminado** para funcionalidades eliminadas
- **Corregido** para correcciones de errores
- **Seguridad** en caso de vulnerabilidades
### Convención de Commits
Los commits siguen la especificación [Conventional Commits](https://conventionalcommits.org/):
- `feat:` para nuevas funcionalidades
- `fix:` para correcciones de errores
- `docs:` para documentación
- `style:` para formateo
- `refactor:` para reestructuración de código
- `test:` para pruebas
- `chore:` para mantenimiento
---
**Leyenda:**
- 🚀 Nueva funcionalidad
- 🐛 Corrección de error
- 📚 Documentación
- 🎨 Estilo
- ♻️ Refactorización
- ⚡ Rendimiento
- 🔒 Seguridad
- ✅ Prueba
+872
View File
@@ -0,0 +1,872 @@
# DTIC Bitácoras - Sistema de Gestión Integral
## 📋 Descripción del Sistema
DTIC Bitácoras es un sistema web completo de gestión de recursos tecnológicos y tareas para el Departamento de Tecnología de la Información y Comunicación (DTIC). Desarrollado con tecnologías modernas, permite administrar eficientemente el inventario de hardware/software, asignar recursos a usuarios, gestionar tareas técnicas y mantener un registro completo de todas las operaciones.
### 🎯 Propósito y Alcance
El sistema está diseñado para:
- **Gestión de Recursos**: Controlar inventario de hardware, software, equipos de red y herramientas
- **Administración de Personal**: Gestionar técnicos del DTIC con diferentes roles y permisos
- **Asignación de Recursos**: Vincular recursos tecnológicos con usuarios finales
- **Seguimiento de Tareas**: Administrar y monitorear tareas técnicas asignadas a técnicos
- **Auditoría Completa**: Mantener registro detallado de todas las operaciones del sistema
- **Reportes y Estadísticas**: Generar informes sobre el estado del inventario y rendimiento
- **Framework de Prompts DTIC**: Sistema automatizado de gestión de flujos de trabajo y documentación para procesos de desarrollo optimizados
## 🚀 Inicio Rápido
### Opción 1: Usando Script Optimizado (Recomendado)
```bash
# Configuración inicial automática (primera ejecución)
./app-run.sh
# Iniciar aplicación
./app-run.sh start
# Ver estado
./app-run.sh status
# Ver logs (requiere aplicación ejecutándose)
./app-run.sh logs
# Crear backup
./app-run.sh bd-backup
# Detener aplicación
./app-run.sh stop
```
### Opción 2: Usando Docker Compose Manual
```bash
# Clonar el repositorio
git clone <repository-url>
cd dtic-bitacoras-php/_app-npm
# Ejecutar la aplicación completa
docker-compose up --build
# Acceder a la aplicación
# Frontend: http://localhost:5173
# Backend API: http://localhost:3001
# Base de datos: localhost:5432
```
## 🔧 Configuración para Despliegue Remoto
### 1. Variables de Entorno
Copia el archivo de ejemplo y configura tus variables:
```bash
cp .env.example .env
# Edita .env según tus necesidades
```
### 2. Configuración por Entorno
El archivo `docker-compose.override.yml` permite personalizar la configuración:
```yaml
# Variables disponibles en .env
POSTGRES_PORT=5432
API_PORT=3001
FRONTEND_PORT=5173
NODE_ENV=production
# ... etc
```
### 3. Despliegue en Producción
```bash
# Configurar variables de producción en .env
NODE_ENV=production
VITE_API_URL=https://tu-dominio.com/api
# Desplegar
make up
```
## 🏗️ Arquitectura del Sistema
### Arquitectura General
El sistema sigue una arquitectura de **3 capas** con contenedores Docker:
```
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Frontend │ │ Backend │ │ Database │
│ React/Vite │◄──►│ Node.js/Express │◄──►│ PostgreSQL │
│ Puerto 5173 │ │ Puerto 3001 │ │ Puerto 5432 │
└─────────────────┘ └─────────────────┘ └─────────────────┘
```
### Componentes Principales
#### 🖥️ Frontend (React + Vite)
- **Framework**: React 18 con TypeScript
- **Estado Global**: Zustand para gestión de estado
- **UI Components**: Bootstrap + FontAwesome
- **Rutas**: React Router con protección de rutas
- **Configuración**: Sistema de entidades dinámicas vía YAML
- **Versionado Dinámico**: Carga automática de versión desde package.json mediante Vite config
#### 🚀 Backend (Node.js + Express)
- **Runtime**: Node.js 18 con Alpine Linux
- **Framework**: Express.js con middleware avanzado
- **Base de Datos**: PostgreSQL con pool de conexiones
- **Autenticación**: JWT con bcrypt para hashing
- **API**: RESTful con validación de datos
- **Seguridad**: Helmet, CORS, Rate Limiting
#### 🗄️ Base de Datos (PostgreSQL)
- **Motor**: PostgreSQL 15
- **Esquema**: `dtic` con tablas normalizadas
- **Índices**: Optimizados para búsquedas comunes
- **Auditoría**: Triggers automáticos para `updated_at`
- **Datos de Ejemplo**: Incluye usuarios y recursos de prueba
### Entidades del Sistema
#### 👥 Técnicos
Los **técnicos** son los profesionales especializados del DTIC que resuelven las tareas asignadas al departamento. Son los responsables directos de ejecutar y completar las actividades del sistema.
**Características principales:**
- **ID único**: Identificador único del técnico
- **Información personal**: Nombre, apellido, email, teléfono
- **Rol**: Administrador, Técnico, Visualizador
- **Departamento**: Área específica dentro del DTIC
- **Estado**: Activo, Inactivo
- **Tareas asignadas**: Número y lista de tareas bajo su responsabilidad
- **Historial de actividad**: Registro de tareas completadas y en progreso
- **Permisos**: Nivel de acceso al sistema según su rol
**Roles definidos:**
- **Administrador**: Acceso completo, gestión de usuarios y configuración
- **Técnico**: Ejecución de tareas, gestión de recursos asignados
- **Visualizador**: Solo lectura, acceso a reportes y consultas
#### 📦 Recursos
Los **recursos** son los elementos físicos o digitales que utiliza el DTIC para realizar sus tareas operativas. Cada recurso tiene características específicas y puede estar asignado a usuarios para su utilización.
**Características principales:**
- **ID único**: Identificador alfanumérico único (ej: RES-001)
- **Nombre**: Descripción clara del recurso
- **Categoría**: Clasificación jerárquica (Hardware, Software, Redes, Seguridad, Herramientas)
- **Estado**: Disponible, Asignado, Mantenimiento, Retirado
- **Ubicación**: Lugar físico donde se encuentra el recurso
- **Información técnica**: Modelo, serie, especificaciones técnicas
- **Historial de uso**: Registro de tareas en las que ha sido utilizado
- **Última tarea**: Información de la tarea más reciente donde participó
**Ejemplos de recursos:**
- Laptops, proyectores, servidores (Hardware)
- Licencias de software, antivirus (Software)
- Routers, switches, cables (Redes)
- Certificados, firewalls (Seguridad)
- Kits de herramientas, testers (Herramientas)
#### 👤 Usuarios Relacionados
Los **usuarios** son las personas que trabajan con los recursos del DTIC en sus actividades diarias. A diferencia de los técnicos, no resuelven tareas del sistema sino que utilizan los recursos relacionados para realizar su trabajo operativo.
**Características principales:**
- **ID único**: Identificador único del usuario
- **Información personal**: Nombre, apellido, email, teléfono
- **Rol operativo**: Operador, Supervisor, Analista, Invitado
- **Departamento**: Área específica donde opera
- **Estado**: Activo, Inactivo
- **Recursos relacionados**: Lista de recursos bajo su responsabilidad
- **Historial de uso**: Registro de recursos utilizados
**Roles operativos:**
- **Operador**: Uso básico de recursos asignados
- **Supervisor**: Coordinación de recursos y supervisión de operadores
- **Analista**: Análisis de datos y reportes usando recursos específicos
- **Invitado**: Acceso limitado a recursos específicos por tiempo determinado
#### 📋 Tareas
Las **tareas** son las actividades específicas que debe realizar el DTIC, asignadas a técnicos para su resolución. Cada tarea tiene un ciclo de vida completo desde su creación hasta su finalización.
**Características principales:**
- **ID único**: Identificador alfanumérico único (ej: TSK-001)
- **Título**: Descripción breve de la tarea
- **Descripción**: Detalles completos de lo que se debe realizar
- **Estado**: Pendiente, En Progreso, Completada, Cancelada
- **Prioridad**: Baja, Media, Alta, Urgente
- **Técnico asignado**: Profesional responsable de la ejecución
- **Fechas**: Creación, inicio, vencimiento, finalización
- **Historial de actividad**: Registro detallado de todos los movimientos
- **Recursos utilizados**: Lista de recursos que participaron en la tarea
**Estados del ciclo de vida:**
- **Pendiente**: Esperando asignación de técnico
- **En Progreso**: Siendo ejecutada por el técnico asignado
- **Completada**: Finalizada exitosamente
- **Cancelada**: Terminada sin completar por diversos motivos
#### 📊 Historial de Auditoría
El **historial de auditoría** registra todas las acciones realizadas en el sistema para mantener un registro completo de cambios y actividades.
**Características principales:**
- **Usuario**: Quién realizó la acción
- **Acción**: Tipo de operación (crear, modificar, eliminar, consultar)
- **Entidad**: Objeto afectado (tarea, recurso, usuario, etc.)
- **Fecha/Hora**: Timestamp preciso de la acción
- **Detalles**: Información específica de lo que cambió
- **IP**: Dirección desde donde se realizó la acción
#### 📈 Reportes y Análisis
Los **reportes** son consultas estructuradas que permiten analizar el estado y rendimiento del sistema DTIC Bitácoras.
**Tipos de reportes:**
- **Tareas**: Estado, productividad, tiempos de resolución
- **Recursos**: Utilización, disponibilidad, mantenimiento
- **Usuarios**: Actividad, asignaciones, rendimiento
- **Sistema**: Estadísticas generales, logs de auditoría
### Funcionalidades Clave
#### 🔐 Sistema de Autenticación
- Login seguro con JWT
- Roles y permisos granulares
- Cambio de contraseña
- Sesiones persistentes
#### 📊 Dashboard y Estadísticas
- Métricas en tiempo real
- Gráficos de estado de recursos
- Contadores de tareas por estado
- Información consolidada del sistema
#### 🔍 Gestión Dinámica de Entidades
- Sistema configurable vía archivos YAML
- Formularios dinámicos
- Tablas con filtros y búsqueda
- Modales para acciones específicas
#### 📈 Reportes y Análisis
- Estados de proyectos
- Calendarios de tareas
- Reportes personalizados
- Exportación de datos
### 🔢 Sistema de Versionado Dinámico
El sistema implementa un mecanismo de versionado dinámico que garantiza la consistencia de versiones en toda la aplicación:
#### 📋 Carga Automática de Versión
- **Configuración Vite**: El archivo `vite.config.ts` lee automáticamente la versión desde `package.json`
- **Variable Global**: Define `import.meta.env.VERSION` disponible en todo el frontend
- **Actualización Automática**: Cambios en `package.json` se reflejan inmediatamente en la interfaz
#### 🎨 Visualización en Interfaz
- **Badge de Versión**: Se muestra en la barra de navegación principal junto al logo
- **Formato**: `v{versión}` (ej: v1.7.0)
- **Estilos**: Badge moderno con gradiente y efectos hover
- **Ubicación**: Navbar superior, siempre visible para usuarios autenticados
#### 🔄 Mantenimiento de Versiones
- **Semantic Versioning**: Seguimiento de cambios según MAJOR.MINOR.PATCH
- **CHANGELOG**: Registro detallado de cambios por versión
- **Consistencia**: Versiones sincronizadas entre package.json, documentación y código
## 📁 Estructura del Proyecto
```
_app-npm/
├── backend/ # API REST Node.js/Express
│ ├── src/
│ │ ├── routes/ # Endpoints por entidad
│ │ │ ├── auth.js # Autenticación
│ │ │ ├── tecnicos.js # Gestión de técnicos
│ │ │ ├── recursos.js # Gestión de recursos
│ │ │ ├── tareas.js # Gestión de tareas
│ │ │ └── usuarios_relacionados.js # Gestión de usuarios
│ │ ├── middleware/ # Middleware de seguridad
│ │ │ └── auth.js # Verificación JWT
│ │ └── server.js # Servidor principal
│ ├── Dockerfile # Contenedor backend
│ └── package.json # Dependencias Node.js
├── frontend/ # SPA React/Vite
│ ├── src/
│ │ ├── components/ # Componentes reutilizables
│ │ │ ├── common/ # Componentes genéricos
│ │ │ ├── layout/ # Layout y navegación
│ │ │ └── auth/ # Componentes de auth
│ │ ├── pages/ # Páginas principales
│ │ │ ├── Dashboard.tsx # Dashboard principal
│ │ │ ├── EntityPage.tsx # Páginas dinámicas
│ │ │ ├── Login.tsx # Página de login
│ │ │ └── Reportes.tsx # Reportes del sistema
│ │ ├── stores/ # Estado global (Zustand)
│ │ │ ├── authStore.ts # Estado de autenticación
│ │ │ └── genericEntityStore.ts # Estado de entidades
│ │ ├── config/ # Configuración
│ │ │ └── entities.yml # Definición de entidades
│ │ └── utils/ # Utilidades
│ ├── Dockerfile # Contenedor frontend
│ ├── package.json # Dependencias frontend
│ └── vite.config.ts # Configuración Vite
├── docker/ # Configuración Docker
│ └── init.sql # Inicialización BD
├── docker-compose.yml # Orquestación de servicios
├── docker-compose.override.yml # Override por entorno
├── .env.example # Variables de entorno
├── app-run.sh # Script principal optimizado
├── app-run_lib.sh # Biblioteca de funciones compartidas
├── app-run_deps.sh # Gestión de dependencias del sistema
└── README.md # Esta documentación
```
## 🛠️ Comandos Disponibles
### Script Optimizado app-run.sh
```bash
./app-run.sh # Menú interactivo completo
./app-run.sh start # Iniciar aplicación
./app-run.sh stop # Detener aplicación
./app-run.sh restart # Reiniciar aplicación
./app-run.sh status # Ver estado detallado
./app-run.sh bd-backup # Crear backup de base de datos
./app-run.sh bd-restore # Restaurar backup de base de datos
```
### Docker Compose
```bash
docker-compose up -d # Iniciar en background
docker-compose up --build # Construir e iniciar
docker-compose down # Detener
docker-compose logs -f # Ver logs en tiempo real
docker-compose ps # Ver estado
docker-compose exec api sh # Acceder al shell del API
docker-compose exec postgres bash # Acceder a PostgreSQL
```
## 🔍 Solución de Problemas
### Error "NetworkError when attempting to fetch resource"
1. **Verificar configuración CORS**: Asegurarse de que el backend permita el origen del frontend
2. **Verificar VITE_API_URL**: Confirmar que apunte al servidor backend correcto
3. **Verificar conectividad**: Probar que el backend esté ejecutándose y accesible
### Puertos Ocupados
Si los puertos por defecto están ocupados, modificalos en `.env`:
```env
POSTGRES_PORT=5433
API_PORT=3002
FRONTEND_PORT=5174
```
### Problemas de Base de Datos
```bash
# Ver logs de PostgreSQL
make logs-db
# Acceder a la base de datos
make dev-db
# Recrear base de datos
docker-compose down -v
make up
```
## 🔒 Seguridad
### Producción
- Cambia `JWT_SECRET` por una clave segura
- Cambia `POSTGRES_PASSWORD` por una contraseña fuerte
- Configura `NODE_ENV=production`
- Usa HTTPS en producción
- Configura firewall para exponer solo los puertos necesarios
### Variables Sensibles
Nunca commits las siguientes variables al repositorio:
- `JWT_SECRET`
- `POSTGRES_PASSWORD`
- Cualquier clave API
## 📊 Monitoreo
### Health Checks
```bash
make health-check
```
### Logs
```bash
make logs # Todos los logs
make logs-api # Solo API
make logs-frontend # Solo frontend
make logs-db # Solo base de datos
```
### Estado de Contenedores
```bash
make status
```
## 🔄 Backup y Restauración
### Crear Backup
```bash
make backup
# Los backups se guardan en ./backups/
```
### Restaurar Backup
```bash
make restore
# Selecciona el archivo de backup del listado
```
## 🐳 Docker
### Imágenes
- **PostgreSQL**: `postgres:15-alpine`
- **API**: `node:18-alpine` con aplicación Node.js
- **Frontend**: `node:18-alpine` con aplicación React/Vite
### Volúmenes
- `postgres_data`: Datos persistentes de PostgreSQL
- `./backups`: Backups de base de datos
- `./logs`: Logs de la aplicación
### Redes
- `dtic_network`: Red interna para comunicación entre servicios
## 🧪 Desarrollo y Testing
### Entorno de Desarrollo
#### Configuración Inicial
```bash
# Clonar repositorio
git clone <repository-url>
cd dtic-bitacoras-php/_app-npm
# Configuración automática
./setup.sh
# O configuración manual
make setup
```
#### Ejecución en Modo Desarrollo
```bash
# Todos los servicios
make up
# Solo frontend (puerto 5173)
make dev-frontend
# Solo backend (puerto 3001)
make dev-backend
# Acceder a base de datos
make dev-db
```
#### Desarrollo con Hot Reload
- **Frontend**: Cambios automáticos con Vite HMR
- **Backend**: Reinicio automático con nodemon
- **Base de Datos**: Persistente con volúmenes Docker
### Testing
#### Ejecutar Tests
```bash
# Suite completa
make test
# Tests específicos
make test-backend # Tests del backend
make test-frontend # Tests del frontend
# Tests con coverage
make test-coverage
```
#### Tipos de Tests
- **Unit Tests**: Componentes individuales y funciones utilitarias
- **Integration Tests**: Endpoints de API y interacciones con BD
- **E2E Tests**: Flujos completos de usuario con Playwright/Cypress
### Debugging
#### Logs en Tiempo Real
```bash
# Todos los servicios
make logs
# Servicio específico
make logs-api # Backend
make logs-frontend # Frontend
make logs-db # Base de datos
```
#### Acceso a Contenedores
```bash
# Shell en backend
docker-compose exec api sh
# PostgreSQL CLI
docker-compose exec postgres psql -U dtic_user -d dtic_bitacoras
# Inspeccionar red
docker network inspect dtic_bitacoras_dtic_network
```
### Base de Datos de Desarrollo
#### Conexión Directa
```bash
# Desde host
psql -h localhost -p 5432 -U dtic_user -d dtic_bitacoras
# Desde contenedor
make dev-db
```
#### Datos de Prueba
La base de datos incluye datos de ejemplo:
- **7 Técnicos**: Admin, técnicos y visualizadores
- **6 Recursos**: Hardware, software y herramientas
- **5 Usuarios Relacionados**: Personal administrativo
- **Asignaciones**: Recursos vinculados a usuarios
#### Reset de Datos
```bash
# Recrear base de datos
make clean
make up
# O desde contenedor
docker-compose exec postgres psql -U dtic_user -d dtic_bitacoras -c "DROP SCHEMA dtic CASCADE; CREATE SCHEMA dtic;"
```
## 🤝 Contribución y Desarrollo
### Flujo de Trabajo
1. **Fork y Clone**
```bash
git clone <tu-fork-url>
cd dtic-bitacoras-php/_app-npm
git checkout -b feature/nueva-funcionalidad
```
2. **Desarrollo**
```bash
# Instalar dependencias
make setup
# Ejecutar en desarrollo
make up
# Tests continuos
make test-watch
```
3. **Commits y Pull Request**
```bash
git add .
git commit -m "feat: descripción de la funcionalidad"
git push origin feature/nueva-funcionalidad
# Crear PR en GitHub
```
### Estándares de Código
#### Frontend (TypeScript/React)
- **Linter**: ESLint con reglas de Airbnb
- **Formatter**: Prettier
- **Tipos**: TypeScript estricto
- **Componentes**: Funcionales con hooks
- **Estado**: Zustand para estado global
#### Backend (Node.js)
- **Linter**: ESLint Node.js
- **Estructura**: MVC con separación de responsabilidades
- **Validación**: Joi para schemas de datos
- **Errores**: Manejo centralizado de errores
- **Logs**: Winston para logging estructurado
#### Base de Datos
- **Migrations**: Versionado de schema
- **Seeds**: Datos de prueba consistentes
- **Índices**: Optimización de consultas
- **Constraints**: Integridad referencial
### Documentación
#### Código
- **JSDoc**: Comentarios en funciones complejas
- **README**: Actualización de documentación
- **API Docs**: Swagger/OpenAPI para endpoints
#### Commits
- **Conventional Commits**: `feat:`, `fix:`, `docs:`, `refactor:`
- **Descripciones**: Claras y específicas
- **Issues**: Referencia a issues relacionados
## 📋 API Reference
### Endpoints Principales
#### Autenticación
```
POST /api/auth/login # Login de usuario
POST /api/auth/logout # Logout (cliente-side)
GET /api/auth/verify # Verificar token
```
#### Técnicos
```
GET /api/tecnicos # Listar técnicos
POST /api/tecnicos # Crear técnico
PUT /api/tecnicos/:id # Actualizar técnico
DELETE /api/tecnicos/:id # Eliminar técnico
PATCH /api/tecnicos/:id/toggle # Activar/desactivar
```
#### Recursos
```
GET /api/recursos # Listar recursos
POST /api/recursos # Crear recurso
PUT /api/recursos/:id # Actualizar recurso
DELETE /api/recursos/:id # Eliminar recurso
POST /api/recursos/:id/assign # Asignar a usuario
DELETE /api/recursos/:id/unassign # Desasignar
```
#### Tareas
```
GET /api/tareas # Listar tareas
POST /api/tareas # Crear tarea
PUT /api/tareas/:id # Actualizar tarea
DELETE /api/tareas/:id # Eliminar tarea
```
#### Usuarios Relacionados
```
GET /api/usuarios_relacionados # Listar usuarios
POST /api/usuarios_relacionados # Crear usuario
PUT /api/usuarios_relacionados/:id # Actualizar usuario
DELETE /api/usuarios_relacionados/:id # Eliminar usuario
```
### Configuración Dinámica
```
GET /api/config/entities.yml # Configuración de entidades
```
## 🔧 Configuración Avanzada
### Variables de Entorno
| Variable | Descripción | Default |
|----------|-------------|---------|
| `NODE_ENV` | Ambiente (development/production) | development |
| `PORT` | Puerto del backend | 3001 |
| `DATABASE_URL` | URL de conexión PostgreSQL | - |
| `JWT_SECRET` | Clave secreta para JWT | - |
| `JWT_EXPIRES_IN` | Expiración del token | 24h |
| `CORS_ORIGIN` | Origen permitido para CORS | * |
### Docker Compose Overrides
```yaml
# docker-compose.override.yml
services:
api:
environment:
NODE_ENV: production
JWT_SECRET: ${JWT_SECRET}
ports:
- "80:3001"
postgres:
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
```
## 📊 Monitoreo y Métricas
### Health Checks
- **Endpoint**: `GET /health`
- **Base de Datos**: Verificación de conexión
- **Servicios**: Estado de dependencias
### Métricas de Rendimiento
- **Response Times**: Tiempos de respuesta por endpoint
- **Database Queries**: Consultas lentas y optimización
- **Memory Usage**: Uso de memoria por contenedor
- **Error Rates**: Tasa de errores por servicio
## 🚨 Solución de Problemas Comunes
### Problemas de Conexión
```bash
# Verificar servicios
docker-compose ps
# Logs de errores
make logs
# Reiniciar servicios
make restart
```
### Problemas de Base de Datos
```bash
# Verificar conexión
make health-check
# Reset de datos
make clean && make up
```
### Problemas de Frontend
```bash
# Limpiar cache
rm -rf node_modules/.vite
make dev-frontend
```
## 📞 Soporte y Contacto
### Canales de Soporte
- **Issues**: GitHub Issues para bugs y features
- **Discussions**: GitHub Discussions para preguntas
- **Wiki**: Documentación detallada en GitHub Wiki
### Reportar Bugs
1. Verificar si ya existe el issue
2. Incluir pasos para reproducir
3. Adjuntar logs relevantes
4. Especificar versión y entorno
### Solicitar Features
1. Describir la funcionalidad deseada
2. Explicar el caso de uso
3. Proponer implementación si es posible
## 📚 Evolución del Proyecto
### Antecedentes
Este proyecto representa la evolución completa del sistema DTIC Bitácoras, desde un enfoque inicial basado en PHP/MySQL hasta la implementación actual con tecnologías modernas React/Node.js/PostgreSQL.
### Fases de Desarrollo
#### **Fase 1: Fundación PHP (2025-10)**
- **Arquitectura**: HTML/JS/PHP/MySQL con Docker
- **Alcance**: Desarrollo de interfaces básicas y configuración de contenedores
- **Estado**: ✅ Completado - Etapas 1 y 2 del plan original
- **Resultado**: Base sólida para la evolución tecnológica
- **Tareas Clave**: Configuración Docker, maquetación interfaz, auto-hide navbar
#### **Fase 2: Migración Tecnológica (2025-11)**
- **Arquitectura**: React/Node.js/PostgreSQL con Docker
- **Alcance**: Reimplementación completa con tecnologías modernas
- **Estado**: ✅ Completado - Sistema 100% funcional (v1.2.0)
- **Resultado**: Aplicación full-stack moderna y escalable
- **Tareas Clave**: APIs RESTful, autenticación JWT, gestión entidades CRUD
### Metodología de Desarrollo
El proyecto se desarrolló siguiendo una metodología estructurada:
1. **Análisis y Planificación**: Definición de entidades y arquitectura
2. **Implementación por Etapas**: Desarrollo incremental con hitos claros
3. **Migración Tecnológica**: Transición de PHP a Node.js/React
4. **Optimización Continua**: Mejoras en scripts, documentación y procesos
### Tecnologías Evolutivas
- **Inicial**: PHP 8.1, MySQL 8.0, HTML5/CSS3/JS, Bootstrap 5
- **Actual**: React 18, Node.js 18, PostgreSQL 15, TypeScript, Docker
### 📋 Resumen de Tareas Completadas
#### **Estimación de Versión (2025-11-04)**
- ✅ Análisis completo de evolución del proyecto
- ✅ Determinación de versión 1.1.0 según Semantic Versioning
- ✅ Justificación técnica por componentes MAJOR/MINOR/PATCH
- ✅ Planificación de versiones futuras (1.2.0, 1.3.0, 2.0.0)
#### **Optimización de Scripts (2025-11-04)**
- ✅ Script app-run.sh completamente optimizado
- ✅ Modo dual: interactivo + parámetros start/stop/restart/status
- ✅ Verificación robusta de dependencias (Docker, docker-compose)
- ✅ Validación completa de conectividad PostgreSQL
- ✅ Cleanup automático de recursos Docker
#### **Reorganización de Documentación (2025-11-04)**
- ✅ CHANGELOG.md movido a _app-npm/ para centralización
- ✅ README.md histórico archivado en _basurero/ como referencia
- ✅ Estructura de documentación consolidada
- ✅ Navegabilidad mejorada para desarrolladores
#### **Enriquecimiento con Información Histórica (2025-11-04)**
- ✅ Sección "Entidades del Sistema" enriquecida con detalles técnicos
- ✅ Nueva sección "Evolución del Proyecto" documentada
- ✅ Información institucional completa del autor agregada
- ✅ Contexto académico de UTN FR La Rioja incorporado
---
## 👨‍💻 Autor y Desarrollo
**Desarrollado por:** Lic. Ricardo MONLA
**Institución:** Universidad Tecnológica Nacional - Facultad Regional La Rioja
**Departamento:** Departamento de Servidores, Dirección de TIC
**Proyecto:** Sistema DTIC Bitácoras v1.7.0
**Fecha:** Noviembre 2025
### Contacto
Para soporte técnico o consultas sobre el desarrollo del sistema, contactar al departamento DTIC de la UTN FR La Rioja.
## 🔄 Cambios Recientes y Mantenimiento
### Últimas Actualizaciones (2025-11-04)
-**Versión 1.1.0** establecida según Semantic Versioning
-**Script app-run.sh** completamente optimizado con modos duales
-**Documentación reorganizada** y centralizada en _app-npm/
-**Información histórica** incorporada y enriquecida
-**Identidad institucional** completa documentada
### Próximas Versiones Planificadas
- **v1.2.0**: Calendario interactivo completo + sistema de reportes
- **v1.3.0**: Notificaciones en tiempo real + filtros avanzados
- **v2.0.0**: Multi-tenancy + APIs públicas
### Mantenimiento y Soporte
- **Repositorio**: Gestión completa con Git y Conventional Commits
- **Documentación**: README.md + CHANGELOG.md actualizados
- **Scripts**: Automatización completa con app-run.sh optimizado
- **Soporte**: Departamento DTIC - UTN FR La Rioja
---
**Desarrollado por:** Lic. Ricardo MONLA
**Institución:** Universidad Tecnológica Nacional - Facultad Regional La Rioja
**Departamento:** Departamento de Servidores, Dirección de TIC
**Proyecto:** Sistema DTIC Bitácoras v1.7.0
**Última actualización:** Noviembre 2025
+778
View File
@@ -0,0 +1,778 @@
#!/bin/bash
# =============================================================================
# DTIC Bitácoras - Script Optimizado de Gestión de Aplicación
# =============================================================================
#
# Script optimizado para gestión completa de la aplicación DTIC Bitácoras
# Soporta modos interactivo y no interactivo con parámetros
#
# Características:
# - Modo interactivo (sin parámetros) con menús inteligentes
# - Modo no interactivo con parámetros: start, stop, restart, status
# - Verificación robusta de dependencias (Docker, docker-compose)
# - Validación completa de PostgreSQL y servicios
# - Cleanup automático de recursos huérfanos
# - Timeouts configurables vía variables de entorno
#
# Uso:
# ./app-run.sh # Modo interactivo
# ./app-run.sh start # Iniciar aplicación (no interactivo)
# ./app-run.sh stop # Detener aplicación (no interactivo)
# ./app-run.sh restart # Reiniciar aplicación (no interactivo)
# ./app-run.sh status # Mostrar estado detallado (no interactivo)
# ./app-run.sh bd-backup # Crear backup de base de datos (no interactivo)
# ./app-run.sh bd-restore # Restaurar base de datos desde backup (no interactivo)
#
# Variables de entorno:
# APP_TIMEOUT_CHECK=30 # Timeout para verificar servicios (segundos)
# APP_MAX_ATTEMPTS=20 # Máximo número de intentos de verificación
# APP_BACKUP_DIR="backups" # Directorio para backups
#
# Versión: 2.1 - Con funcionalidad de backup
# Fecha: 2025-11-06
# =============================================================================
set -e
# Change to script directory to allow running from anywhere
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
# Cargar biblioteca compartida
source "$SCRIPT_DIR/app-run_lib.sh"
# Configuración
API_PORT=3001
FRONTEND_PORT=5173
DB_PORT=5432
API_URL="http://localhost:$API_PORT"
FRONTEND_URL="http://localhost:$FRONTEND_PORT"
DB_URL="localhost:$DB_PORT"
# Configuración de timeouts (configurables vía entorno)
TIMEOUT_CHECK=${APP_TIMEOUT_CHECK:-30}
MAX_ATTEMPTS=${APP_MAX_ATTEMPTS:-20}
# Configuración de backup
BACKUP_DIR=${APP_BACKUP_DIR:-"backups"}
BACKUP_FORMAT="dtic_bitacoras_backup_%Y%m%d_%H%M%S.sql"
# Modo de operación
INTERACTIVE_MODE=true
COMMAND=""
# Función para verificar si la aplicación está ejecutándose
check_app_running() {
log "🔍 Verificando estado de contenedores Docker..."
# Verificar contenedores Docker
if docker compose ps 2>/dev/null | grep -q "dtic_bitacoras"; then
log "✅ Contenedores encontrados ejecutándose"
return 0
else
log "❌ No se encontraron contenedores ejecutándose"
return 1
fi
}
# Función para verificar conectividad a PostgreSQL
check_db_connection() {
log "🔍 Verificando conexión a PostgreSQL..."
# Método 1: Usar psql si está disponible
if command -v psql &> /dev/null; then
log "📡 Intentando conectar a PostgreSQL con psql..."
if PGPASSWORD=dtic_password psql -h localhost -p $DB_PORT -U dtic_user -d dtic_bitacoras -c "SELECT 1;" &> /dev/null; then
log "✅ Conexión a PostgreSQL exitosa (psql)"
return 0
else
log "❌ Fallo en conexión a PostgreSQL (psql)"
fi
else
log "⚠️ psql no disponible, intentando método alternativo con curl..."
fi
# Método 2: Verificar conectividad usando la API (que internamente usa PostgreSQL)
log "🌐 Verificando conectividad de BD a través de la API..."
if curl -s --max-time 5 "$API_URL/health" >/dev/null 2>&1; then
log "✅ API responde, indicando que PostgreSQL está conectado"
return 0
else
log "❌ API no responde, posible problema con PostgreSQL"
return 1
fi
}
# Función para verificar si la API está accesible
check_api_accessible() {
log "🔍 Verificando accesibilidad de la API..."
log "🌐 Probando endpoint: $API_URL/health"
if curl -s --max-time 5 "$API_URL/health" >/dev/null 2>&1; then
log "✅ API accesible"
return 0
else
log "❌ API no accesible"
return 1
fi
}
# Función para verificar si el frontend está accesible
check_frontend_accessible() {
log "🔍 Verificando accesibilidad del frontend..."
log "🌐 Probando URL: $FRONTEND_URL"
if curl -s --max-time 5 "$FRONTEND_URL" >/dev/null 2>&1; then
log "✅ Frontend accesible"
return 0
else
log "❌ Frontend no accesible"
return 1
fi
}
# Función para mostrar estado actual
show_status() {
echo ""
echo "📊 Estado Actual de DTIC Bitácoras:"
echo "=================================="
if check_app_running; then
echo -e "🐳 Contenedores: ${GREEN}✅ Ejecutándose${NC}"
if check_api_accessible; then
echo -e "🔧 API: ${GREEN}✅ Accesible${NC} (puerto $API_PORT)"
else
echo -e "🔧 API: ${RED}❌ No accesible${NC} (puerto $API_PORT)"
fi
if check_frontend_accessible; then
echo -e "🌐 Frontend: ${GREEN}✅ Accesible${NC} (puerto $FRONTEND_PORT)"
else
echo -e "🌐 Frontend: ${RED}❌ No accesible${NC} (puerto $FRONTEND_PORT)"
fi
if check_db_connection; then
echo -e "🗄️ Base de Datos: ${GREEN}✅ Conectada${NC} (puerto $DB_PORT)"
else
echo -e "🗄️ Base de Datos: ${RED}❌ No conectada${NC} (puerto $DB_PORT)"
fi
else
echo -e " Contenedores: ${RED}❌ Detenidos${NC}"
echo -e "🔧 API: ${YELLOW}❓ No verificable${NC}"
echo -e "🌐 Frontend: ${YELLOW}❓ No verificable${NC}"
echo -e "🗄️ Base de Datos: ${YELLOW}❓ No verificable${NC}"
fi
echo ""
}
# Función para mostrar menú de opciones
show_menu() {
echo "Opciones disponibles:"
echo "==================="
local option_num=1
if check_app_running; then
echo -e "${GREEN}${option_num})${NC} 🛑 Detener aplicación"
((option_num++))
echo -e "${GREEN}${option_num})${NC} 🔄 Reiniciar aplicación"
((option_num++))
echo -e "${YELLOW}${option_num})${NC} 💾 Crear backup de BD"
((option_num++))
echo -e "${YELLOW}${option_num})${NC} 🔄 Restaurar BD desde backup"
((option_num++))
else
echo -e "${GREEN}${option_num})${NC} ▶️ Iniciar aplicación"
((option_num++))
echo -e "${YELLOW}${option_num})${NC} 💾 Crear backup de BD"
((option_num++))
echo -e "${YELLOW}${option_num})${NC} 🔄 Restaurar BD desde backup"
((option_num++))
fi
echo -e "${BLUE}${option_num})${NC} 📊 Ver estado detallado"
((option_num++))
echo -e "${BLUE}${option_num})${NC} 🚪 Salir"
echo ""
}
# Función para iniciar aplicación
start_app() {
log "🚀 Iniciando aplicación DTIC Bitácoras..."
if check_app_running; then
warning "La aplicación ya está ejecutándose"
return 0
fi
# Cleanup automático antes de iniciar
cleanup_resources
log "🐳 Ejecutando 'docker compose up --build -d'..."
if docker compose up --build -d; then
success "Aplicación iniciada"
# Esperar a que esté lista
log "⏳ Esperando que los servicios estén listos..."
sleep 5
local attempts=0
while [ $attempts -lt $MAX_ATTEMPTS ]; do
log "🔄 Intento $((attempts+1))/$MAX_ATTEMPTS de verificación de servicios..."
if check_api_accessible && check_frontend_accessible && check_db_connection; then
success "✅ Todos los servicios están listos"
if [ "$INTERACTIVE_MODE" = false ]; then
show_access_urls
fi
break
fi
sleep 3
((attempts++))
done
if [ $attempts -eq $MAX_ATTEMPTS ]; then
warning "⚠️ Algunos servicios pueden no estar completamente listos aún"
log "📊 Estado final de servicios:"
check_api_accessible
check_frontend_accessible
check_db_connection
fi
else
error "❌ Fallo al iniciar la aplicación"
log "🔍 Verificando logs de Docker para más detalles..."
docker compose logs --tail=20
return 1
fi
}
# Función para detener aplicación
stop_app() {
log "🛑 Deteniendo aplicación DTIC Bitácoras..."
if ! check_app_running; then
warning "La aplicación no está ejecutándose"
return 0
fi
log "🐳 Ejecutando 'docker compose down'..."
if docker compose down; then
success "Aplicación detenida"
# Cleanup automático después de detener
cleanup_resources
else
error "❌ Fallo al detener la aplicación"
log "🔍 Verificando estado actual de contenedores..."
docker compose ps
return 1
fi
}
# Función para cleanup de recursos
cleanup_resources() {
log "🧹 Realizando limpieza automática de recursos..."
# Limpiar contenedores detenidos
log "🗑️ Limpiando contenedores detenidos..."
if docker container prune -f >/dev/null 2>&1; then
log "✅ Contenedores huérfanos limpiados"
else
log "⚠️ No se pudieron limpiar contenedores huérfanos"
fi
# Limpiar imágenes no utilizadas (opcional, solo si hay muchas)
# docker image prune -f >/dev/null 2>&1
# Limpiar volúmenes huérfanos (con cuidado)
log "🗂️ Limpiando volúmenes huérfanos..."
if docker volume prune -f >/dev/null 2>&1; then
log "✅ Volúmenes huérfanos limpiados"
else
log "⚠️ No se pudieron limpiar volúmenes huérfanos"
fi
}
# Función para crear backup de la base de datos
backup_database() {
log "💾 Iniciando proceso de backup de base de datos..."
# Verificar que la aplicación esté ejecutándose
if ! check_app_running; then
error "❌ La aplicación no está ejecutándose. Inicia la aplicación antes de hacer backup."
return 1
fi
# Crear directorio de backups si no existe
log "📁 Verificando directorio de backups: $BACKUP_DIR"
mkdir -p "$BACKUP_DIR"
if [ ! -d "$BACKUP_DIR" ]; then
error "❌ No se pudo crear el directorio de backups: $BACKUP_DIR"
return 1
fi
# Generar nombre del archivo de backup con timestamp
local backup_filename
backup_filename=$(date +"$BACKUP_FORMAT")
local backup_path="$BACKUP_DIR/$backup_filename"
log "📄 Archivo de backup: $backup_path"
# Verificar conexión a PostgreSQL
if ! check_db_connection; then
error "❌ No se puede conectar a la base de datos. Verifica que PostgreSQL esté funcionando."
return 1
fi
# Obtener credenciales de la base de datos desde docker-compose
local db_host="localhost"
local db_port=$DB_PORT
local db_name="dtic_bitacoras"
local db_user="dtic_user"
local db_password="dtic_password"
# Verificar si hay variables de entorno en el archivo .env
if [ -f "backend/.env" ]; then
source backend/.env 2>/dev/null || true
fi
log "🔐 Conectando a PostgreSQL para crear backup..."
log "📡 Host: $db_host:$db_port"
log "🗄️ Base de datos: $db_name"
log "👤 Usuario: $db_user"
# Verificar si psql está disponible localmente
local use_docker_psql=false
if ! command -v psql &> /dev/null; then
log "⚠️ psql no está disponible localmente, usando Docker container..."
use_docker_psql=true
fi
# Crear el backup usando pg_dump
log "⏳ Ejecutando pg_dump..."
local backup_success=false
if [ "$use_docker_psql" = true ]; then
# Usar psql desde el contenedor de PostgreSQL
log "🐳 Usando PostgreSQL client desde Docker container..."
# Crear el backup dentro del contenedor y copiarlo al host
local temp_backup_name="temp_backup_$(date +%s).sql"
if docker exec -e PGPASSWORD="$db_password" dtic_bitacoras_postgres pg_dump -h localhost -p 5432 -U "$db_user" -d "$db_name" -f "/tmp/$temp_backup_name"; then
log "📁 Copiando backup desde contenedor al host..."
if docker cp dtic_bitacoras_postgres:/tmp/"$temp_backup_name" "$backup_path"; then
# Limpiar el archivo temporal del contenedor
docker exec dtic_bitacoras_postgres rm -f "/tmp/$temp_backup_name"
backup_success=true
else
error "❌ Error al copiar el backup desde el contenedor"
fi
else
error "❌ Error al crear el backup dentro del contenedor"
fi
else
# Usar psql local
log "💻 Usando PostgreSQL client local..."
if PGPASSWORD="$db_password" pg_dump -h "$db_host" -p "$db_port" -U "$db_user" -d "$db_name" -f "$backup_path"; then
backup_success=true
fi
fi
if [ "$backup_success" = true ]; then
success "✅ Backup creado exitosamente: $backup_path"
# Verificar que el archivo se creó y tiene contenido
if [ -f "$backup_path" ] && [ -s "$backup_path" ]; then
local file_size
file_size=$(du -h "$backup_path" | cut -f1)
log "📊 Tamaño del backup: $file_size"
# Mostrar información adicional del backup
log "🔍 Verificando integridad del backup..."
local line_count
line_count=$(wc -l < "$backup_path")
log "📋 Líneas en el backup: $line_count"
if [ $line_count -gt 10 ]; then
success "✅ Backup verificado correctamente"
else
warning "⚠️ El backup parece tener pocas líneas, pero se creó exitosamente"
fi
return 0
else
error "❌ El archivo de backup se creó pero está vacío o no existe"
return 1
fi
else
error "❌ Error al crear el backup. Verifica la conectividad y credenciales de la base de datos."
# Limpiar archivo de backup parcial si existe
if [ -f "$backup_path" ]; then
rm -f "$backup_path"
log "🗑️ Archivo de backup parcial eliminado"
fi
return 1
fi
}
# Función para restaurar base de datos desde backup
restore_database() {
log "💾 Iniciando proceso de restauración de base de datos..."
# Verificar que la aplicación esté ejecutándose
if ! check_app_running; then
error "❌ La aplicación no está ejecutándose. Inicia la aplicación antes de restaurar."
return 1
fi
# Ruta del archivo de backup
local backup_file="backups/dtic_bitacoras_backup_20251107_171026.sql"
# Verificar que el archivo existe
if [ ! -f "$backup_file" ]; then
error "❌ Archivo de backup no encontrado: $backup_file"
return 1
fi
# Verificar conexión a PostgreSQL
if ! check_db_connection; then
error "❌ No se puede conectar a la base de datos. Verifica que PostgreSQL esté funcionando."
return 1
fi
# Obtener credenciales de la base de datos
local db_name="dtic_bitacoras"
local db_user="dtic_user"
local db_password="dtic_password"
log "🔐 Conectando a PostgreSQL para restaurar..."
log "📄 Archivo de backup: $backup_file"
log "🗄️ Base de datos: $db_name"
log "👤 Usuario: $db_user"
# Copiar archivo de backup al contenedor
local temp_backup_name="restore_backup.sql"
log "📁 Copiando archivo de backup al contenedor..."
if ! docker cp "$backup_file" dtic_bitacoras_postgres:/tmp/"$temp_backup_name"; then
error "❌ Error al copiar el archivo de backup al contenedor"
return 1
fi
# Preparar base de datos para restauración (drop y recreate)
log "🗄️ Preparando base de datos para restauración..."
if ! docker exec -e PGPASSWORD="$db_password" dtic_bitacoras_postgres psql -h localhost -p 5432 -U "$db_user" -d postgres -c "DROP DATABASE IF EXISTS $db_name;"; then
error "❌ Error al eliminar la base de datos existente"
# Limpiar archivo temporal
docker exec dtic_bitacoras_postgres rm -f "/tmp/$temp_backup_name" 2>/dev/null || true
return 1
fi
if ! docker exec -e PGPASSWORD="$db_password" dtic_bitacoras_postgres psql -h localhost -p 5432 -U "$db_user" -d postgres -c "CREATE DATABASE $db_name;"; then
error "❌ Error al crear la base de datos"
# Limpiar archivo temporal
docker exec dtic_bitacoras_postgres rm -f "/tmp/$temp_backup_name" 2>/dev/null || true
return 1
fi
# Ejecutar restauración
log "⏳ Ejecutando restauración desde backup..."
if docker exec -e PGPASSWORD="$db_password" dtic_bitacoras_postgres psql -h localhost -p 5432 -U "$db_user" -d "$db_name" -f "/tmp/$temp_backup_name"; then
success "✅ Restauración completada exitosamente"
# Verificar que la restauración fue exitosa
log "🔍 Verificando restauración..."
if docker exec -e PGPASSWORD="$db_password" dtic_bitacoras_postgres psql -h localhost -p 5432 -U "$db_user" -d "$db_name" -c "SELECT 1;" &>/dev/null; then
success "✅ Base de datos restaurada y verificada correctamente"
else
warning "⚠️ La restauración se completó pero la verificación falló"
fi
# Limpiar archivo temporal
docker exec dtic_bitacoras_postgres rm -f "/tmp/$temp_backup_name"
return 0
else
error "❌ Error durante la restauración"
# Limpiar archivo temporal
docker exec dtic_bitacoras_postgres rm -f "/tmp/$temp_backup_name"
return 1
fi
}
# Función para reiniciar aplicación
restart_app() {
log "🔄 Reiniciando aplicación DTIC Bitácoras..."
if ! check_app_running; then
warning "La aplicación no está ejecutándose. Iniciándola..."
start_app
return $?
fi
log "🐳 Ejecutando 'docker compose restart'..."
if docker compose restart; then
success "Aplicación reiniciada"
# Verificar que esté funcionando después del reinicio
log "⏳ Verificando servicios después del reinicio..."
sleep 3
if check_api_accessible && check_frontend_accessible; then
success "✅ Servicios verificados después del reinicio"
else
warning "⚠️ Algunos servicios pueden tardar en estar listos"
log "📊 Estado de servicios post-reinicio:"
check_api_accessible
check_frontend_accessible
fi
else
error "❌ Fallo al reiniciar la aplicación"
log "🔍 Verificando logs de reinicio..."
docker compose logs --tail=10
return 1
fi
}
# Función para mostrar estado detallado
show_detailed_status() {
echo ""
echo "📊 Estado Detallado del Sistema:"
echo "==============================="
echo "🐳 Contenedores Docker:"
docker compose ps
echo ""
if check_app_running; then
echo "🔧 API Health Check:"
if check_api_accessible; then
curl -s "$API_URL/health" | jq . 2>/dev/null || curl -s "$API_URL/health"
else
echo -e "${RED}❌ API no accesible${NC}"
fi
echo ""
echo "🌐 Frontend Status:"
if check_frontend_accessible; then
echo -e "${GREEN}✅ Frontend accesible${NC}"
else
echo -e "${RED}❌ Frontend no accesible${NC}"
fi
echo ""
echo "🗄️ Base de Datos:"
if check_db_connection; then
echo -e "${GREEN}✅ Conexión exitosa a PostgreSQL${NC}"
# Mostrar información básica de la BD
if command -v psql &> /dev/null; then
echo "Tablas en la base de datos:"
PGPASSWORD=dtic_password psql -h localhost -p $DB_PORT -U dtic_user -d dtic_bitacoras -c "\dt" 2>/dev/null | head -10
fi
else
echo -e "${RED}❌ No se puede conectar a PostgreSQL${NC}"
fi
echo ""
fi
}
# Función para mostrar URLs de acceso
show_access_urls() {
echo ""
echo "🌐 URLs de Acceso:"
echo "================="
if check_api_accessible; then
echo -e "🔧 API: ${GREEN}$API_URL${NC}"
echo -e " Health Check: ${GREEN}$API_URL/health${NC}"
else
echo -e "🔧 API: ${RED}$API_URL${NC} (no accesible)"
fi
if check_frontend_accessible; then
echo -e "🌐 Frontend: ${GREEN}$FRONTEND_URL${NC}"
else
echo -e "🌐 Frontend: ${RED}$FRONTEND_URL${NC} (no accesible)"
fi
echo ""
echo -e "${BLUE}💡 Para acceder a la aplicación, use la URL del Frontend en su navegador${NC}"
}
# Función para procesar parámetros de línea de comandos
parse_command() {
case "$1" in
start)
INTERACTIVE_MODE=false
COMMAND="start"
;;
stop)
INTERACTIVE_MODE=false
COMMAND="stop"
;;
restart)
INTERACTIVE_MODE=false
COMMAND="restart"
;;
status)
INTERACTIVE_MODE=false
COMMAND="status"
;;
bd-backup)
INTERACTIVE_MODE=false
COMMAND="backup"
;;
bd-restore)
INTERACTIVE_MODE=false
COMMAND="restore"
;;
*)
INTERACTIVE_MODE=true
;;
esac
}
# Función principal
main() {
# Ejecutar configuración inicial solo en la primera ejecución
if is_first_run; then
"$SCRIPT_DIR/app-run_deps.sh" initial-setup || exit 1
fi
# Procesar parámetros de línea de comandos
parse_command "$1"
if [ "$INTERACTIVE_MODE" = false ]; then
# Modo no interactivo
case "$COMMAND" in
start)
"$SCRIPT_DIR/app-run_deps.sh" check-docker-deps || exit 1
start_app
;;
stop)
"$SCRIPT_DIR/app-run_deps.sh" check-docker-deps || exit 1
stop_app
;;
restart)
"$SCRIPT_DIR/app-run_deps.sh" check-docker-deps || exit 1
restart_app
;;
status)
"$SCRIPT_DIR/app-run_deps.sh" check-docker-deps || exit 1
show_status
show_access_urls
;;
backup)
"$SCRIPT_DIR/app-run_deps.sh" check-docker-deps || exit 1
backup_database
;;
restore)
"$SCRIPT_DIR/app-run_deps.sh" check-docker-deps || exit 1
restore_database
;;
esac
else
# Modo interactivo (comportamiento original)
echo ""
echo "🚀 DTIC Bitácoras - Gestor Inteligente"
echo "====================================="
echo ""
# Mostrar estado inicial
show_status
# Bucle principal
while true; do
show_menu
# Determinar rango de opciones válido
local max_option
if check_app_running; then
max_option=6 # 1:detener, 2:reiniciar, 3:backup, 4:restore, 5:estado, 6:salir
read -p "Seleccione una opción (1-6): " choice
else
max_option=5 # 1:iniciar, 2:backup, 3:restore, 4:estado, 5:salir
read -p "Seleccione una opción (1-5): " choice
fi
case $choice in
1)
if check_app_running; then
stop_app
else
start_app
fi
echo ""
read -p "Presione Enter para continuar..."
;;
2)
if check_app_running; then
restart_app
else
backup_database
fi
echo ""
read -p "Presione Enter para continuar..."
;;
3)
if check_app_running; then
backup_database
else
restore_database
fi
echo ""
read -p "Presione Enter para continuar..."
;;
4)
if check_app_running; then
restore_database
else
show_detailed_status
fi
echo ""
read -p "Presione Enter para continuar..."
;;
5)
if check_app_running; then
show_detailed_status
else
echo ""
log "¡Hasta luego!"
break
fi
echo ""
read -p "Presione Enter para continuar..."
;;
6)
if check_app_running; then
echo ""
log "¡Hasta luego!"
break
else
error "Opción inválida."
sleep 2
fi
;;
*)
error "Opción inválida."
sleep 2
;;
esac
# Mostrar estado actualizado y URLs después de cada acción
show_status
show_access_urls
done
fi
}
# Verificar dependencias antes de continuar
"$SCRIPT_DIR/app-run_deps.sh" check-docker-deps || exit 1
# Verificar que estamos en el directorio correcto
if [ ! -f "docker-compose.yml" ]; then
error "No se encuentra docker-compose.yml. Asegúrese de ejecutar este script desde el directorio _app-bitacoras"
exit 1
fi
# Ejecutar función principal con parámetros
main "$@"
+249
View File
@@ -0,0 +1,249 @@
#!/bin/bash
# =============================================================================
# DTIC Bitácoras - Gestión de Dependencias
# =============================================================================
#
# Script modular para gestión de dependencias del sistema
# Actúa como API: recibe argumentos CLI y retorna códigos de salida
#
# Uso:
# ./app-run_deps.sh check-host-deps # Verifica dependencias del host
# ./app-run_deps.sh install-host-deps # Instala dependencias del host
# ./app-run_deps.sh check-docker-deps # Verifica dependencias Docker
# ./app-run_deps.sh initial-setup # Ejecuta configuración inicial
#
# Códigos de salida:
# 0: Éxito
# 1: Fallo
#
# Versión: 1.0
# Fecha: 2025-11-28
# =============================================================================
# Cargar biblioteca compartida
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/app-run_lib.sh"
# Dependencias del host con sus comandos de instalación por sistema operativo
declare -A HOST_DEPENDENCIES=(
[curl]="Utilizado para verificar conectividad de servicios"
[jq]="Utilizado para formatear respuestas JSON (opcional)"
)
declare -A INSTALL_COMMANDS_LINUX=(
[curl]="apt-get install -y curl"
[jq]="apt-get install -y jq"
)
declare -A INSTALL_COMMANDS_MACOS=(
[curl]="brew install curl"
[jq]="brew install jq"
)
# Función para obtener el gestor de paquetes del sistema
get_package_manager() {
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
if command -v apt-get &> /dev/null; then
echo "apt-get"
elif command -v yum &> /dev/null; then
echo "yum"
elif command -v dnf &> /dev/null; then
echo "dnf"
else
echo "none"
fi
elif [[ "$OSTYPE" == "darwin"* ]]; then
if command -v brew &> /dev/null; then
echo "brew"
else
echo "none"
fi
else
echo "unsupported"
fi
}
# Función para verificar dependencias del host
check_host_dependencies() {
log "🔍 Verificando dependencias del sistema host..."
local missing_deps=()
for dep in "${!HOST_DEPENDENCIES[@]}"; do
if ! command -v "$dep" &> /dev/null; then
missing_deps+=("$dep")
fi
done
if [ ${#missing_deps[@]} -eq 0 ]; then
log "✅ Dependencias del host verificadas correctamente"
return 0
else
log "⚠️ Dependencias faltantes detectadas: ${missing_deps[*]}"
return 1
fi
}
# Función para instalar dependencias automáticamente
install_host_dependencies() {
log "🛠️ Instalando dependencias del sistema host..."
local package_manager=$(get_package_manager)
case "$package_manager" in
"apt-get"|"yum"|"dnf")
sudo "$package_manager" update
;;
"brew")
# brew no necesita update para install
;;
"none")
error "❌ No se encontró un gestor de paquetes compatible"
return 1
;;
"unsupported")
error "❌ Sistema operativo no soportado para instalación automática"
return 1
;;
esac
for dep in "${!HOST_DEPENDENCIES[@]}"; do
if ! command -v "$dep" &> /dev/null; then
log "📦 Instalando $dep..."
case "$package_manager" in
"apt-get")
sudo apt-get install -y "$dep"
;;
"yum")
sudo yum install -y "$dep"
;;
"dnf")
sudo dnf install -y "$dep"
;;
"brew")
brew install "$dep"
;;
*)
error "❌ No se puede instalar $dep: $package_manager no soportado"
continue
;;
esac
if command -v "$dep" &> /dev/null; then
success "$dep instalado correctamente"
else
error "❌ Error al instalar $dep"
fi
fi
done
return 0
}
# Función para verificar dependencias Docker
check_docker_dependencies() {
log "🔍 Verificando dependencias del sistema..."
local missing_deps=()
if ! command -v docker &> /dev/null; then
missing_deps+=("docker")
fi
if ! command -v docker &> /dev/null || ! docker compose version &> /dev/null; then
missing_deps+=("docker-compose")
fi
if [ ${#missing_deps[@]} -ne 0 ]; then
error "Dependencias faltantes: ${missing_deps[*]}"
error "Por favor instala las dependencias requeridas antes de continuar"
return 1
fi
# Verificar que Docker esté ejecutándose
log "🔍 Verificando que Docker daemon esté ejecutándose..."
if ! docker info &> /dev/null; then
error "Docker daemon no está ejecutándose"
error "Por favor inicia Docker y vuelve a intentar"
return 1
fi
# Verificar que docker-compose funcione
log "🔍 Verificando funcionalidad de docker-compose..."
if ! docker compose version &> /dev/null; then
error "docker-compose no funciona correctamente"
return 1
fi
log "✅ Todas las dependencias verificadas correctamente"
return 0
}
# Función para ejecutar configuración inicial
run_initial_setup() {
echo ""
echo "🚀 Configuración Inicial de DTIC Bitácoras"
echo "========================================="
echo ""
log "🔧 Esta es la primera vez que ejecutas el script en este sistema"
log "🛠️ Se verificarán e instalarán las dependencias necesarias"
echo ""
# Verificar dependencias del host
if ! check_host_dependencies; then
echo ""
warning "⚠️ Se detectaron dependencias faltantes en el sistema host:"
echo ""
echo "Dependencias que se pueden instalar automáticamente:"
for dep in "${!HOST_DEPENDENCIES[@]}"; do
echo "$dep - ${HOST_DEPENDENCIES[$dep]}"
done
echo ""
echo "Sistemas soportados:"
echo " • Linux (Ubuntu/Debian, CentOS/RHEL, Fedora)"
echo " • macOS (con Homebrew)"
echo ""
# En modo API, siempre intentar instalar automáticamente
log "Ejecutando instalación automática de dependencias..."
if install_host_dependencies; then
success "✅ Dependencias instaladas correctamente"
else
error "❌ Error al instalar algunas dependencias"
echo ""
echo "Puedes instalar manualmente en:"
echo " • curl: https://curl.se/download.html"
echo " • jq: https://stedolan.github.io/jq/download/"
return 1
fi
else
log "✅ Todas las dependencias ya están instaladas"
fi
# Marcar configuración como completada
mark_setup_complete
echo ""
success "🎉 Configuración inicial completada"
echo ""
sleep 2
return 0
}
# Procesar argumentos CLI
case "$1" in
check-host-deps)
check_host_dependencies
;;
install-host-deps)
install_host_dependencies
;;
check-docker-deps)
check_docker_dependencies
;;
initial-setup)
run_initial_setup
;;
*)
error "Uso: $0 {check-host-deps|install-host-deps|check-docker-deps|initial-setup}"
exit 1
;;
esac
+38
View File
@@ -0,0 +1,38 @@
#!/bin/bash
# =============================================================================
# DTIC Bitácoras - Biblioteca de Funciones Compartidas
# =============================================================================
#
# Biblioteca de funciones reutilizables para scripts de gestión de aplicación
#
# Versión: 1.0
# Fecha: 2025-11-28
# =============================================================================
# Colores para salida
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
# Archivo para recordar si ya se ejecutó la configuración inicial
SETUP_MARKER=".dtic_setup_done"
# Funciones de logging
log() { echo -e "${BLUE}[INFO]${NC} $1"; }
success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
error() { echo -e "${RED}[ERROR]${NC} $1"; }
warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; }
# Función para verificar si es la primera ejecución
is_first_run() {
[ ! -f "$SETUP_MARKER" ]
}
# Función para marcar que la configuración inicial se completó
mark_setup_complete() {
touch "$SETUP_MARKER"
log "📝 Configuración inicial completada"
}
+25
View File
@@ -0,0 +1,25 @@
FROM node:18-alpine
# Instalar Docker CLI para poder ejecutar comandos Docker desde el contenedor
RUN apk add --no-cache docker-cli
# Establecer directorio de trabajo
WORKDIR /app
# Copiar archivos de configuración de paquetes
COPY package*.json ./
# Instalar dependencias
RUN npm install --omit=dev
# Copiar código fuente
COPY . .
# Crear directorio para logs
RUN mkdir -p logs
# Exponer puerto
EXPOSE 3001
# Comando para ejecutar la aplicación
CMD ["npm", "start"]
+1
View File
@@ -0,0 +1 @@
../baseline-browser-mapping/dist/cli.js
+1
View File
@@ -0,0 +1 @@
../browserslist/cli.js
+1
View File
@@ -0,0 +1 @@
../create-jest/bin/create-jest.js
+1
View File
@@ -0,0 +1 @@
../esprima/bin/esparse.js
+1
View File
@@ -0,0 +1 @@
../esprima/bin/esvalidate.js
+1
View File
@@ -0,0 +1 @@
../import-local/fixtures/cli.js
+1
View File
@@ -0,0 +1 @@
../jest/bin/jest.js
+1
View File
@@ -0,0 +1 @@
../js-yaml/bin/js-yaml.js
+1
View File
@@ -0,0 +1 @@
../jsesc/bin/jsesc
+1
View File
@@ -0,0 +1 @@
../json5/lib/cli.js
+1
View File
@@ -0,0 +1 @@
../mime/cli.js
+1
View File
@@ -0,0 +1 @@
../mkdirp/bin/cmd.js
+1
View File
@@ -0,0 +1 @@
../which/bin/node-which
+1
View File
@@ -0,0 +1 @@
../nodemon/bin/nodemon.js
+1
View File
@@ -0,0 +1 @@
../touch/bin/nodetouch.js
+1
View File
@@ -0,0 +1 @@
../@babel/parser/bin/babel-parser.js
+1
View File
@@ -0,0 +1 @@
../resolve/bin/resolve
+1
View File
@@ -0,0 +1 @@
../semver/bin/semver.js
+1
View File
@@ -0,0 +1 @@
../update-browserslist-db/cli.js
File diff suppressed because it is too large Load Diff
+22
View File
@@ -0,0 +1,22 @@
MIT License
Copyright (c) 2014-present Sebastian McKenzie and other contributors
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+19
View File
@@ -0,0 +1,19 @@
# @babel/code-frame
> Generate errors that contain a code frame that point to source locations.
See our website [@babel/code-frame](https://babeljs.io/docs/babel-code-frame) for more information.
## Install
Using npm:
```sh
npm install --save-dev @babel/code-frame
```
or using yarn:
```sh
yarn add @babel/code-frame --dev
```
+216
View File
@@ -0,0 +1,216 @@
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var picocolors = require('picocolors');
var jsTokens = require('js-tokens');
var helperValidatorIdentifier = require('@babel/helper-validator-identifier');
function isColorSupported() {
return (typeof process === "object" && (process.env.FORCE_COLOR === "0" || process.env.FORCE_COLOR === "false") ? false : picocolors.isColorSupported
);
}
const compose = (f, g) => v => f(g(v));
function buildDefs(colors) {
return {
keyword: colors.cyan,
capitalized: colors.yellow,
jsxIdentifier: colors.yellow,
punctuator: colors.yellow,
number: colors.magenta,
string: colors.green,
regex: colors.magenta,
comment: colors.gray,
invalid: compose(compose(colors.white, colors.bgRed), colors.bold),
gutter: colors.gray,
marker: compose(colors.red, colors.bold),
message: compose(colors.red, colors.bold),
reset: colors.reset
};
}
const defsOn = buildDefs(picocolors.createColors(true));
const defsOff = buildDefs(picocolors.createColors(false));
function getDefs(enabled) {
return enabled ? defsOn : defsOff;
}
const sometimesKeywords = new Set(["as", "async", "from", "get", "of", "set"]);
const NEWLINE$1 = /\r\n|[\n\r\u2028\u2029]/;
const BRACKET = /^[()[\]{}]$/;
let tokenize;
{
const JSX_TAG = /^[a-z][\w-]*$/i;
const getTokenType = function (token, offset, text) {
if (token.type === "name") {
if (helperValidatorIdentifier.isKeyword(token.value) || helperValidatorIdentifier.isStrictReservedWord(token.value, true) || sometimesKeywords.has(token.value)) {
return "keyword";
}
if (JSX_TAG.test(token.value) && (text[offset - 1] === "<" || text.slice(offset - 2, offset) === "</")) {
return "jsxIdentifier";
}
if (token.value[0] !== token.value[0].toLowerCase()) {
return "capitalized";
}
}
if (token.type === "punctuator" && BRACKET.test(token.value)) {
return "bracket";
}
if (token.type === "invalid" && (token.value === "@" || token.value === "#")) {
return "punctuator";
}
return token.type;
};
tokenize = function* (text) {
let match;
while (match = jsTokens.default.exec(text)) {
const token = jsTokens.matchToToken(match);
yield {
type: getTokenType(token, match.index, text),
value: token.value
};
}
};
}
function highlight(text) {
if (text === "") return "";
const defs = getDefs(true);
let highlighted = "";
for (const {
type,
value
} of tokenize(text)) {
if (type in defs) {
highlighted += value.split(NEWLINE$1).map(str => defs[type](str)).join("\n");
} else {
highlighted += value;
}
}
return highlighted;
}
let deprecationWarningShown = false;
const NEWLINE = /\r\n|[\n\r\u2028\u2029]/;
function getMarkerLines(loc, source, opts) {
const startLoc = Object.assign({
column: 0,
line: -1
}, loc.start);
const endLoc = Object.assign({}, startLoc, loc.end);
const {
linesAbove = 2,
linesBelow = 3
} = opts || {};
const startLine = startLoc.line;
const startColumn = startLoc.column;
const endLine = endLoc.line;
const endColumn = endLoc.column;
let start = Math.max(startLine - (linesAbove + 1), 0);
let end = Math.min(source.length, endLine + linesBelow);
if (startLine === -1) {
start = 0;
}
if (endLine === -1) {
end = source.length;
}
const lineDiff = endLine - startLine;
const markerLines = {};
if (lineDiff) {
for (let i = 0; i <= lineDiff; i++) {
const lineNumber = i + startLine;
if (!startColumn) {
markerLines[lineNumber] = true;
} else if (i === 0) {
const sourceLength = source[lineNumber - 1].length;
markerLines[lineNumber] = [startColumn, sourceLength - startColumn + 1];
} else if (i === lineDiff) {
markerLines[lineNumber] = [0, endColumn];
} else {
const sourceLength = source[lineNumber - i].length;
markerLines[lineNumber] = [0, sourceLength];
}
}
} else {
if (startColumn === endColumn) {
if (startColumn) {
markerLines[startLine] = [startColumn, 0];
} else {
markerLines[startLine] = true;
}
} else {
markerLines[startLine] = [startColumn, endColumn - startColumn];
}
}
return {
start,
end,
markerLines
};
}
function codeFrameColumns(rawLines, loc, opts = {}) {
const shouldHighlight = opts.forceColor || isColorSupported() && opts.highlightCode;
const defs = getDefs(shouldHighlight);
const lines = rawLines.split(NEWLINE);
const {
start,
end,
markerLines
} = getMarkerLines(loc, lines, opts);
const hasColumns = loc.start && typeof loc.start.column === "number";
const numberMaxWidth = String(end).length;
const highlightedLines = shouldHighlight ? highlight(rawLines) : rawLines;
let frame = highlightedLines.split(NEWLINE, end).slice(start, end).map((line, index) => {
const number = start + 1 + index;
const paddedNumber = ` ${number}`.slice(-numberMaxWidth);
const gutter = ` ${paddedNumber} |`;
const hasMarker = markerLines[number];
const lastMarkerLine = !markerLines[number + 1];
if (hasMarker) {
let markerLine = "";
if (Array.isArray(hasMarker)) {
const markerSpacing = line.slice(0, Math.max(hasMarker[0] - 1, 0)).replace(/[^\t]/g, " ");
const numberOfMarkers = hasMarker[1] || 1;
markerLine = ["\n ", defs.gutter(gutter.replace(/\d/g, " ")), " ", markerSpacing, defs.marker("^").repeat(numberOfMarkers)].join("");
if (lastMarkerLine && opts.message) {
markerLine += " " + defs.message(opts.message);
}
}
return [defs.marker(">"), defs.gutter(gutter), line.length > 0 ? ` ${line}` : "", markerLine].join("");
} else {
return ` ${defs.gutter(gutter)}${line.length > 0 ? ` ${line}` : ""}`;
}
}).join("\n");
if (opts.message && !hasColumns) {
frame = `${" ".repeat(numberMaxWidth + 1)}${opts.message}\n${frame}`;
}
if (shouldHighlight) {
return defs.reset(frame);
} else {
return frame;
}
}
function index (rawLines, lineNumber, colNumber, opts = {}) {
if (!deprecationWarningShown) {
deprecationWarningShown = true;
const message = "Passing lineNumber and colNumber is deprecated to @babel/code-frame. Please use `codeFrameColumns`.";
if (process.emitWarning) {
process.emitWarning(message, "DeprecationWarning");
} else {
const deprecationError = new Error(message);
deprecationError.name = "DeprecationWarning";
console.warn(new Error(message));
}
}
colNumber = Math.max(colNumber, 0);
const location = {
start: {
column: colNumber,
line: lineNumber
}
};
return codeFrameColumns(rawLines, location, opts);
}
exports.codeFrameColumns = codeFrameColumns;
exports.default = index;
exports.highlight = highlight;
//# sourceMappingURL=index.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,31 @@
{
"name": "@babel/code-frame",
"version": "7.27.1",
"description": "Generate errors that contain a code frame that point to source locations.",
"author": "The Babel Team (https://babel.dev/team)",
"homepage": "https://babel.dev/docs/en/next/babel-code-frame",
"bugs": "https://github.com/babel/babel/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen",
"license": "MIT",
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "https://github.com/babel/babel.git",
"directory": "packages/babel-code-frame"
},
"main": "./lib/index.js",
"dependencies": {
"@babel/helper-validator-identifier": "^7.27.1",
"js-tokens": "^4.0.0",
"picocolors": "^1.1.1"
},
"devDependencies": {
"import-meta-resolve": "^4.1.0",
"strip-ansi": "^4.0.0"
},
"engines": {
"node": ">=6.9.0"
},
"type": "commonjs"
}
+22
View File
@@ -0,0 +1,22 @@
MIT License
Copyright (c) 2014-present Sebastian McKenzie and other contributors
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+19
View File
@@ -0,0 +1,19 @@
# @babel/compat-data
> The compat-data to determine required Babel plugins
See our website [@babel/compat-data](https://babeljs.io/docs/babel-compat-data) for more information.
## Install
Using npm:
```sh
npm install --save @babel/compat-data
```
or using yarn:
```sh
yarn add @babel/compat-data
```
@@ -0,0 +1,2 @@
// Todo (Babel 8): remove this file as Babel 8 drop support of core-js 2
module.exports = require("./data/corejs2-built-ins.json");
@@ -0,0 +1,2 @@
// Todo (Babel 8): remove this file now that it is included in babel-plugin-polyfill-corejs3
module.exports = require("./data/corejs3-shipped-proposals.json");
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,5 @@
[
"esnext.promise.all-settled",
"esnext.string.match-all",
"esnext.global-this"
]
@@ -0,0 +1,18 @@
{
"es6.module": {
"chrome": "61",
"and_chr": "61",
"edge": "16",
"firefox": "60",
"and_ff": "60",
"node": "13.2.0",
"opera": "48",
"op_mob": "45",
"safari": "10.1",
"ios": "10.3",
"samsung": "8.2",
"android": "61",
"electron": "2.0",
"ios_saf": "10.3"
}
}
@@ -0,0 +1,35 @@
{
"transform-async-to-generator": [
"bugfix/transform-async-arrows-in-class"
],
"transform-parameters": [
"bugfix/transform-edge-default-parameters",
"bugfix/transform-safari-id-destructuring-collision-in-function-expression"
],
"transform-function-name": [
"bugfix/transform-edge-function-name"
],
"transform-block-scoping": [
"bugfix/transform-safari-block-shadowing",
"bugfix/transform-safari-for-shadowing"
],
"transform-template-literals": [
"bugfix/transform-tagged-template-caching"
],
"transform-optional-chaining": [
"bugfix/transform-v8-spread-parameters-in-optional-chaining"
],
"proposal-optional-chaining": [
"bugfix/transform-v8-spread-parameters-in-optional-chaining"
],
"transform-class-properties": [
"bugfix/transform-v8-static-class-fields-redefine-readonly",
"bugfix/transform-firefox-class-in-computed-class-key",
"bugfix/transform-safari-class-field-initializer-scope"
],
"proposal-class-properties": [
"bugfix/transform-v8-static-class-fields-redefine-readonly",
"bugfix/transform-firefox-class-in-computed-class-key",
"bugfix/transform-safari-class-field-initializer-scope"
]
}
@@ -0,0 +1,203 @@
{
"bugfix/transform-async-arrows-in-class": {
"chrome": "55",
"opera": "42",
"edge": "15",
"firefox": "52",
"safari": "11",
"node": "7.6",
"deno": "1",
"ios": "11",
"samsung": "6",
"opera_mobile": "42",
"electron": "1.6"
},
"bugfix/transform-edge-default-parameters": {
"chrome": "49",
"opera": "36",
"edge": "18",
"firefox": "52",
"safari": "10",
"node": "6",
"deno": "1",
"ios": "10",
"samsung": "5",
"opera_mobile": "36",
"electron": "0.37"
},
"bugfix/transform-edge-function-name": {
"chrome": "51",
"opera": "38",
"edge": "79",
"firefox": "53",
"safari": "10",
"node": "6.5",
"deno": "1",
"ios": "10",
"samsung": "5",
"opera_mobile": "41",
"electron": "1.2"
},
"bugfix/transform-safari-block-shadowing": {
"chrome": "49",
"opera": "36",
"edge": "12",
"firefox": "44",
"safari": "11",
"node": "6",
"deno": "1",
"ie": "11",
"ios": "11",
"samsung": "5",
"opera_mobile": "36",
"electron": "0.37"
},
"bugfix/transform-safari-for-shadowing": {
"chrome": "49",
"opera": "36",
"edge": "12",
"firefox": "4",
"safari": "11",
"node": "6",
"deno": "1",
"ie": "11",
"ios": "11",
"samsung": "5",
"rhino": "1.7.13",
"opera_mobile": "36",
"electron": "0.37"
},
"bugfix/transform-safari-id-destructuring-collision-in-function-expression": {
"chrome": "49",
"opera": "36",
"edge": "14",
"firefox": "2",
"safari": "16.3",
"node": "6",
"deno": "1",
"ios": "16.3",
"samsung": "5",
"opera_mobile": "36",
"electron": "0.37"
},
"bugfix/transform-tagged-template-caching": {
"chrome": "41",
"opera": "28",
"edge": "12",
"firefox": "34",
"safari": "13",
"node": "4",
"deno": "1",
"ios": "13",
"samsung": "3.4",
"rhino": "1.7.14",
"opera_mobile": "28",
"electron": "0.21"
},
"bugfix/transform-v8-spread-parameters-in-optional-chaining": {
"chrome": "91",
"opera": "77",
"edge": "91",
"firefox": "74",
"safari": "13.1",
"node": "16.9",
"deno": "1.9",
"ios": "13.4",
"samsung": "16",
"opera_mobile": "64",
"electron": "13.0"
},
"transform-optional-chaining": {
"chrome": "80",
"opera": "67",
"edge": "80",
"firefox": "74",
"safari": "13.1",
"node": "14",
"deno": "1",
"ios": "13.4",
"samsung": "13",
"rhino": "1.8",
"opera_mobile": "57",
"electron": "8.0"
},
"proposal-optional-chaining": {
"chrome": "80",
"opera": "67",
"edge": "80",
"firefox": "74",
"safari": "13.1",
"node": "14",
"deno": "1",
"ios": "13.4",
"samsung": "13",
"rhino": "1.8",
"opera_mobile": "57",
"electron": "8.0"
},
"transform-parameters": {
"chrome": "49",
"opera": "36",
"edge": "15",
"firefox": "52",
"safari": "10",
"node": "6",
"deno": "1",
"ios": "10",
"samsung": "5",
"opera_mobile": "36",
"electron": "0.37"
},
"transform-async-to-generator": {
"chrome": "55",
"opera": "42",
"edge": "15",
"firefox": "52",
"safari": "10.1",
"node": "7.6",
"deno": "1",
"ios": "10.3",
"samsung": "6",
"opera_mobile": "42",
"electron": "1.6"
},
"transform-template-literals": {
"chrome": "41",
"opera": "28",
"edge": "13",
"firefox": "34",
"safari": "9",
"node": "4",
"deno": "1",
"ios": "9",
"samsung": "3.4",
"opera_mobile": "28",
"electron": "0.21"
},
"transform-function-name": {
"chrome": "51",
"opera": "38",
"edge": "14",
"firefox": "53",
"safari": "10",
"node": "6.5",
"deno": "1",
"ios": "10",
"samsung": "5",
"opera_mobile": "41",
"electron": "1.2"
},
"transform-block-scoping": {
"chrome": "50",
"opera": "37",
"edge": "14",
"firefox": "53",
"safari": "10",
"node": "6",
"deno": "1",
"ios": "10",
"samsung": "5",
"opera_mobile": "37",
"electron": "1.1"
}
}
@@ -0,0 +1,838 @@
{
"transform-explicit-resource-management": {
"chrome": "134",
"edge": "134",
"firefox": "141",
"node": "24",
"electron": "35.0"
},
"transform-duplicate-named-capturing-groups-regex": {
"chrome": "126",
"opera": "112",
"edge": "126",
"firefox": "129",
"safari": "17.4",
"node": "23",
"ios": "17.4",
"electron": "31.0"
},
"transform-regexp-modifiers": {
"chrome": "125",
"opera": "111",
"edge": "125",
"firefox": "132",
"node": "23",
"samsung": "27",
"electron": "31.0"
},
"transform-unicode-sets-regex": {
"chrome": "112",
"opera": "98",
"edge": "112",
"firefox": "116",
"safari": "17",
"node": "20",
"deno": "1.32",
"ios": "17",
"samsung": "23",
"opera_mobile": "75",
"electron": "24.0"
},
"bugfix/transform-v8-static-class-fields-redefine-readonly": {
"chrome": "98",
"opera": "84",
"edge": "98",
"firefox": "75",
"safari": "15",
"node": "12",
"deno": "1.18",
"ios": "15",
"samsung": "11",
"opera_mobile": "52",
"electron": "17.0"
},
"bugfix/transform-firefox-class-in-computed-class-key": {
"chrome": "74",
"opera": "62",
"edge": "79",
"firefox": "126",
"safari": "16",
"node": "12",
"deno": "1",
"ios": "16",
"samsung": "11",
"opera_mobile": "53",
"electron": "6.0"
},
"bugfix/transform-safari-class-field-initializer-scope": {
"chrome": "74",
"opera": "62",
"edge": "79",
"firefox": "69",
"safari": "16",
"node": "12",
"deno": "1",
"ios": "16",
"samsung": "11",
"opera_mobile": "53",
"electron": "6.0"
},
"transform-class-static-block": {
"chrome": "94",
"opera": "80",
"edge": "94",
"firefox": "93",
"safari": "16.4",
"node": "16.11",
"deno": "1.14",
"ios": "16.4",
"samsung": "17",
"opera_mobile": "66",
"electron": "15.0"
},
"proposal-class-static-block": {
"chrome": "94",
"opera": "80",
"edge": "94",
"firefox": "93",
"safari": "16.4",
"node": "16.11",
"deno": "1.14",
"ios": "16.4",
"samsung": "17",
"opera_mobile": "66",
"electron": "15.0"
},
"transform-private-property-in-object": {
"chrome": "91",
"opera": "77",
"edge": "91",
"firefox": "90",
"safari": "15",
"node": "16.9",
"deno": "1.9",
"ios": "15",
"samsung": "16",
"opera_mobile": "64",
"electron": "13.0"
},
"proposal-private-property-in-object": {
"chrome": "91",
"opera": "77",
"edge": "91",
"firefox": "90",
"safari": "15",
"node": "16.9",
"deno": "1.9",
"ios": "15",
"samsung": "16",
"opera_mobile": "64",
"electron": "13.0"
},
"transform-class-properties": {
"chrome": "74",
"opera": "62",
"edge": "79",
"firefox": "90",
"safari": "14.1",
"node": "12",
"deno": "1",
"ios": "14.5",
"samsung": "11",
"opera_mobile": "53",
"electron": "6.0"
},
"proposal-class-properties": {
"chrome": "74",
"opera": "62",
"edge": "79",
"firefox": "90",
"safari": "14.1",
"node": "12",
"deno": "1",
"ios": "14.5",
"samsung": "11",
"opera_mobile": "53",
"electron": "6.0"
},
"transform-private-methods": {
"chrome": "84",
"opera": "70",
"edge": "84",
"firefox": "90",
"safari": "15",
"node": "14.6",
"deno": "1",
"ios": "15",
"samsung": "14",
"opera_mobile": "60",
"electron": "10.0"
},
"proposal-private-methods": {
"chrome": "84",
"opera": "70",
"edge": "84",
"firefox": "90",
"safari": "15",
"node": "14.6",
"deno": "1",
"ios": "15",
"samsung": "14",
"opera_mobile": "60",
"electron": "10.0"
},
"transform-numeric-separator": {
"chrome": "75",
"opera": "62",
"edge": "79",
"firefox": "70",
"safari": "13",
"node": "12.5",
"deno": "1",
"ios": "13",
"samsung": "11",
"rhino": "1.7.14",
"opera_mobile": "54",
"electron": "6.0"
},
"proposal-numeric-separator": {
"chrome": "75",
"opera": "62",
"edge": "79",
"firefox": "70",
"safari": "13",
"node": "12.5",
"deno": "1",
"ios": "13",
"samsung": "11",
"rhino": "1.7.14",
"opera_mobile": "54",
"electron": "6.0"
},
"transform-logical-assignment-operators": {
"chrome": "85",
"opera": "71",
"edge": "85",
"firefox": "79",
"safari": "14",
"node": "15",
"deno": "1.2",
"ios": "14",
"samsung": "14",
"opera_mobile": "60",
"electron": "10.0"
},
"proposal-logical-assignment-operators": {
"chrome": "85",
"opera": "71",
"edge": "85",
"firefox": "79",
"safari": "14",
"node": "15",
"deno": "1.2",
"ios": "14",
"samsung": "14",
"opera_mobile": "60",
"electron": "10.0"
},
"transform-nullish-coalescing-operator": {
"chrome": "80",
"opera": "67",
"edge": "80",
"firefox": "72",
"safari": "13.1",
"node": "14",
"deno": "1",
"ios": "13.4",
"samsung": "13",
"rhino": "1.8",
"opera_mobile": "57",
"electron": "8.0"
},
"proposal-nullish-coalescing-operator": {
"chrome": "80",
"opera": "67",
"edge": "80",
"firefox": "72",
"safari": "13.1",
"node": "14",
"deno": "1",
"ios": "13.4",
"samsung": "13",
"rhino": "1.8",
"opera_mobile": "57",
"electron": "8.0"
},
"transform-optional-chaining": {
"chrome": "91",
"opera": "77",
"edge": "91",
"firefox": "74",
"safari": "13.1",
"node": "16.9",
"deno": "1.9",
"ios": "13.4",
"samsung": "16",
"opera_mobile": "64",
"electron": "13.0"
},
"proposal-optional-chaining": {
"chrome": "91",
"opera": "77",
"edge": "91",
"firefox": "74",
"safari": "13.1",
"node": "16.9",
"deno": "1.9",
"ios": "13.4",
"samsung": "16",
"opera_mobile": "64",
"electron": "13.0"
},
"transform-json-strings": {
"chrome": "66",
"opera": "53",
"edge": "79",
"firefox": "62",
"safari": "12",
"node": "10",
"deno": "1",
"ios": "12",
"samsung": "9",
"rhino": "1.7.14",
"opera_mobile": "47",
"electron": "3.0"
},
"proposal-json-strings": {
"chrome": "66",
"opera": "53",
"edge": "79",
"firefox": "62",
"safari": "12",
"node": "10",
"deno": "1",
"ios": "12",
"samsung": "9",
"rhino": "1.7.14",
"opera_mobile": "47",
"electron": "3.0"
},
"transform-optional-catch-binding": {
"chrome": "66",
"opera": "53",
"edge": "79",
"firefox": "58",
"safari": "11.1",
"node": "10",
"deno": "1",
"ios": "11.3",
"samsung": "9",
"opera_mobile": "47",
"electron": "3.0"
},
"proposal-optional-catch-binding": {
"chrome": "66",
"opera": "53",
"edge": "79",
"firefox": "58",
"safari": "11.1",
"node": "10",
"deno": "1",
"ios": "11.3",
"samsung": "9",
"opera_mobile": "47",
"electron": "3.0"
},
"transform-parameters": {
"chrome": "49",
"opera": "36",
"edge": "18",
"firefox": "52",
"safari": "16.3",
"node": "6",
"deno": "1",
"ios": "16.3",
"samsung": "5",
"opera_mobile": "36",
"electron": "0.37"
},
"transform-async-generator-functions": {
"chrome": "63",
"opera": "50",
"edge": "79",
"firefox": "57",
"safari": "12",
"node": "10",
"deno": "1",
"ios": "12",
"samsung": "8",
"opera_mobile": "46",
"electron": "3.0"
},
"proposal-async-generator-functions": {
"chrome": "63",
"opera": "50",
"edge": "79",
"firefox": "57",
"safari": "12",
"node": "10",
"deno": "1",
"ios": "12",
"samsung": "8",
"opera_mobile": "46",
"electron": "3.0"
},
"transform-object-rest-spread": {
"chrome": "60",
"opera": "47",
"edge": "79",
"firefox": "55",
"safari": "11.1",
"node": "8.3",
"deno": "1",
"ios": "11.3",
"samsung": "8",
"opera_mobile": "44",
"electron": "2.0"
},
"proposal-object-rest-spread": {
"chrome": "60",
"opera": "47",
"edge": "79",
"firefox": "55",
"safari": "11.1",
"node": "8.3",
"deno": "1",
"ios": "11.3",
"samsung": "8",
"opera_mobile": "44",
"electron": "2.0"
},
"transform-dotall-regex": {
"chrome": "62",
"opera": "49",
"edge": "79",
"firefox": "78",
"safari": "11.1",
"node": "8.10",
"deno": "1",
"ios": "11.3",
"samsung": "8",
"rhino": "1.7.15",
"opera_mobile": "46",
"electron": "3.0"
},
"transform-unicode-property-regex": {
"chrome": "64",
"opera": "51",
"edge": "79",
"firefox": "78",
"safari": "11.1",
"node": "10",
"deno": "1",
"ios": "11.3",
"samsung": "9",
"opera_mobile": "47",
"electron": "3.0"
},
"proposal-unicode-property-regex": {
"chrome": "64",
"opera": "51",
"edge": "79",
"firefox": "78",
"safari": "11.1",
"node": "10",
"deno": "1",
"ios": "11.3",
"samsung": "9",
"opera_mobile": "47",
"electron": "3.0"
},
"transform-named-capturing-groups-regex": {
"chrome": "64",
"opera": "51",
"edge": "79",
"firefox": "78",
"safari": "11.1",
"node": "10",
"deno": "1",
"ios": "11.3",
"samsung": "9",
"opera_mobile": "47",
"electron": "3.0"
},
"transform-async-to-generator": {
"chrome": "55",
"opera": "42",
"edge": "15",
"firefox": "52",
"safari": "11",
"node": "7.6",
"deno": "1",
"ios": "11",
"samsung": "6",
"opera_mobile": "42",
"electron": "1.6"
},
"transform-exponentiation-operator": {
"chrome": "52",
"opera": "39",
"edge": "14",
"firefox": "52",
"safari": "10.1",
"node": "7",
"deno": "1",
"ios": "10.3",
"samsung": "6",
"rhino": "1.7.14",
"opera_mobile": "41",
"electron": "1.3"
},
"transform-template-literals": {
"chrome": "41",
"opera": "28",
"edge": "13",
"firefox": "34",
"safari": "13",
"node": "4",
"deno": "1",
"ios": "13",
"samsung": "3.4",
"opera_mobile": "28",
"electron": "0.21"
},
"transform-literals": {
"chrome": "44",
"opera": "31",
"edge": "12",
"firefox": "53",
"safari": "9",
"node": "4",
"deno": "1",
"ios": "9",
"samsung": "4",
"rhino": "1.7.15",
"opera_mobile": "32",
"electron": "0.30"
},
"transform-function-name": {
"chrome": "51",
"opera": "38",
"edge": "79",
"firefox": "53",
"safari": "10",
"node": "6.5",
"deno": "1",
"ios": "10",
"samsung": "5",
"opera_mobile": "41",
"electron": "1.2"
},
"transform-arrow-functions": {
"chrome": "47",
"opera": "34",
"edge": "13",
"firefox": "43",
"safari": "10",
"node": "6",
"deno": "1",
"ios": "10",
"samsung": "5",
"rhino": "1.7.13",
"opera_mobile": "34",
"electron": "0.36"
},
"transform-block-scoped-functions": {
"chrome": "41",
"opera": "28",
"edge": "12",
"firefox": "46",
"safari": "10",
"node": "4",
"deno": "1",
"ie": "11",
"ios": "10",
"samsung": "3.4",
"opera_mobile": "28",
"electron": "0.21"
},
"transform-classes": {
"chrome": "46",
"opera": "33",
"edge": "13",
"firefox": "45",
"safari": "10",
"node": "5",
"deno": "1",
"ios": "10",
"samsung": "5",
"opera_mobile": "33",
"electron": "0.36"
},
"transform-object-super": {
"chrome": "46",
"opera": "33",
"edge": "13",
"firefox": "45",
"safari": "10",
"node": "5",
"deno": "1",
"ios": "10",
"samsung": "5",
"opera_mobile": "33",
"electron": "0.36"
},
"transform-shorthand-properties": {
"chrome": "43",
"opera": "30",
"edge": "12",
"firefox": "33",
"safari": "9",
"node": "4",
"deno": "1",
"ios": "9",
"samsung": "4",
"rhino": "1.7.14",
"opera_mobile": "30",
"electron": "0.27"
},
"transform-duplicate-keys": {
"chrome": "42",
"opera": "29",
"edge": "12",
"firefox": "34",
"safari": "9",
"node": "4",
"deno": "1",
"ios": "9",
"samsung": "3.4",
"opera_mobile": "29",
"electron": "0.25"
},
"transform-computed-properties": {
"chrome": "44",
"opera": "31",
"edge": "12",
"firefox": "34",
"safari": "7.1",
"node": "4",
"deno": "1",
"ios": "8",
"samsung": "4",
"rhino": "1.8",
"opera_mobile": "32",
"electron": "0.30"
},
"transform-for-of": {
"chrome": "51",
"opera": "38",
"edge": "15",
"firefox": "53",
"safari": "10",
"node": "6.5",
"deno": "1",
"ios": "10",
"samsung": "5",
"opera_mobile": "41",
"electron": "1.2"
},
"transform-sticky-regex": {
"chrome": "49",
"opera": "36",
"edge": "13",
"firefox": "3",
"safari": "10",
"node": "6",
"deno": "1",
"ios": "10",
"samsung": "5",
"rhino": "1.7.15",
"opera_mobile": "36",
"electron": "0.37"
},
"transform-unicode-escapes": {
"chrome": "44",
"opera": "31",
"edge": "12",
"firefox": "53",
"safari": "9",
"node": "4",
"deno": "1",
"ios": "9",
"samsung": "4",
"rhino": "1.7.15",
"opera_mobile": "32",
"electron": "0.30"
},
"transform-unicode-regex": {
"chrome": "50",
"opera": "37",
"edge": "13",
"firefox": "46",
"safari": "12",
"node": "6",
"deno": "1",
"ios": "12",
"samsung": "5",
"opera_mobile": "37",
"electron": "1.1"
},
"transform-spread": {
"chrome": "46",
"opera": "33",
"edge": "13",
"firefox": "45",
"safari": "10",
"node": "5",
"deno": "1",
"ios": "10",
"samsung": "5",
"opera_mobile": "33",
"electron": "0.36"
},
"transform-destructuring": {
"chrome": "51",
"opera": "38",
"edge": "15",
"firefox": "53",
"safari": "10",
"node": "6.5",
"deno": "1",
"ios": "10",
"samsung": "5",
"opera_mobile": "41",
"electron": "1.2"
},
"transform-block-scoping": {
"chrome": "50",
"opera": "37",
"edge": "14",
"firefox": "53",
"safari": "11",
"node": "6",
"deno": "1",
"ios": "11",
"samsung": "5",
"opera_mobile": "37",
"electron": "1.1"
},
"transform-typeof-symbol": {
"chrome": "48",
"opera": "35",
"edge": "12",
"firefox": "36",
"safari": "9",
"node": "6",
"deno": "1",
"ios": "9",
"samsung": "5",
"rhino": "1.8",
"opera_mobile": "35",
"electron": "0.37"
},
"transform-new-target": {
"chrome": "46",
"opera": "33",
"edge": "14",
"firefox": "41",
"safari": "10",
"node": "5",
"deno": "1",
"ios": "10",
"samsung": "5",
"opera_mobile": "33",
"electron": "0.36"
},
"transform-regenerator": {
"chrome": "50",
"opera": "37",
"edge": "13",
"firefox": "53",
"safari": "10",
"node": "6",
"deno": "1",
"ios": "10",
"samsung": "5",
"opera_mobile": "37",
"electron": "1.1"
},
"transform-member-expression-literals": {
"chrome": "7",
"opera": "12",
"edge": "12",
"firefox": "2",
"safari": "5.1",
"node": "0.4",
"deno": "1",
"ie": "9",
"android": "4",
"ios": "6",
"phantom": "1.9",
"samsung": "1",
"rhino": "1.7.13",
"opera_mobile": "12",
"electron": "0.20"
},
"transform-property-literals": {
"chrome": "7",
"opera": "12",
"edge": "12",
"firefox": "2",
"safari": "5.1",
"node": "0.4",
"deno": "1",
"ie": "9",
"android": "4",
"ios": "6",
"phantom": "1.9",
"samsung": "1",
"rhino": "1.7.13",
"opera_mobile": "12",
"electron": "0.20"
},
"transform-reserved-words": {
"chrome": "13",
"opera": "10.50",
"edge": "12",
"firefox": "2",
"safari": "3.1",
"node": "0.6",
"deno": "1",
"ie": "9",
"android": "4.4",
"ios": "6",
"phantom": "1.9",
"samsung": "1",
"rhino": "1.7.13",
"opera_mobile": "10.1",
"electron": "0.20"
},
"transform-export-namespace-from": {
"chrome": "72",
"deno": "1.0",
"edge": "79",
"firefox": "80",
"node": "13.2.0",
"opera": "60",
"opera_mobile": "51",
"safari": "14.1",
"ios": "14.5",
"samsung": "11.0",
"android": "72",
"electron": "5.0"
},
"proposal-export-namespace-from": {
"chrome": "72",
"deno": "1.0",
"edge": "79",
"firefox": "80",
"node": "13.2.0",
"opera": "60",
"opera_mobile": "51",
"safari": "14.1",
"ios": "14.5",
"samsung": "11.0",
"android": "72",
"electron": "5.0"
}
}
@@ -0,0 +1,2 @@
// Todo (Babel 8): remove this file, in Babel 8 users import the .json directly
module.exports = require("./data/native-modules.json");
@@ -0,0 +1,2 @@
// Todo (Babel 8): remove this file, in Babel 8 users import the .json directly
module.exports = require("./data/overlapping-plugins.json");
@@ -0,0 +1,40 @@
{
"name": "@babel/compat-data",
"version": "7.28.5",
"author": "The Babel Team (https://babel.dev/team)",
"license": "MIT",
"description": "The compat-data to determine required Babel plugins",
"repository": {
"type": "git",
"url": "https://github.com/babel/babel.git",
"directory": "packages/babel-compat-data"
},
"publishConfig": {
"access": "public"
},
"exports": {
"./plugins": "./plugins.js",
"./native-modules": "./native-modules.js",
"./corejs2-built-ins": "./corejs2-built-ins.js",
"./corejs3-shipped-proposals": "./corejs3-shipped-proposals.js",
"./overlapping-plugins": "./overlapping-plugins.js",
"./plugin-bugfixes": "./plugin-bugfixes.js"
},
"scripts": {
"build-data": "./scripts/download-compat-table.sh && node ./scripts/build-data.mjs && node ./scripts/build-modules-support.mjs && node ./scripts/build-bugfixes-targets.mjs"
},
"keywords": [
"babel",
"compat-table",
"compat-data"
],
"devDependencies": {
"@mdn/browser-compat-data": "^6.0.8",
"core-js-compat": "^3.43.0",
"electron-to-chromium": "^1.5.140"
},
"engines": {
"node": ">=6.9.0"
},
"type": "commonjs"
}
@@ -0,0 +1,2 @@
// Todo (Babel 8): remove this file, in Babel 8 users import the .json directly
module.exports = require("./data/plugin-bugfixes.json");
@@ -0,0 +1,2 @@
// Todo (Babel 8): remove this file, in Babel 8 users import the .json directly
module.exports = require("./data/plugins.json");
+22
View File
@@ -0,0 +1,22 @@
MIT License
Copyright (c) 2014-present Sebastian McKenzie and other contributors
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+19
View File
@@ -0,0 +1,19 @@
# @babel/core
> Babel compiler core.
See our website [@babel/core](https://babeljs.io/docs/babel-core) for more information or the [issues](https://github.com/babel/babel/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3A%22pkg%3A%20core%22+is%3Aopen) associated with this package.
## Install
Using npm:
```sh
npm install --save-dev @babel/core
```
or using yarn:
```sh
yarn add @babel/core --dev
```
@@ -0,0 +1,5 @@
"use strict";
0 && 0;
//# sourceMappingURL=cache-contexts.js.map
@@ -0,0 +1 @@
{"version":3,"names":[],"sources":["../../src/config/cache-contexts.ts"],"sourcesContent":["import type { ConfigContext } from \"./config-chain.ts\";\nimport type {\n CallerMetadata,\n TargetsListOrObject,\n} from \"./validation/options.ts\";\n\nexport type { ConfigContext as FullConfig };\n\nexport type FullPreset = {\n targets: TargetsListOrObject;\n} & ConfigContext;\nexport type FullPlugin = {\n assumptions: { [name: string]: boolean };\n} & FullPreset;\n\n// Context not including filename since it is used in places that cannot\n// process 'ignore'/'only' and other filename-based logic.\nexport type SimpleConfig = {\n envName: string;\n caller: CallerMetadata | undefined;\n};\nexport type SimplePreset = {\n targets: TargetsListOrObject;\n} & SimpleConfig;\nexport type SimplePlugin = {\n assumptions: {\n [name: string]: boolean;\n };\n} & SimplePreset;\n"],"mappings":"","ignoreList":[]}
@@ -0,0 +1,261 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.assertSimpleType = assertSimpleType;
exports.makeStrongCache = makeStrongCache;
exports.makeStrongCacheSync = makeStrongCacheSync;
exports.makeWeakCache = makeWeakCache;
exports.makeWeakCacheSync = makeWeakCacheSync;
function _gensync() {
const data = require("gensync");
_gensync = function () {
return data;
};
return data;
}
var _async = require("../gensync-utils/async.js");
var _util = require("./util.js");
const synchronize = gen => {
return _gensync()(gen).sync;
};
function* genTrue() {
return true;
}
function makeWeakCache(handler) {
return makeCachedFunction(WeakMap, handler);
}
function makeWeakCacheSync(handler) {
return synchronize(makeWeakCache(handler));
}
function makeStrongCache(handler) {
return makeCachedFunction(Map, handler);
}
function makeStrongCacheSync(handler) {
return synchronize(makeStrongCache(handler));
}
function makeCachedFunction(CallCache, handler) {
const callCacheSync = new CallCache();
const callCacheAsync = new CallCache();
const futureCache = new CallCache();
return function* cachedFunction(arg, data) {
const asyncContext = yield* (0, _async.isAsync)();
const callCache = asyncContext ? callCacheAsync : callCacheSync;
const cached = yield* getCachedValueOrWait(asyncContext, callCache, futureCache, arg, data);
if (cached.valid) return cached.value;
const cache = new CacheConfigurator(data);
const handlerResult = handler(arg, cache);
let finishLock;
let value;
if ((0, _util.isIterableIterator)(handlerResult)) {
value = yield* (0, _async.onFirstPause)(handlerResult, () => {
finishLock = setupAsyncLocks(cache, futureCache, arg);
});
} else {
value = handlerResult;
}
updateFunctionCache(callCache, cache, arg, value);
if (finishLock) {
futureCache.delete(arg);
finishLock.release(value);
}
return value;
};
}
function* getCachedValue(cache, arg, data) {
const cachedValue = cache.get(arg);
if (cachedValue) {
for (const {
value,
valid
} of cachedValue) {
if (yield* valid(data)) return {
valid: true,
value
};
}
}
return {
valid: false,
value: null
};
}
function* getCachedValueOrWait(asyncContext, callCache, futureCache, arg, data) {
const cached = yield* getCachedValue(callCache, arg, data);
if (cached.valid) {
return cached;
}
if (asyncContext) {
const cached = yield* getCachedValue(futureCache, arg, data);
if (cached.valid) {
const value = yield* (0, _async.waitFor)(cached.value.promise);
return {
valid: true,
value
};
}
}
return {
valid: false,
value: null
};
}
function setupAsyncLocks(config, futureCache, arg) {
const finishLock = new Lock();
updateFunctionCache(futureCache, config, arg, finishLock);
return finishLock;
}
function updateFunctionCache(cache, config, arg, value) {
if (!config.configured()) config.forever();
let cachedValue = cache.get(arg);
config.deactivate();
switch (config.mode()) {
case "forever":
cachedValue = [{
value,
valid: genTrue
}];
cache.set(arg, cachedValue);
break;
case "invalidate":
cachedValue = [{
value,
valid: config.validator()
}];
cache.set(arg, cachedValue);
break;
case "valid":
if (cachedValue) {
cachedValue.push({
value,
valid: config.validator()
});
} else {
cachedValue = [{
value,
valid: config.validator()
}];
cache.set(arg, cachedValue);
}
}
}
class CacheConfigurator {
constructor(data) {
this._active = true;
this._never = false;
this._forever = false;
this._invalidate = false;
this._configured = false;
this._pairs = [];
this._data = void 0;
this._data = data;
}
simple() {
return makeSimpleConfigurator(this);
}
mode() {
if (this._never) return "never";
if (this._forever) return "forever";
if (this._invalidate) return "invalidate";
return "valid";
}
forever() {
if (!this._active) {
throw new Error("Cannot change caching after evaluation has completed.");
}
if (this._never) {
throw new Error("Caching has already been configured with .never()");
}
this._forever = true;
this._configured = true;
}
never() {
if (!this._active) {
throw new Error("Cannot change caching after evaluation has completed.");
}
if (this._forever) {
throw new Error("Caching has already been configured with .forever()");
}
this._never = true;
this._configured = true;
}
using(handler) {
if (!this._active) {
throw new Error("Cannot change caching after evaluation has completed.");
}
if (this._never || this._forever) {
throw new Error("Caching has already been configured with .never or .forever()");
}
this._configured = true;
const key = handler(this._data);
const fn = (0, _async.maybeAsync)(handler, `You appear to be using an async cache handler, but Babel has been called synchronously`);
if ((0, _async.isThenable)(key)) {
return key.then(key => {
this._pairs.push([key, fn]);
return key;
});
}
this._pairs.push([key, fn]);
return key;
}
invalidate(handler) {
this._invalidate = true;
return this.using(handler);
}
validator() {
const pairs = this._pairs;
return function* (data) {
for (const [key, fn] of pairs) {
if (key !== (yield* fn(data))) return false;
}
return true;
};
}
deactivate() {
this._active = false;
}
configured() {
return this._configured;
}
}
function makeSimpleConfigurator(cache) {
function cacheFn(val) {
if (typeof val === "boolean") {
if (val) cache.forever();else cache.never();
return;
}
return cache.using(() => assertSimpleType(val()));
}
cacheFn.forever = () => cache.forever();
cacheFn.never = () => cache.never();
cacheFn.using = cb => cache.using(() => assertSimpleType(cb()));
cacheFn.invalidate = cb => cache.invalidate(() => assertSimpleType(cb()));
return cacheFn;
}
function assertSimpleType(value) {
if ((0, _async.isThenable)(value)) {
throw new Error(`You appear to be using an async cache handler, ` + `which your current version of Babel does not support. ` + `We may add support for this in the future, ` + `but if you're on the most recent version of @babel/core and still ` + `seeing this error, then you'll need to synchronously handle your caching logic.`);
}
if (value != null && typeof value !== "string" && typeof value !== "boolean" && typeof value !== "number") {
throw new Error("Cache keys must be either string, boolean, number, null, or undefined.");
}
return value;
}
class Lock {
constructor() {
this.released = false;
this.promise = void 0;
this._resolve = void 0;
this.promise = new Promise(resolve => {
this._resolve = resolve;
});
}
release(value) {
this.released = true;
this._resolve(value);
}
}
0 && 0;
//# sourceMappingURL=caching.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,469 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.buildPresetChain = buildPresetChain;
exports.buildPresetChainWalker = void 0;
exports.buildRootChain = buildRootChain;
function _path() {
const data = require("path");
_path = function () {
return data;
};
return data;
}
function _debug() {
const data = require("debug");
_debug = function () {
return data;
};
return data;
}
var _options = require("./validation/options.js");
var _patternToRegex = require("./pattern-to-regex.js");
var _printer = require("./printer.js");
var _rewriteStackTrace = require("../errors/rewrite-stack-trace.js");
var _configError = require("../errors/config-error.js");
var _index = require("./files/index.js");
var _caching = require("./caching.js");
var _configDescriptors = require("./config-descriptors.js");
const debug = _debug()("babel:config:config-chain");
function* buildPresetChain(arg, context) {
const chain = yield* buildPresetChainWalker(arg, context);
if (!chain) return null;
return {
plugins: dedupDescriptors(chain.plugins),
presets: dedupDescriptors(chain.presets),
options: chain.options.map(o => createConfigChainOptions(o)),
files: new Set()
};
}
const buildPresetChainWalker = exports.buildPresetChainWalker = makeChainWalker({
root: preset => loadPresetDescriptors(preset),
env: (preset, envName) => loadPresetEnvDescriptors(preset)(envName),
overrides: (preset, index) => loadPresetOverridesDescriptors(preset)(index),
overridesEnv: (preset, index, envName) => loadPresetOverridesEnvDescriptors(preset)(index)(envName),
createLogger: () => () => {}
});
const loadPresetDescriptors = (0, _caching.makeWeakCacheSync)(preset => buildRootDescriptors(preset, preset.alias, _configDescriptors.createUncachedDescriptors));
const loadPresetEnvDescriptors = (0, _caching.makeWeakCacheSync)(preset => (0, _caching.makeStrongCacheSync)(envName => buildEnvDescriptors(preset, preset.alias, _configDescriptors.createUncachedDescriptors, envName)));
const loadPresetOverridesDescriptors = (0, _caching.makeWeakCacheSync)(preset => (0, _caching.makeStrongCacheSync)(index => buildOverrideDescriptors(preset, preset.alias, _configDescriptors.createUncachedDescriptors, index)));
const loadPresetOverridesEnvDescriptors = (0, _caching.makeWeakCacheSync)(preset => (0, _caching.makeStrongCacheSync)(index => (0, _caching.makeStrongCacheSync)(envName => buildOverrideEnvDescriptors(preset, preset.alias, _configDescriptors.createUncachedDescriptors, index, envName))));
function* buildRootChain(opts, context) {
let configReport, babelRcReport;
const programmaticLogger = new _printer.ConfigPrinter();
const programmaticChain = yield* loadProgrammaticChain({
options: opts,
dirname: context.cwd
}, context, undefined, programmaticLogger);
if (!programmaticChain) return null;
const programmaticReport = yield* programmaticLogger.output();
let configFile;
if (typeof opts.configFile === "string") {
configFile = yield* (0, _index.loadConfig)(opts.configFile, context.cwd, context.envName, context.caller);
} else if (opts.configFile !== false) {
configFile = yield* (0, _index.findRootConfig)(context.root, context.envName, context.caller);
}
let {
babelrc,
babelrcRoots
} = opts;
let babelrcRootsDirectory = context.cwd;
const configFileChain = emptyChain();
const configFileLogger = new _printer.ConfigPrinter();
if (configFile) {
const validatedFile = validateConfigFile(configFile);
const result = yield* loadFileChain(validatedFile, context, undefined, configFileLogger);
if (!result) return null;
configReport = yield* configFileLogger.output();
if (babelrc === undefined) {
babelrc = validatedFile.options.babelrc;
}
if (babelrcRoots === undefined) {
babelrcRootsDirectory = validatedFile.dirname;
babelrcRoots = validatedFile.options.babelrcRoots;
}
mergeChain(configFileChain, result);
}
let ignoreFile, babelrcFile;
let isIgnored = false;
const fileChain = emptyChain();
if ((babelrc === true || babelrc === undefined) && typeof context.filename === "string") {
const pkgData = yield* (0, _index.findPackageData)(context.filename);
if (pkgData && babelrcLoadEnabled(context, pkgData, babelrcRoots, babelrcRootsDirectory)) {
({
ignore: ignoreFile,
config: babelrcFile
} = yield* (0, _index.findRelativeConfig)(pkgData, context.envName, context.caller));
if (ignoreFile) {
fileChain.files.add(ignoreFile.filepath);
}
if (ignoreFile && shouldIgnore(context, ignoreFile.ignore, null, ignoreFile.dirname)) {
isIgnored = true;
}
if (babelrcFile && !isIgnored) {
const validatedFile = validateBabelrcFile(babelrcFile);
const babelrcLogger = new _printer.ConfigPrinter();
const result = yield* loadFileChain(validatedFile, context, undefined, babelrcLogger);
if (!result) {
isIgnored = true;
} else {
babelRcReport = yield* babelrcLogger.output();
mergeChain(fileChain, result);
}
}
if (babelrcFile && isIgnored) {
fileChain.files.add(babelrcFile.filepath);
}
}
}
if (context.showConfig) {
console.log(`Babel configs on "${context.filename}" (ascending priority):\n` + [configReport, babelRcReport, programmaticReport].filter(x => !!x).join("\n\n") + "\n-----End Babel configs-----");
}
const chain = mergeChain(mergeChain(mergeChain(emptyChain(), configFileChain), fileChain), programmaticChain);
return {
plugins: isIgnored ? [] : dedupDescriptors(chain.plugins),
presets: isIgnored ? [] : dedupDescriptors(chain.presets),
options: isIgnored ? [] : chain.options.map(o => createConfigChainOptions(o)),
fileHandling: isIgnored ? "ignored" : "transpile",
ignore: ignoreFile || undefined,
babelrc: babelrcFile || undefined,
config: configFile || undefined,
files: chain.files
};
}
function babelrcLoadEnabled(context, pkgData, babelrcRoots, babelrcRootsDirectory) {
if (typeof babelrcRoots === "boolean") return babelrcRoots;
const absoluteRoot = context.root;
if (babelrcRoots === undefined) {
return pkgData.directories.includes(absoluteRoot);
}
let babelrcPatterns = babelrcRoots;
if (!Array.isArray(babelrcPatterns)) {
babelrcPatterns = [babelrcPatterns];
}
babelrcPatterns = babelrcPatterns.map(pat => {
return typeof pat === "string" ? _path().resolve(babelrcRootsDirectory, pat) : pat;
});
if (babelrcPatterns.length === 1 && babelrcPatterns[0] === absoluteRoot) {
return pkgData.directories.includes(absoluteRoot);
}
return babelrcPatterns.some(pat => {
if (typeof pat === "string") {
pat = (0, _patternToRegex.default)(pat, babelrcRootsDirectory);
}
return pkgData.directories.some(directory => {
return matchPattern(pat, babelrcRootsDirectory, directory, context);
});
});
}
const validateConfigFile = (0, _caching.makeWeakCacheSync)(file => ({
filepath: file.filepath,
dirname: file.dirname,
options: (0, _options.validate)("configfile", file.options, file.filepath)
}));
const validateBabelrcFile = (0, _caching.makeWeakCacheSync)(file => ({
filepath: file.filepath,
dirname: file.dirname,
options: (0, _options.validate)("babelrcfile", file.options, file.filepath)
}));
const validateExtendFile = (0, _caching.makeWeakCacheSync)(file => ({
filepath: file.filepath,
dirname: file.dirname,
options: (0, _options.validate)("extendsfile", file.options, file.filepath)
}));
const loadProgrammaticChain = makeChainWalker({
root: input => buildRootDescriptors(input, "base", _configDescriptors.createCachedDescriptors),
env: (input, envName) => buildEnvDescriptors(input, "base", _configDescriptors.createCachedDescriptors, envName),
overrides: (input, index) => buildOverrideDescriptors(input, "base", _configDescriptors.createCachedDescriptors, index),
overridesEnv: (input, index, envName) => buildOverrideEnvDescriptors(input, "base", _configDescriptors.createCachedDescriptors, index, envName),
createLogger: (input, context, baseLogger) => buildProgrammaticLogger(input, context, baseLogger)
});
const loadFileChainWalker = makeChainWalker({
root: file => loadFileDescriptors(file),
env: (file, envName) => loadFileEnvDescriptors(file)(envName),
overrides: (file, index) => loadFileOverridesDescriptors(file)(index),
overridesEnv: (file, index, envName) => loadFileOverridesEnvDescriptors(file)(index)(envName),
createLogger: (file, context, baseLogger) => buildFileLogger(file.filepath, context, baseLogger)
});
function* loadFileChain(input, context, files, baseLogger) {
const chain = yield* loadFileChainWalker(input, context, files, baseLogger);
chain == null || chain.files.add(input.filepath);
return chain;
}
const loadFileDescriptors = (0, _caching.makeWeakCacheSync)(file => buildRootDescriptors(file, file.filepath, _configDescriptors.createUncachedDescriptors));
const loadFileEnvDescriptors = (0, _caching.makeWeakCacheSync)(file => (0, _caching.makeStrongCacheSync)(envName => buildEnvDescriptors(file, file.filepath, _configDescriptors.createUncachedDescriptors, envName)));
const loadFileOverridesDescriptors = (0, _caching.makeWeakCacheSync)(file => (0, _caching.makeStrongCacheSync)(index => buildOverrideDescriptors(file, file.filepath, _configDescriptors.createUncachedDescriptors, index)));
const loadFileOverridesEnvDescriptors = (0, _caching.makeWeakCacheSync)(file => (0, _caching.makeStrongCacheSync)(index => (0, _caching.makeStrongCacheSync)(envName => buildOverrideEnvDescriptors(file, file.filepath, _configDescriptors.createUncachedDescriptors, index, envName))));
function buildFileLogger(filepath, context, baseLogger) {
if (!baseLogger) {
return () => {};
}
return baseLogger.configure(context.showConfig, _printer.ChainFormatter.Config, {
filepath
});
}
function buildRootDescriptors({
dirname,
options
}, alias, descriptors) {
return descriptors(dirname, options, alias);
}
function buildProgrammaticLogger(_, context, baseLogger) {
var _context$caller;
if (!baseLogger) {
return () => {};
}
return baseLogger.configure(context.showConfig, _printer.ChainFormatter.Programmatic, {
callerName: (_context$caller = context.caller) == null ? void 0 : _context$caller.name
});
}
function buildEnvDescriptors({
dirname,
options
}, alias, descriptors, envName) {
var _options$env;
const opts = (_options$env = options.env) == null ? void 0 : _options$env[envName];
return opts ? descriptors(dirname, opts, `${alias}.env["${envName}"]`) : null;
}
function buildOverrideDescriptors({
dirname,
options
}, alias, descriptors, index) {
var _options$overrides;
const opts = (_options$overrides = options.overrides) == null ? void 0 : _options$overrides[index];
if (!opts) throw new Error("Assertion failure - missing override");
return descriptors(dirname, opts, `${alias}.overrides[${index}]`);
}
function buildOverrideEnvDescriptors({
dirname,
options
}, alias, descriptors, index, envName) {
var _options$overrides2, _override$env;
const override = (_options$overrides2 = options.overrides) == null ? void 0 : _options$overrides2[index];
if (!override) throw new Error("Assertion failure - missing override");
const opts = (_override$env = override.env) == null ? void 0 : _override$env[envName];
return opts ? descriptors(dirname, opts, `${alias}.overrides[${index}].env["${envName}"]`) : null;
}
function makeChainWalker({
root,
env,
overrides,
overridesEnv,
createLogger
}) {
return function* chainWalker(input, context, files = new Set(), baseLogger) {
const {
dirname
} = input;
const flattenedConfigs = [];
const rootOpts = root(input);
if (configIsApplicable(rootOpts, dirname, context, input.filepath)) {
flattenedConfigs.push({
config: rootOpts,
envName: undefined,
index: undefined
});
const envOpts = env(input, context.envName);
if (envOpts && configIsApplicable(envOpts, dirname, context, input.filepath)) {
flattenedConfigs.push({
config: envOpts,
envName: context.envName,
index: undefined
});
}
(rootOpts.options.overrides || []).forEach((_, index) => {
const overrideOps = overrides(input, index);
if (configIsApplicable(overrideOps, dirname, context, input.filepath)) {
flattenedConfigs.push({
config: overrideOps,
index,
envName: undefined
});
const overrideEnvOpts = overridesEnv(input, index, context.envName);
if (overrideEnvOpts && configIsApplicable(overrideEnvOpts, dirname, context, input.filepath)) {
flattenedConfigs.push({
config: overrideEnvOpts,
index,
envName: context.envName
});
}
}
});
}
if (flattenedConfigs.some(({
config: {
options: {
ignore,
only
}
}
}) => shouldIgnore(context, ignore, only, dirname))) {
return null;
}
const chain = emptyChain();
const logger = createLogger(input, context, baseLogger);
for (const {
config,
index,
envName
} of flattenedConfigs) {
if (!(yield* mergeExtendsChain(chain, config.options, dirname, context, files, baseLogger))) {
return null;
}
logger(config, index, envName);
yield* mergeChainOpts(chain, config);
}
return chain;
};
}
function* mergeExtendsChain(chain, opts, dirname, context, files, baseLogger) {
if (opts.extends === undefined) return true;
const file = yield* (0, _index.loadConfig)(opts.extends, dirname, context.envName, context.caller);
if (files.has(file)) {
throw new Error(`Configuration cycle detected loading ${file.filepath}.\n` + `File already loaded following the config chain:\n` + Array.from(files, file => ` - ${file.filepath}`).join("\n"));
}
files.add(file);
const fileChain = yield* loadFileChain(validateExtendFile(file), context, files, baseLogger);
files.delete(file);
if (!fileChain) return false;
mergeChain(chain, fileChain);
return true;
}
function mergeChain(target, source) {
target.options.push(...source.options);
target.plugins.push(...source.plugins);
target.presets.push(...source.presets);
for (const file of source.files) {
target.files.add(file);
}
return target;
}
function* mergeChainOpts(target, {
options,
plugins,
presets
}) {
target.options.push(options);
target.plugins.push(...(yield* plugins()));
target.presets.push(...(yield* presets()));
return target;
}
function emptyChain() {
return {
options: [],
presets: [],
plugins: [],
files: new Set()
};
}
function createConfigChainOptions(opts) {
const options = Object.assign({}, opts);
delete options.extends;
delete options.env;
delete options.overrides;
delete options.plugins;
delete options.presets;
delete options.passPerPreset;
delete options.ignore;
delete options.only;
delete options.test;
delete options.include;
delete options.exclude;
if (hasOwnProperty.call(options, "sourceMap")) {
options.sourceMaps = options.sourceMap;
delete options.sourceMap;
}
return options;
}
function dedupDescriptors(items) {
const map = new Map();
const descriptors = [];
for (const item of items) {
if (typeof item.value === "function") {
const fnKey = item.value;
let nameMap = map.get(fnKey);
if (!nameMap) {
nameMap = new Map();
map.set(fnKey, nameMap);
}
let desc = nameMap.get(item.name);
if (!desc) {
desc = {
value: item
};
descriptors.push(desc);
if (!item.ownPass) nameMap.set(item.name, desc);
} else {
desc.value = item;
}
} else {
descriptors.push({
value: item
});
}
}
return descriptors.reduce((acc, desc) => {
acc.push(desc.value);
return acc;
}, []);
}
function configIsApplicable({
options
}, dirname, context, configName) {
return (options.test === undefined || configFieldIsApplicable(context, options.test, dirname, configName)) && (options.include === undefined || configFieldIsApplicable(context, options.include, dirname, configName)) && (options.exclude === undefined || !configFieldIsApplicable(context, options.exclude, dirname, configName));
}
function configFieldIsApplicable(context, test, dirname, configName) {
const patterns = Array.isArray(test) ? test : [test];
return matchesPatterns(context, patterns, dirname, configName);
}
function ignoreListReplacer(_key, value) {
if (value instanceof RegExp) {
return String(value);
}
return value;
}
function shouldIgnore(context, ignore, only, dirname) {
if (ignore && matchesPatterns(context, ignore, dirname)) {
var _context$filename;
const message = `No config is applied to "${(_context$filename = context.filename) != null ? _context$filename : "(unknown)"}" because it matches one of \`ignore: ${JSON.stringify(ignore, ignoreListReplacer)}\` from "${dirname}"`;
debug(message);
if (context.showConfig) {
console.log(message);
}
return true;
}
if (only && !matchesPatterns(context, only, dirname)) {
var _context$filename2;
const message = `No config is applied to "${(_context$filename2 = context.filename) != null ? _context$filename2 : "(unknown)"}" because it fails to match one of \`only: ${JSON.stringify(only, ignoreListReplacer)}\` from "${dirname}"`;
debug(message);
if (context.showConfig) {
console.log(message);
}
return true;
}
return false;
}
function matchesPatterns(context, patterns, dirname, configName) {
return patterns.some(pattern => matchPattern(pattern, dirname, context.filename, context, configName));
}
function matchPattern(pattern, dirname, pathToTest, context, configName) {
if (typeof pattern === "function") {
return !!(0, _rewriteStackTrace.endHiddenCallStack)(pattern)(pathToTest, {
dirname,
envName: context.envName,
caller: context.caller
});
}
if (typeof pathToTest !== "string") {
throw new _configError.default(`Configuration contains string/RegExp pattern, but no filename was passed to Babel`, configName);
}
if (typeof pattern === "string") {
pattern = (0, _patternToRegex.default)(pattern, dirname);
}
return pattern.test(pathToTest);
}
0 && 0;
//# sourceMappingURL=config-chain.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,190 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.createCachedDescriptors = createCachedDescriptors;
exports.createDescriptor = createDescriptor;
exports.createUncachedDescriptors = createUncachedDescriptors;
function _gensync() {
const data = require("gensync");
_gensync = function () {
return data;
};
return data;
}
var _functional = require("../gensync-utils/functional.js");
var _index = require("./files/index.js");
var _item = require("./item.js");
var _caching = require("./caching.js");
var _resolveTargets = require("./resolve-targets.js");
function isEqualDescriptor(a, b) {
var _a$file, _b$file, _a$file2, _b$file2;
return a.name === b.name && a.value === b.value && a.options === b.options && a.dirname === b.dirname && a.alias === b.alias && a.ownPass === b.ownPass && ((_a$file = a.file) == null ? void 0 : _a$file.request) === ((_b$file = b.file) == null ? void 0 : _b$file.request) && ((_a$file2 = a.file) == null ? void 0 : _a$file2.resolved) === ((_b$file2 = b.file) == null ? void 0 : _b$file2.resolved);
}
function* handlerOf(value) {
return value;
}
function optionsWithResolvedBrowserslistConfigFile(options, dirname) {
if (typeof options.browserslistConfigFile === "string") {
options.browserslistConfigFile = (0, _resolveTargets.resolveBrowserslistConfigFile)(options.browserslistConfigFile, dirname);
}
return options;
}
function createCachedDescriptors(dirname, options, alias) {
const {
plugins,
presets,
passPerPreset
} = options;
return {
options: optionsWithResolvedBrowserslistConfigFile(options, dirname),
plugins: plugins ? () => createCachedPluginDescriptors(plugins, dirname)(alias) : () => handlerOf([]),
presets: presets ? () => createCachedPresetDescriptors(presets, dirname)(alias)(!!passPerPreset) : () => handlerOf([])
};
}
function createUncachedDescriptors(dirname, options, alias) {
return {
options: optionsWithResolvedBrowserslistConfigFile(options, dirname),
plugins: (0, _functional.once)(() => createPluginDescriptors(options.plugins || [], dirname, alias)),
presets: (0, _functional.once)(() => createPresetDescriptors(options.presets || [], dirname, alias, !!options.passPerPreset))
};
}
const PRESET_DESCRIPTOR_CACHE = new WeakMap();
const createCachedPresetDescriptors = (0, _caching.makeWeakCacheSync)((items, cache) => {
const dirname = cache.using(dir => dir);
return (0, _caching.makeStrongCacheSync)(alias => (0, _caching.makeStrongCache)(function* (passPerPreset) {
const descriptors = yield* createPresetDescriptors(items, dirname, alias, passPerPreset);
return descriptors.map(desc => loadCachedDescriptor(PRESET_DESCRIPTOR_CACHE, desc));
}));
});
const PLUGIN_DESCRIPTOR_CACHE = new WeakMap();
const createCachedPluginDescriptors = (0, _caching.makeWeakCacheSync)((items, cache) => {
const dirname = cache.using(dir => dir);
return (0, _caching.makeStrongCache)(function* (alias) {
const descriptors = yield* createPluginDescriptors(items, dirname, alias);
return descriptors.map(desc => loadCachedDescriptor(PLUGIN_DESCRIPTOR_CACHE, desc));
});
});
const DEFAULT_OPTIONS = {};
function loadCachedDescriptor(cache, desc) {
const {
value,
options = DEFAULT_OPTIONS
} = desc;
if (options === false) return desc;
let cacheByOptions = cache.get(value);
if (!cacheByOptions) {
cacheByOptions = new WeakMap();
cache.set(value, cacheByOptions);
}
let possibilities = cacheByOptions.get(options);
if (!possibilities) {
possibilities = [];
cacheByOptions.set(options, possibilities);
}
if (!possibilities.includes(desc)) {
const matches = possibilities.filter(possibility => isEqualDescriptor(possibility, desc));
if (matches.length > 0) {
return matches[0];
}
possibilities.push(desc);
}
return desc;
}
function* createPresetDescriptors(items, dirname, alias, passPerPreset) {
return yield* createDescriptors("preset", items, dirname, alias, passPerPreset);
}
function* createPluginDescriptors(items, dirname, alias) {
return yield* createDescriptors("plugin", items, dirname, alias);
}
function* createDescriptors(type, items, dirname, alias, ownPass) {
const descriptors = yield* _gensync().all(items.map((item, index) => createDescriptor(item, dirname, {
type,
alias: `${alias}$${index}`,
ownPass: !!ownPass
})));
assertNoDuplicates(descriptors);
return descriptors;
}
function* createDescriptor(pair, dirname, {
type,
alias,
ownPass
}) {
const desc = (0, _item.getItemDescriptor)(pair);
if (desc) {
return desc;
}
let name;
let options;
let value = pair;
if (Array.isArray(value)) {
if (value.length === 3) {
[value, options, name] = value;
} else {
[value, options] = value;
}
}
let file = undefined;
let filepath = null;
if (typeof value === "string") {
if (typeof type !== "string") {
throw new Error("To resolve a string-based item, the type of item must be given");
}
const resolver = type === "plugin" ? _index.loadPlugin : _index.loadPreset;
const request = value;
({
filepath,
value
} = yield* resolver(value, dirname));
file = {
request,
resolved: filepath
};
}
if (!value) {
throw new Error(`Unexpected falsy value: ${String(value)}`);
}
if (typeof value === "object" && value.__esModule) {
if (value.default) {
value = value.default;
} else {
throw new Error("Must export a default export when using ES6 modules.");
}
}
if (typeof value !== "object" && typeof value !== "function") {
throw new Error(`Unsupported format: ${typeof value}. Expected an object or a function.`);
}
if (filepath !== null && typeof value === "object" && value) {
throw new Error(`Plugin/Preset files are not allowed to export objects, only functions. In ${filepath}`);
}
return {
name,
alias: filepath || alias,
value,
options,
dirname,
ownPass,
file
};
}
function assertNoDuplicates(items) {
const map = new Map();
for (const item of items) {
if (typeof item.value !== "function") continue;
let nameMap = map.get(item.value);
if (!nameMap) {
nameMap = new Set();
map.set(item.value, nameMap);
}
if (nameMap.has(item.name)) {
const conflicts = items.filter(i => i.value === item.value);
throw new Error([`Duplicate plugin/preset detected.`, `If you'd like to use two separate instances of a plugin,`, `they need separate names, e.g.`, ``, ` plugins: [`, ` ['some-plugin', {}],`, ` ['some-plugin', {}, 'some unique name'],`, ` ]`, ``, `Duplicates detected are:`, `${JSON.stringify(conflicts, null, 2)}`].join("\n"));
}
nameMap.add(item.name);
}
}
0 && 0;
//# sourceMappingURL=config-descriptors.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,290 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.ROOT_CONFIG_FILENAMES = void 0;
exports.findConfigUpwards = findConfigUpwards;
exports.findRelativeConfig = findRelativeConfig;
exports.findRootConfig = findRootConfig;
exports.loadConfig = loadConfig;
exports.resolveShowConfigPath = resolveShowConfigPath;
function _debug() {
const data = require("debug");
_debug = function () {
return data;
};
return data;
}
function _fs() {
const data = require("fs");
_fs = function () {
return data;
};
return data;
}
function _path() {
const data = require("path");
_path = function () {
return data;
};
return data;
}
function _json() {
const data = require("json5");
_json = function () {
return data;
};
return data;
}
function _gensync() {
const data = require("gensync");
_gensync = function () {
return data;
};
return data;
}
var _caching = require("../caching.js");
var _configApi = require("../helpers/config-api.js");
var _utils = require("./utils.js");
var _moduleTypes = require("./module-types.js");
var _patternToRegex = require("../pattern-to-regex.js");
var _configError = require("../../errors/config-error.js");
var fs = require("../../gensync-utils/fs.js");
require("module");
var _rewriteStackTrace = require("../../errors/rewrite-stack-trace.js");
var _async = require("../../gensync-utils/async.js");
const debug = _debug()("babel:config:loading:files:configuration");
const ROOT_CONFIG_FILENAMES = exports.ROOT_CONFIG_FILENAMES = ["babel.config.js", "babel.config.cjs", "babel.config.mjs", "babel.config.json", "babel.config.cts", "babel.config.ts", "babel.config.mts"];
const RELATIVE_CONFIG_FILENAMES = [".babelrc", ".babelrc.js", ".babelrc.cjs", ".babelrc.mjs", ".babelrc.json", ".babelrc.cts"];
const BABELIGNORE_FILENAME = ".babelignore";
const runConfig = (0, _caching.makeWeakCache)(function* runConfig(options, cache) {
yield* [];
return {
options: (0, _rewriteStackTrace.endHiddenCallStack)(options)((0, _configApi.makeConfigAPI)(cache)),
cacheNeedsConfiguration: !cache.configured()
};
});
function* readConfigCode(filepath, data) {
if (!_fs().existsSync(filepath)) return null;
let options = yield* (0, _moduleTypes.default)(filepath, (yield* (0, _async.isAsync)()) ? "auto" : "require", "You appear to be using a native ECMAScript module configuration " + "file, which is only supported when running Babel asynchronously " + "or when using the Node.js `--experimental-require-module` flag.", "You appear to be using a configuration file that contains top-level " + "await, which is only supported when running Babel asynchronously.");
let cacheNeedsConfiguration = false;
if (typeof options === "function") {
({
options,
cacheNeedsConfiguration
} = yield* runConfig(options, data));
}
if (!options || typeof options !== "object" || Array.isArray(options)) {
throw new _configError.default(`Configuration should be an exported JavaScript object.`, filepath);
}
if (typeof options.then === "function") {
options.catch == null || options.catch(() => {});
throw new _configError.default(`You appear to be using an async configuration, ` + `which your current version of Babel does not support. ` + `We may add support for this in the future, ` + `but if you're on the most recent version of @babel/core and still ` + `seeing this error, then you'll need to synchronously return your config.`, filepath);
}
if (cacheNeedsConfiguration) throwConfigError(filepath);
return buildConfigFileObject(options, filepath);
}
const cfboaf = new WeakMap();
function buildConfigFileObject(options, filepath) {
let configFilesByFilepath = cfboaf.get(options);
if (!configFilesByFilepath) {
cfboaf.set(options, configFilesByFilepath = new Map());
}
let configFile = configFilesByFilepath.get(filepath);
if (!configFile) {
configFile = {
filepath,
dirname: _path().dirname(filepath),
options
};
configFilesByFilepath.set(filepath, configFile);
}
return configFile;
}
const packageToBabelConfig = (0, _caching.makeWeakCacheSync)(file => {
const babel = file.options.babel;
if (babel === undefined) return null;
if (typeof babel !== "object" || Array.isArray(babel) || babel === null) {
throw new _configError.default(`.babel property must be an object`, file.filepath);
}
return {
filepath: file.filepath,
dirname: file.dirname,
options: babel
};
});
const readConfigJSON5 = (0, _utils.makeStaticFileCache)((filepath, content) => {
let options;
try {
options = _json().parse(content);
} catch (err) {
throw new _configError.default(`Error while parsing config - ${err.message}`, filepath);
}
if (!options) throw new _configError.default(`No config detected`, filepath);
if (typeof options !== "object") {
throw new _configError.default(`Config returned typeof ${typeof options}`, filepath);
}
if (Array.isArray(options)) {
throw new _configError.default(`Expected config object but found array`, filepath);
}
delete options.$schema;
return {
filepath,
dirname: _path().dirname(filepath),
options
};
});
const readIgnoreConfig = (0, _utils.makeStaticFileCache)((filepath, content) => {
const ignoreDir = _path().dirname(filepath);
const ignorePatterns = content.split("\n").map(line => line.replace(/#.*$/, "").trim()).filter(Boolean);
for (const pattern of ignorePatterns) {
if (pattern[0] === "!") {
throw new _configError.default(`Negation of file paths is not supported.`, filepath);
}
}
return {
filepath,
dirname: _path().dirname(filepath),
ignore: ignorePatterns.map(pattern => (0, _patternToRegex.default)(pattern, ignoreDir))
};
});
function findConfigUpwards(rootDir) {
let dirname = rootDir;
for (;;) {
for (const filename of ROOT_CONFIG_FILENAMES) {
if (_fs().existsSync(_path().join(dirname, filename))) {
return dirname;
}
}
const nextDir = _path().dirname(dirname);
if (dirname === nextDir) break;
dirname = nextDir;
}
return null;
}
function* findRelativeConfig(packageData, envName, caller) {
let config = null;
let ignore = null;
const dirname = _path().dirname(packageData.filepath);
for (const loc of packageData.directories) {
if (!config) {
var _packageData$pkg;
config = yield* loadOneConfig(RELATIVE_CONFIG_FILENAMES, loc, envName, caller, ((_packageData$pkg = packageData.pkg) == null ? void 0 : _packageData$pkg.dirname) === loc ? packageToBabelConfig(packageData.pkg) : null);
}
if (!ignore) {
const ignoreLoc = _path().join(loc, BABELIGNORE_FILENAME);
ignore = yield* readIgnoreConfig(ignoreLoc);
if (ignore) {
debug("Found ignore %o from %o.", ignore.filepath, dirname);
}
}
}
return {
config,
ignore
};
}
function findRootConfig(dirname, envName, caller) {
return loadOneConfig(ROOT_CONFIG_FILENAMES, dirname, envName, caller);
}
function* loadOneConfig(names, dirname, envName, caller, previousConfig = null) {
const configs = yield* _gensync().all(names.map(filename => readConfig(_path().join(dirname, filename), envName, caller)));
const config = configs.reduce((previousConfig, config) => {
if (config && previousConfig) {
throw new _configError.default(`Multiple configuration files found. Please remove one:\n` + ` - ${_path().basename(previousConfig.filepath)}\n` + ` - ${config.filepath}\n` + `from ${dirname}`);
}
return config || previousConfig;
}, previousConfig);
if (config) {
debug("Found configuration %o from %o.", config.filepath, dirname);
}
return config;
}
function* loadConfig(name, dirname, envName, caller) {
const filepath = (((v, w) => (v = v.split("."), w = w.split("."), +v[0] > +w[0] || v[0] == w[0] && +v[1] >= +w[1]))(process.versions.node, "8.9") ? require.resolve : (r, {
paths: [b]
}, M = require("module")) => {
let f = M._findPath(r, M._nodeModulePaths(b).concat(b));
if (f) return f;
f = new Error(`Cannot resolve module '${r}'`);
f.code = "MODULE_NOT_FOUND";
throw f;
})(name, {
paths: [dirname]
});
const conf = yield* readConfig(filepath, envName, caller);
if (!conf) {
throw new _configError.default(`Config file contains no configuration data`, filepath);
}
debug("Loaded config %o from %o.", name, dirname);
return conf;
}
function readConfig(filepath, envName, caller) {
const ext = _path().extname(filepath);
switch (ext) {
case ".js":
case ".cjs":
case ".mjs":
case ".ts":
case ".cts":
case ".mts":
return readConfigCode(filepath, {
envName,
caller
});
default:
return readConfigJSON5(filepath);
}
}
function* resolveShowConfigPath(dirname) {
const targetPath = process.env.BABEL_SHOW_CONFIG_FOR;
if (targetPath != null) {
const absolutePath = _path().resolve(dirname, targetPath);
const stats = yield* fs.stat(absolutePath);
if (!stats.isFile()) {
throw new Error(`${absolutePath}: BABEL_SHOW_CONFIG_FOR must refer to a regular file, directories are not supported.`);
}
return absolutePath;
}
return null;
}
function throwConfigError(filepath) {
throw new _configError.default(`\
Caching was left unconfigured. Babel's plugins, presets, and .babelrc.js files can be configured
for various types of caching, using the first param of their handler functions:
module.exports = function(api) {
// The API exposes the following:
// Cache the returned value forever and don't call this function again.
api.cache(true);
// Don't cache at all. Not recommended because it will be very slow.
api.cache(false);
// Cached based on the value of some function. If this function returns a value different from
// a previously-encountered value, the plugins will re-evaluate.
var env = api.cache(() => process.env.NODE_ENV);
// If testing for a specific env, we recommend specifics to avoid instantiating a plugin for
// any possible NODE_ENV value that might come up during plugin execution.
var isProd = api.cache(() => process.env.NODE_ENV === "production");
// .cache(fn) will perform a linear search though instances to find the matching plugin based
// based on previous instantiated plugins. If you want to recreate the plugin and discard the
// previous instance whenever something changes, you may use:
var isProd = api.cache.invalidate(() => process.env.NODE_ENV === "production");
// Note, we also expose the following more-verbose versions of the above examples:
api.cache.forever(); // api.cache(true)
api.cache.never(); // api.cache(false)
api.cache.using(fn); // api.cache(fn)
// Return the value that will be cached.
return { };
};`, filepath);
}
0 && 0;
//# sourceMappingURL=configuration.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,6 @@
module.exports = function import_(filepath) {
return import(filepath);
};
0 && 0;
//# sourceMappingURL=import.cjs.map
@@ -0,0 +1 @@
{"version":3,"names":["module","exports","import_","filepath"],"sources":["../../../src/config/files/import.cjs"],"sourcesContent":["// We keep this in a separate file so that in older node versions, where\n// import() isn't supported, we can try/catch around the require() call\n// when loading this file.\n\nmodule.exports = function import_(filepath) {\n return import(filepath);\n};\n"],"mappings":"AAIAA,MAAM,CAACC,OAAO,GAAG,SAASC,OAAOA,CAACC,QAAQ,EAAE;EAC1C,OAAO,OAAOA,QAAQ,CAAC;AACzB,CAAC;AAAC","ignoreList":[]}
@@ -0,0 +1,58 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.ROOT_CONFIG_FILENAMES = void 0;
exports.findConfigUpwards = findConfigUpwards;
exports.findPackageData = findPackageData;
exports.findRelativeConfig = findRelativeConfig;
exports.findRootConfig = findRootConfig;
exports.loadConfig = loadConfig;
exports.loadPlugin = loadPlugin;
exports.loadPreset = loadPreset;
exports.resolvePlugin = resolvePlugin;
exports.resolvePreset = resolvePreset;
exports.resolveShowConfigPath = resolveShowConfigPath;
function findConfigUpwards(rootDir) {
return null;
}
function* findPackageData(filepath) {
return {
filepath,
directories: [],
pkg: null,
isPackage: false
};
}
function* findRelativeConfig(pkgData, envName, caller) {
return {
config: null,
ignore: null
};
}
function* findRootConfig(dirname, envName, caller) {
return null;
}
function* loadConfig(name, dirname, envName, caller) {
throw new Error(`Cannot load ${name} relative to ${dirname} in a browser`);
}
function* resolveShowConfigPath(dirname) {
return null;
}
const ROOT_CONFIG_FILENAMES = exports.ROOT_CONFIG_FILENAMES = [];
function resolvePlugin(name, dirname) {
return null;
}
function resolvePreset(name, dirname) {
return null;
}
function loadPlugin(name, dirname) {
throw new Error(`Cannot load plugin ${name} relative to ${dirname} in a browser`);
}
function loadPreset(name, dirname) {
throw new Error(`Cannot load preset ${name} relative to ${dirname} in a browser`);
}
0 && 0;
//# sourceMappingURL=index-browser.js.map
@@ -0,0 +1 @@
{"version":3,"names":["findConfigUpwards","rootDir","findPackageData","filepath","directories","pkg","isPackage","findRelativeConfig","pkgData","envName","caller","config","ignore","findRootConfig","dirname","loadConfig","name","Error","resolveShowConfigPath","ROOT_CONFIG_FILENAMES","exports","resolvePlugin","resolvePreset","loadPlugin","loadPreset"],"sources":["../../../src/config/files/index-browser.ts"],"sourcesContent":["/* c8 ignore start */\n\nimport type { Handler } from \"gensync\";\n\nimport type {\n ConfigFile,\n IgnoreFile,\n RelativeConfig,\n FilePackageData,\n} from \"./types.ts\";\n\nimport type { CallerMetadata } from \"../validation/options.ts\";\n\nexport type { ConfigFile, IgnoreFile, RelativeConfig, FilePackageData };\n\nexport function findConfigUpwards(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n rootDir: string,\n): string | null {\n return null;\n}\n\n// eslint-disable-next-line require-yield\nexport function* findPackageData(filepath: string): Handler<FilePackageData> {\n return {\n filepath,\n directories: [],\n pkg: null,\n isPackage: false,\n };\n}\n\n// eslint-disable-next-line require-yield\nexport function* findRelativeConfig(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n pkgData: FilePackageData,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n envName: string,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n caller: CallerMetadata | undefined,\n): Handler<RelativeConfig> {\n return { config: null, ignore: null };\n}\n\n// eslint-disable-next-line require-yield\nexport function* findRootConfig(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n dirname: string,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n envName: string,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n caller: CallerMetadata | undefined,\n): Handler<ConfigFile | null> {\n return null;\n}\n\n// eslint-disable-next-line require-yield\nexport function* loadConfig(\n name: string,\n dirname: string,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n envName: string,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n caller: CallerMetadata | undefined,\n): Handler<ConfigFile> {\n throw new Error(`Cannot load ${name} relative to ${dirname} in a browser`);\n}\n\n// eslint-disable-next-line require-yield\nexport function* resolveShowConfigPath(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n dirname: string,\n): Handler<string | null> {\n return null;\n}\n\nexport const ROOT_CONFIG_FILENAMES: string[] = [];\n\ntype Resolved =\n | { loader: \"require\"; filepath: string }\n | { loader: \"import\"; filepath: string };\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport function resolvePlugin(name: string, dirname: string): Resolved | null {\n return null;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport function resolvePreset(name: string, dirname: string): Resolved | null {\n return null;\n}\n\nexport function loadPlugin(\n name: string,\n dirname: string,\n): Handler<{\n filepath: string;\n value: unknown;\n}> {\n throw new Error(\n `Cannot load plugin ${name} relative to ${dirname} in a browser`,\n );\n}\n\nexport function loadPreset(\n name: string,\n dirname: string,\n): Handler<{\n filepath: string;\n value: unknown;\n}> {\n throw new Error(\n `Cannot load preset ${name} relative to ${dirname} in a browser`,\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAeO,SAASA,iBAAiBA,CAE/BC,OAAe,EACA;EACf,OAAO,IAAI;AACb;AAGO,UAAUC,eAAeA,CAACC,QAAgB,EAA4B;EAC3E,OAAO;IACLA,QAAQ;IACRC,WAAW,EAAE,EAAE;IACfC,GAAG,EAAE,IAAI;IACTC,SAAS,EAAE;EACb,CAAC;AACH;AAGO,UAAUC,kBAAkBA,CAEjCC,OAAwB,EAExBC,OAAe,EAEfC,MAAkC,EACT;EACzB,OAAO;IAAEC,MAAM,EAAE,IAAI;IAAEC,MAAM,EAAE;EAAK,CAAC;AACvC;AAGO,UAAUC,cAAcA,CAE7BC,OAAe,EAEfL,OAAe,EAEfC,MAAkC,EACN;EAC5B,OAAO,IAAI;AACb;AAGO,UAAUK,UAAUA,CACzBC,IAAY,EACZF,OAAe,EAEfL,OAAe,EAEfC,MAAkC,EACb;EACrB,MAAM,IAAIO,KAAK,CAAC,eAAeD,IAAI,gBAAgBF,OAAO,eAAe,CAAC;AAC5E;AAGO,UAAUI,qBAAqBA,CAEpCJ,OAAe,EACS;EACxB,OAAO,IAAI;AACb;AAEO,MAAMK,qBAA+B,GAAAC,OAAA,CAAAD,qBAAA,GAAG,EAAE;AAO1C,SAASE,aAAaA,CAACL,IAAY,EAAEF,OAAe,EAAmB;EAC5E,OAAO,IAAI;AACb;AAGO,SAASQ,aAAaA,CAACN,IAAY,EAAEF,OAAe,EAAmB;EAC5E,OAAO,IAAI;AACb;AAEO,SAASS,UAAUA,CACxBP,IAAY,EACZF,OAAe,EAId;EACD,MAAM,IAAIG,KAAK,CACb,sBAAsBD,IAAI,gBAAgBF,OAAO,eACnD,CAAC;AACH;AAEO,SAASU,UAAUA,CACxBR,IAAY,EACZF,OAAe,EAId;EACD,MAAM,IAAIG,KAAK,CACb,sBAAsBD,IAAI,gBAAgBF,OAAO,eACnD,CAAC;AACH;AAAC","ignoreList":[]}
@@ -0,0 +1,78 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "ROOT_CONFIG_FILENAMES", {
enumerable: true,
get: function () {
return _configuration.ROOT_CONFIG_FILENAMES;
}
});
Object.defineProperty(exports, "findConfigUpwards", {
enumerable: true,
get: function () {
return _configuration.findConfigUpwards;
}
});
Object.defineProperty(exports, "findPackageData", {
enumerable: true,
get: function () {
return _package.findPackageData;
}
});
Object.defineProperty(exports, "findRelativeConfig", {
enumerable: true,
get: function () {
return _configuration.findRelativeConfig;
}
});
Object.defineProperty(exports, "findRootConfig", {
enumerable: true,
get: function () {
return _configuration.findRootConfig;
}
});
Object.defineProperty(exports, "loadConfig", {
enumerable: true,
get: function () {
return _configuration.loadConfig;
}
});
Object.defineProperty(exports, "loadPlugin", {
enumerable: true,
get: function () {
return _plugins.loadPlugin;
}
});
Object.defineProperty(exports, "loadPreset", {
enumerable: true,
get: function () {
return _plugins.loadPreset;
}
});
Object.defineProperty(exports, "resolvePlugin", {
enumerable: true,
get: function () {
return _plugins.resolvePlugin;
}
});
Object.defineProperty(exports, "resolvePreset", {
enumerable: true,
get: function () {
return _plugins.resolvePreset;
}
});
Object.defineProperty(exports, "resolveShowConfigPath", {
enumerable: true,
get: function () {
return _configuration.resolveShowConfigPath;
}
});
var _package = require("./package.js");
var _configuration = require("./configuration.js");
var _plugins = require("./plugins.js");
({});
0 && 0;
//# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
{"version":3,"names":["_package","require","_configuration","_plugins"],"sources":["../../../src/config/files/index.ts"],"sourcesContent":["type indexBrowserType = typeof import(\"./index-browser\");\ntype indexType = typeof import(\"./index\");\n\n// Kind of gross, but essentially asserting that the exports of this module are the same as the\n// exports of index-browser, since this file may be replaced at bundle time with index-browser.\n({}) as any as indexBrowserType as indexType;\n\nexport { findPackageData } from \"./package.ts\";\n\nexport {\n findConfigUpwards,\n findRelativeConfig,\n findRootConfig,\n loadConfig,\n resolveShowConfigPath,\n ROOT_CONFIG_FILENAMES,\n} from \"./configuration.ts\";\nexport type {\n ConfigFile,\n IgnoreFile,\n RelativeConfig,\n FilePackageData,\n} from \"./types.ts\";\nexport {\n loadPlugin,\n loadPreset,\n resolvePlugin,\n resolvePreset,\n} from \"./plugins.ts\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOA,IAAAA,QAAA,GAAAC,OAAA;AAEA,IAAAC,cAAA,GAAAD,OAAA;AAcA,IAAAE,QAAA,GAAAF,OAAA;AAlBA,CAAC,CAAC,CAAC;AAA0C","ignoreList":[]}
@@ -0,0 +1,211 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = loadCodeDefault;
exports.supportsESM = void 0;
var _async = require("../../gensync-utils/async.js");
function _path() {
const data = require("path");
_path = function () {
return data;
};
return data;
}
function _url() {
const data = require("url");
_url = function () {
return data;
};
return data;
}
require("module");
function _semver() {
const data = require("semver");
_semver = function () {
return data;
};
return data;
}
function _debug() {
const data = require("debug");
_debug = function () {
return data;
};
return data;
}
var _rewriteStackTrace = require("../../errors/rewrite-stack-trace.js");
var _configError = require("../../errors/config-error.js");
var _transformFile = require("../../transform-file.js");
function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
const debug = _debug()("babel:config:loading:files:module-types");
{
try {
var import_ = require("./import.cjs");
} catch (_unused) {}
}
const supportsESM = exports.supportsESM = _semver().satisfies(process.versions.node, "^12.17 || >=13.2");
const LOADING_CJS_FILES = new Set();
function loadCjsDefault(filepath) {
if (LOADING_CJS_FILES.has(filepath)) {
debug("Auto-ignoring usage of config %o.", filepath);
return {};
}
let module;
try {
LOADING_CJS_FILES.add(filepath);
module = (0, _rewriteStackTrace.endHiddenCallStack)(require)(filepath);
} finally {
LOADING_CJS_FILES.delete(filepath);
}
{
return module != null && (module.__esModule || module[Symbol.toStringTag] === "Module") ? module.default || (arguments[1] ? module : undefined) : module;
}
}
const loadMjsFromPath = (0, _rewriteStackTrace.endHiddenCallStack)(function () {
var _loadMjsFromPath = _asyncToGenerator(function* (filepath) {
const url = (0, _url().pathToFileURL)(filepath).toString() + "?import";
{
if (!import_) {
throw new _configError.default("Internal error: Native ECMAScript modules aren't supported by this platform.\n", filepath);
}
return yield import_(url);
}
});
function loadMjsFromPath(_x) {
return _loadMjsFromPath.apply(this, arguments);
}
return loadMjsFromPath;
}());
const tsNotSupportedError = ext => `\
You are using a ${ext} config file, but Babel only supports transpiling .cts configs. Either:
- Use a .cts config file
- Update to Node.js 23.6.0, which has native TypeScript support
- Install tsx to transpile ${ext} files on the fly\
`;
const SUPPORTED_EXTENSIONS = {
".js": "unknown",
".mjs": "esm",
".cjs": "cjs",
".ts": "unknown",
".mts": "esm",
".cts": "cjs"
};
const asyncModules = new Set();
function* loadCodeDefault(filepath, loader, esmError, tlaError) {
let async;
const ext = _path().extname(filepath);
const isTS = ext === ".ts" || ext === ".cts" || ext === ".mts";
const type = SUPPORTED_EXTENSIONS[hasOwnProperty.call(SUPPORTED_EXTENSIONS, ext) ? ext : ".js"];
const pattern = `${loader} ${type}`;
switch (pattern) {
case "require cjs":
case "auto cjs":
if (isTS) {
return ensureTsSupport(filepath, ext, () => loadCjsDefault(filepath));
} else {
return loadCjsDefault(filepath, arguments[2]);
}
case "auto unknown":
case "require unknown":
case "require esm":
try {
if (isTS) {
return ensureTsSupport(filepath, ext, () => loadCjsDefault(filepath));
} else {
return loadCjsDefault(filepath, arguments[2]);
}
} catch (e) {
if (e.code === "ERR_REQUIRE_ASYNC_MODULE" || e.code === "ERR_REQUIRE_CYCLE_MODULE" && asyncModules.has(filepath)) {
asyncModules.add(filepath);
if (!(async != null ? async : async = yield* (0, _async.isAsync)())) {
throw new _configError.default(tlaError, filepath);
}
} else if (e.code === "ERR_REQUIRE_ESM" || type === "esm") {} else {
throw e;
}
}
case "auto esm":
if (async != null ? async : async = yield* (0, _async.isAsync)()) {
const promise = isTS ? ensureTsSupport(filepath, ext, () => loadMjsFromPath(filepath)) : loadMjsFromPath(filepath);
return (yield* (0, _async.waitFor)(promise)).default;
}
if (isTS) {
throw new _configError.default(tsNotSupportedError(ext), filepath);
} else {
throw new _configError.default(esmError, filepath);
}
default:
throw new Error("Internal Babel error: unreachable code.");
}
}
function ensureTsSupport(filepath, ext, callback) {
if (process.features.typescript || require.extensions[".ts"] || require.extensions[".cts"] || require.extensions[".mts"]) {
return callback();
}
if (ext !== ".cts") {
throw new _configError.default(tsNotSupportedError(ext), filepath);
}
const opts = {
babelrc: false,
configFile: false,
sourceType: "unambiguous",
sourceMaps: "inline",
sourceFileName: _path().basename(filepath),
presets: [[getTSPreset(filepath), Object.assign({
onlyRemoveTypeImports: true,
optimizeConstEnums: true
}, {
allowDeclareFields: true
})]]
};
let handler = function (m, filename) {
if (handler && filename.endsWith(".cts")) {
try {
return m._compile((0, _transformFile.transformFileSync)(filename, Object.assign({}, opts, {
filename
})).code, filename);
} catch (error) {
const packageJson = require("@babel/preset-typescript/package.json");
if (_semver().lt(packageJson.version, "7.21.4")) {
console.error("`.cts` configuration file failed to load, please try to update `@babel/preset-typescript`.");
}
throw error;
}
}
return require.extensions[".js"](m, filename);
};
require.extensions[ext] = handler;
try {
return callback();
} finally {
if (require.extensions[ext] === handler) delete require.extensions[ext];
handler = undefined;
}
}
function getTSPreset(filepath) {
try {
return require("@babel/preset-typescript");
} catch (error) {
if (error.code !== "MODULE_NOT_FOUND") throw error;
let message = "You appear to be using a .cts file as Babel configuration, but the `@babel/preset-typescript` package was not found: please install it!";
{
if (process.versions.pnp) {
message += `
If you are using Yarn Plug'n'Play, you may also need to add the following configuration to your .yarnrc.yml file:
packageExtensions:
\t"@babel/core@*":
\t\tpeerDependencies:
\t\t\t"@babel/preset-typescript": "*"
`;
}
}
throw new _configError.default(message, filepath);
}
}
0 && 0;
//# sourceMappingURL=module-types.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,61 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.findPackageData = findPackageData;
function _path() {
const data = require("path");
_path = function () {
return data;
};
return data;
}
var _utils = require("./utils.js");
var _configError = require("../../errors/config-error.js");
const PACKAGE_FILENAME = "package.json";
const readConfigPackage = (0, _utils.makeStaticFileCache)((filepath, content) => {
let options;
try {
options = JSON.parse(content);
} catch (err) {
throw new _configError.default(`Error while parsing JSON - ${err.message}`, filepath);
}
if (!options) throw new Error(`${filepath}: No config detected`);
if (typeof options !== "object") {
throw new _configError.default(`Config returned typeof ${typeof options}`, filepath);
}
if (Array.isArray(options)) {
throw new _configError.default(`Expected config object but found array`, filepath);
}
return {
filepath,
dirname: _path().dirname(filepath),
options
};
});
function* findPackageData(filepath) {
let pkg = null;
const directories = [];
let isPackage = true;
let dirname = _path().dirname(filepath);
while (!pkg && _path().basename(dirname) !== "node_modules") {
directories.push(dirname);
pkg = yield* readConfigPackage(_path().join(dirname, PACKAGE_FILENAME));
const nextLoc = _path().dirname(dirname);
if (dirname === nextLoc) {
isPackage = false;
break;
}
dirname = nextLoc;
}
return {
filepath,
directories,
pkg,
isPackage
};
}
0 && 0;
//# sourceMappingURL=package.js.map
@@ -0,0 +1 @@
{"version":3,"names":["_path","data","require","_utils","_configError","PACKAGE_FILENAME","readConfigPackage","makeStaticFileCache","filepath","content","options","JSON","parse","err","ConfigError","message","Error","Array","isArray","dirname","path","findPackageData","pkg","directories","isPackage","basename","push","join","nextLoc"],"sources":["../../../src/config/files/package.ts"],"sourcesContent":["import path from \"node:path\";\nimport type { Handler } from \"gensync\";\nimport { makeStaticFileCache } from \"./utils.ts\";\n\nimport type { ConfigFile, FilePackageData } from \"./types.ts\";\n\nimport ConfigError from \"../../errors/config-error.ts\";\n\nconst PACKAGE_FILENAME = \"package.json\";\n\nconst readConfigPackage = makeStaticFileCache(\n (filepath, content): ConfigFile => {\n let options;\n try {\n options = JSON.parse(content) as unknown;\n } catch (err) {\n throw new ConfigError(\n `Error while parsing JSON - ${err.message}`,\n filepath,\n );\n }\n\n if (!options) throw new Error(`${filepath}: No config detected`);\n\n if (typeof options !== \"object\") {\n throw new ConfigError(\n `Config returned typeof ${typeof options}`,\n filepath,\n );\n }\n if (Array.isArray(options)) {\n throw new ConfigError(`Expected config object but found array`, filepath);\n }\n\n return {\n filepath,\n dirname: path.dirname(filepath),\n options,\n };\n },\n);\n\n/**\n * Find metadata about the package that this file is inside of. Resolution\n * of Babel's config requires general package information to decide when to\n * search for .babelrc files\n */\nexport function* findPackageData(filepath: string): Handler<FilePackageData> {\n let pkg = null;\n const directories = [];\n let isPackage = true;\n\n let dirname = path.dirname(filepath);\n while (!pkg && path.basename(dirname) !== \"node_modules\") {\n directories.push(dirname);\n\n pkg = yield* readConfigPackage(path.join(dirname, PACKAGE_FILENAME));\n\n const nextLoc = path.dirname(dirname);\n if (dirname === nextLoc) {\n isPackage = false;\n break;\n }\n dirname = nextLoc;\n }\n\n return { filepath, directories, pkg, isPackage };\n}\n"],"mappings":";;;;;;AAAA,SAAAA,MAAA;EAAA,MAAAC,IAAA,GAAAC,OAAA;EAAAF,KAAA,YAAAA,CAAA;IAAA,OAAAC,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AAEA,IAAAE,MAAA,GAAAD,OAAA;AAIA,IAAAE,YAAA,GAAAF,OAAA;AAEA,MAAMG,gBAAgB,GAAG,cAAc;AAEvC,MAAMC,iBAAiB,GAAG,IAAAC,0BAAmB,EAC3C,CAACC,QAAQ,EAAEC,OAAO,KAAiB;EACjC,IAAIC,OAAO;EACX,IAAI;IACFA,OAAO,GAAGC,IAAI,CAACC,KAAK,CAACH,OAAO,CAAY;EAC1C,CAAC,CAAC,OAAOI,GAAG,EAAE;IACZ,MAAM,IAAIC,oBAAW,CACnB,8BAA8BD,GAAG,CAACE,OAAO,EAAE,EAC3CP,QACF,CAAC;EACH;EAEA,IAAI,CAACE,OAAO,EAAE,MAAM,IAAIM,KAAK,CAAC,GAAGR,QAAQ,sBAAsB,CAAC;EAEhE,IAAI,OAAOE,OAAO,KAAK,QAAQ,EAAE;IAC/B,MAAM,IAAII,oBAAW,CACnB,0BAA0B,OAAOJ,OAAO,EAAE,EAC1CF,QACF,CAAC;EACH;EACA,IAAIS,KAAK,CAACC,OAAO,CAACR,OAAO,CAAC,EAAE;IAC1B,MAAM,IAAII,oBAAW,CAAC,wCAAwC,EAAEN,QAAQ,CAAC;EAC3E;EAEA,OAAO;IACLA,QAAQ;IACRW,OAAO,EAAEC,MAAGA,CAAC,CAACD,OAAO,CAACX,QAAQ,CAAC;IAC/BE;EACF,CAAC;AACH,CACF,CAAC;AAOM,UAAUW,eAAeA,CAACb,QAAgB,EAA4B;EAC3E,IAAIc,GAAG,GAAG,IAAI;EACd,MAAMC,WAAW,GAAG,EAAE;EACtB,IAAIC,SAAS,GAAG,IAAI;EAEpB,IAAIL,OAAO,GAAGC,MAAGA,CAAC,CAACD,OAAO,CAACX,QAAQ,CAAC;EACpC,OAAO,CAACc,GAAG,IAAIF,MAAGA,CAAC,CAACK,QAAQ,CAACN,OAAO,CAAC,KAAK,cAAc,EAAE;IACxDI,WAAW,CAACG,IAAI,CAACP,OAAO,CAAC;IAEzBG,GAAG,GAAG,OAAOhB,iBAAiB,CAACc,MAAGA,CAAC,CAACO,IAAI,CAACR,OAAO,EAAEd,gBAAgB,CAAC,CAAC;IAEpE,MAAMuB,OAAO,GAAGR,MAAGA,CAAC,CAACD,OAAO,CAACA,OAAO,CAAC;IACrC,IAAIA,OAAO,KAAKS,OAAO,EAAE;MACvBJ,SAAS,GAAG,KAAK;MACjB;IACF;IACAL,OAAO,GAAGS,OAAO;EACnB;EAEA,OAAO;IAAEpB,QAAQ;IAAEe,WAAW;IAAED,GAAG;IAAEE;EAAU,CAAC;AAClD;AAAC","ignoreList":[]}
@@ -0,0 +1,230 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.loadPlugin = loadPlugin;
exports.loadPreset = loadPreset;
exports.resolvePreset = exports.resolvePlugin = void 0;
function _debug() {
const data = require("debug");
_debug = function () {
return data;
};
return data;
}
function _path() {
const data = require("path");
_path = function () {
return data;
};
return data;
}
var _async = require("../../gensync-utils/async.js");
var _moduleTypes = require("./module-types.js");
function _url() {
const data = require("url");
_url = function () {
return data;
};
return data;
}
var _importMetaResolve = require("../../vendor/import-meta-resolve.js");
require("module");
function _fs() {
const data = require("fs");
_fs = function () {
return data;
};
return data;
}
const debug = _debug()("babel:config:loading:files:plugins");
const EXACT_RE = /^module:/;
const BABEL_PLUGIN_PREFIX_RE = /^(?!@|module:|[^/]+\/|babel-plugin-)/;
const BABEL_PRESET_PREFIX_RE = /^(?!@|module:|[^/]+\/|babel-preset-)/;
const BABEL_PLUGIN_ORG_RE = /^(@babel\/)(?!plugin-|[^/]+\/)/;
const BABEL_PRESET_ORG_RE = /^(@babel\/)(?!preset-|[^/]+\/)/;
const OTHER_PLUGIN_ORG_RE = /^(@(?!babel\/)[^/]+\/)(?![^/]*babel-plugin(?:-|\/|$)|[^/]+\/)/;
const OTHER_PRESET_ORG_RE = /^(@(?!babel\/)[^/]+\/)(?![^/]*babel-preset(?:-|\/|$)|[^/]+\/)/;
const OTHER_ORG_DEFAULT_RE = /^(@(?!babel$)[^/]+)$/;
const resolvePlugin = exports.resolvePlugin = resolveStandardizedName.bind(null, "plugin");
const resolvePreset = exports.resolvePreset = resolveStandardizedName.bind(null, "preset");
function* loadPlugin(name, dirname) {
const {
filepath,
loader
} = resolvePlugin(name, dirname, yield* (0, _async.isAsync)());
const value = yield* requireModule("plugin", loader, filepath);
debug("Loaded plugin %o from %o.", name, dirname);
return {
filepath,
value
};
}
function* loadPreset(name, dirname) {
const {
filepath,
loader
} = resolvePreset(name, dirname, yield* (0, _async.isAsync)());
const value = yield* requireModule("preset", loader, filepath);
debug("Loaded preset %o from %o.", name, dirname);
return {
filepath,
value
};
}
function standardizeName(type, name) {
if (_path().isAbsolute(name)) return name;
const isPreset = type === "preset";
return name.replace(isPreset ? BABEL_PRESET_PREFIX_RE : BABEL_PLUGIN_PREFIX_RE, `babel-${type}-`).replace(isPreset ? BABEL_PRESET_ORG_RE : BABEL_PLUGIN_ORG_RE, `$1${type}-`).replace(isPreset ? OTHER_PRESET_ORG_RE : OTHER_PLUGIN_ORG_RE, `$1babel-${type}-`).replace(OTHER_ORG_DEFAULT_RE, `$1/babel-${type}`).replace(EXACT_RE, "");
}
function* resolveAlternativesHelper(type, name) {
const standardizedName = standardizeName(type, name);
const {
error,
value
} = yield standardizedName;
if (!error) return value;
if (error.code !== "MODULE_NOT_FOUND") throw error;
if (standardizedName !== name && !(yield name).error) {
error.message += `\n- If you want to resolve "${name}", use "module:${name}"`;
}
if (!(yield standardizeName(type, "@babel/" + name)).error) {
error.message += `\n- Did you mean "@babel/${name}"?`;
}
const oppositeType = type === "preset" ? "plugin" : "preset";
if (!(yield standardizeName(oppositeType, name)).error) {
error.message += `\n- Did you accidentally pass a ${oppositeType} as a ${type}?`;
}
if (type === "plugin") {
const transformName = standardizedName.replace("-proposal-", "-transform-");
if (transformName !== standardizedName && !(yield transformName).error) {
error.message += `\n- Did you mean "${transformName}"?`;
}
}
error.message += `\n
Make sure that all the Babel plugins and presets you are using
are defined as dependencies or devDependencies in your package.json
file. It's possible that the missing plugin is loaded by a preset
you are using that forgot to add the plugin to its dependencies: you
can workaround this problem by explicitly adding the missing package
to your top-level package.json.
`;
throw error;
}
function tryRequireResolve(id, dirname) {
try {
if (dirname) {
return {
error: null,
value: (((v, w) => (v = v.split("."), w = w.split("."), +v[0] > +w[0] || v[0] == w[0] && +v[1] >= +w[1]))(process.versions.node, "8.9") ? require.resolve : (r, {
paths: [b]
}, M = require("module")) => {
let f = M._findPath(r, M._nodeModulePaths(b).concat(b));
if (f) return f;
f = new Error(`Cannot resolve module '${r}'`);
f.code = "MODULE_NOT_FOUND";
throw f;
})(id, {
paths: [dirname]
})
};
} else {
return {
error: null,
value: require.resolve(id)
};
}
} catch (error) {
return {
error,
value: null
};
}
}
function tryImportMetaResolve(id, options) {
try {
return {
error: null,
value: (0, _importMetaResolve.resolve)(id, options)
};
} catch (error) {
return {
error,
value: null
};
}
}
function resolveStandardizedNameForRequire(type, name, dirname) {
const it = resolveAlternativesHelper(type, name);
let res = it.next();
while (!res.done) {
res = it.next(tryRequireResolve(res.value, dirname));
}
return {
loader: "require",
filepath: res.value
};
}
function resolveStandardizedNameForImport(type, name, dirname) {
const parentUrl = (0, _url().pathToFileURL)(_path().join(dirname, "./babel-virtual-resolve-base.js")).href;
const it = resolveAlternativesHelper(type, name);
let res = it.next();
while (!res.done) {
res = it.next(tryImportMetaResolve(res.value, parentUrl));
}
return {
loader: "auto",
filepath: (0, _url().fileURLToPath)(res.value)
};
}
function resolveStandardizedName(type, name, dirname, allowAsync) {
if (!_moduleTypes.supportsESM || !allowAsync) {
return resolveStandardizedNameForRequire(type, name, dirname);
}
try {
const resolved = resolveStandardizedNameForImport(type, name, dirname);
if (!(0, _fs().existsSync)(resolved.filepath)) {
throw Object.assign(new Error(`Could not resolve "${name}" in file ${dirname}.`), {
type: "MODULE_NOT_FOUND"
});
}
return resolved;
} catch (e) {
try {
return resolveStandardizedNameForRequire(type, name, dirname);
} catch (e2) {
if (e.type === "MODULE_NOT_FOUND") throw e;
if (e2.type === "MODULE_NOT_FOUND") throw e2;
throw e;
}
}
}
{
var LOADING_MODULES = new Set();
}
function* requireModule(type, loader, name) {
{
if (!(yield* (0, _async.isAsync)()) && LOADING_MODULES.has(name)) {
throw new Error(`Reentrant ${type} detected trying to load "${name}". This module is not ignored ` + "and is trying to load itself while compiling itself, leading to a dependency cycle. " + 'We recommend adding it to your "ignore" list in your babelrc, or to a .babelignore.');
}
}
try {
{
LOADING_MODULES.add(name);
}
{
return yield* (0, _moduleTypes.default)(name, loader, `You appear to be using a native ECMAScript module ${type}, ` + "which is only supported when running Babel asynchronously " + "or when using the Node.js `--experimental-require-module` flag.", `You appear to be using a ${type} that contains top-level await, ` + "which is only supported when running Babel asynchronously.", true);
}
} catch (err) {
err.message = `[BABEL]: ${err.message} (While processing: ${name})`;
throw err;
} finally {
{
LOADING_MODULES.delete(name);
}
}
}
0 && 0;
//# sourceMappingURL=plugins.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,5 @@
"use strict";
0 && 0;
//# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
{"version":3,"names":[],"sources":["../../../src/config/files/types.ts"],"sourcesContent":["import type { InputOptions } from \"../index.ts\";\n\nexport type ConfigFile = {\n filepath: string;\n dirname: string;\n options: InputOptions & { babel?: unknown };\n};\n\nexport type IgnoreFile = {\n filepath: string;\n dirname: string;\n ignore: Array<RegExp>;\n};\n\nexport type RelativeConfig = {\n // The actual config, either from package.json#babel, .babelrc, or\n // .babelrc.js, if there was one.\n config: ConfigFile | null;\n // The .babelignore, if there was one.\n ignore: IgnoreFile | null;\n};\n\nexport type FilePackageData = {\n // The file in the package.\n filepath: string;\n // Any ancestor directories of the file that are within the package.\n directories: Array<string>;\n // The contents of the package.json. May not be found if the package just\n // terminated at a node_modules folder without finding one.\n pkg: ConfigFile | null;\n // True if a package.json or node_modules folder was found while traversing\n // the directory structure.\n isPackage: boolean;\n};\n"],"mappings":"","ignoreList":[]}
@@ -0,0 +1,36 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.makeStaticFileCache = makeStaticFileCache;
var _caching = require("../caching.js");
var fs = require("../../gensync-utils/fs.js");
function _fs2() {
const data = require("fs");
_fs2 = function () {
return data;
};
return data;
}
function makeStaticFileCache(fn) {
return (0, _caching.makeStrongCache)(function* (filepath, cache) {
const cached = cache.invalidate(() => fileMtime(filepath));
if (cached === null) {
return null;
}
return fn(filepath, yield* fs.readFile(filepath, "utf8"));
});
}
function fileMtime(filepath) {
if (!_fs2().existsSync(filepath)) return null;
try {
return +_fs2().statSync(filepath).mtime;
} catch (e) {
if (e.code !== "ENOENT" && e.code !== "ENOTDIR") throw e;
}
return null;
}
0 && 0;
//# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
{"version":3,"names":["_caching","require","fs","_fs2","data","makeStaticFileCache","fn","makeStrongCache","filepath","cache","cached","invalidate","fileMtime","readFile","nodeFs","existsSync","statSync","mtime","e","code"],"sources":["../../../src/config/files/utils.ts"],"sourcesContent":["import type { Handler } from \"gensync\";\n\nimport { makeStrongCache } from \"../caching.ts\";\nimport type { CacheConfigurator } from \"../caching.ts\";\nimport * as fs from \"../../gensync-utils/fs.ts\";\nimport nodeFs from \"node:fs\";\n\nexport function makeStaticFileCache<T>(\n fn: (filepath: string, contents: string) => T,\n) {\n return makeStrongCache(function* (\n filepath: string,\n cache: CacheConfigurator<void>,\n ): Handler<null | T> {\n const cached = cache.invalidate(() => fileMtime(filepath));\n\n if (cached === null) {\n return null;\n }\n\n return fn(filepath, yield* fs.readFile(filepath, \"utf8\"));\n });\n}\n\nfunction fileMtime(filepath: string): number | null {\n if (!nodeFs.existsSync(filepath)) return null;\n\n try {\n return +nodeFs.statSync(filepath).mtime;\n } catch (e) {\n if (e.code !== \"ENOENT\" && e.code !== \"ENOTDIR\") throw e;\n }\n\n return null;\n}\n"],"mappings":";;;;;;AAEA,IAAAA,QAAA,GAAAC,OAAA;AAEA,IAAAC,EAAA,GAAAD,OAAA;AACA,SAAAE,KAAA;EAAA,MAAAC,IAAA,GAAAH,OAAA;EAAAE,IAAA,YAAAA,CAAA;IAAA,OAAAC,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AAEO,SAASC,mBAAmBA,CACjCC,EAA6C,EAC7C;EACA,OAAO,IAAAC,wBAAe,EAAC,WACrBC,QAAgB,EAChBC,KAA8B,EACX;IACnB,MAAMC,MAAM,GAAGD,KAAK,CAACE,UAAU,CAAC,MAAMC,SAAS,CAACJ,QAAQ,CAAC,CAAC;IAE1D,IAAIE,MAAM,KAAK,IAAI,EAAE;MACnB,OAAO,IAAI;IACb;IAEA,OAAOJ,EAAE,CAACE,QAAQ,EAAE,OAAON,EAAE,CAACW,QAAQ,CAACL,QAAQ,EAAE,MAAM,CAAC,CAAC;EAC3D,CAAC,CAAC;AACJ;AAEA,SAASI,SAASA,CAACJ,QAAgB,EAAiB;EAClD,IAAI,CAACM,KAAKA,CAAC,CAACC,UAAU,CAACP,QAAQ,CAAC,EAAE,OAAO,IAAI;EAE7C,IAAI;IACF,OAAO,CAACM,KAAKA,CAAC,CAACE,QAAQ,CAACR,QAAQ,CAAC,CAACS,KAAK;EACzC,CAAC,CAAC,OAAOC,CAAC,EAAE;IACV,IAAIA,CAAC,CAACC,IAAI,KAAK,QAAQ,IAAID,CAAC,CAACC,IAAI,KAAK,SAAS,EAAE,MAAMD,CAAC;EAC1D;EAEA,OAAO,IAAI;AACb;AAAC","ignoreList":[]}
+312
View File
@@ -0,0 +1,312 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
function _gensync() {
const data = require("gensync");
_gensync = function () {
return data;
};
return data;
}
var _async = require("../gensync-utils/async.js");
var _util = require("./util.js");
var context = require("../index.js");
var _plugin = require("./plugin.js");
var _item = require("./item.js");
var _configChain = require("./config-chain.js");
var _deepArray = require("./helpers/deep-array.js");
function _traverse() {
const data = require("@babel/traverse");
_traverse = function () {
return data;
};
return data;
}
var _caching = require("./caching.js");
var _options = require("./validation/options.js");
var _plugins = require("./validation/plugins.js");
var _configApi = require("./helpers/config-api.js");
var _partial = require("./partial.js");
var _configError = require("../errors/config-error.js");
var _default = exports.default = _gensync()(function* loadFullConfig(inputOpts) {
var _opts$assumptions;
const result = yield* (0, _partial.default)(inputOpts);
if (!result) {
return null;
}
const {
options,
context,
fileHandling
} = result;
if (fileHandling === "ignored") {
return null;
}
const optionDefaults = {};
const {
plugins,
presets
} = options;
if (!plugins || !presets) {
throw new Error("Assertion failure - plugins and presets exist");
}
const presetContext = Object.assign({}, context, {
targets: options.targets
});
const toDescriptor = item => {
const desc = (0, _item.getItemDescriptor)(item);
if (!desc) {
throw new Error("Assertion failure - must be config item");
}
return desc;
};
const presetsDescriptors = presets.map(toDescriptor);
const initialPluginsDescriptors = plugins.map(toDescriptor);
const pluginDescriptorsByPass = [[]];
const passes = [];
const externalDependencies = [];
const ignored = yield* enhanceError(context, function* recursePresetDescriptors(rawPresets, pluginDescriptorsPass) {
const presets = [];
for (let i = 0; i < rawPresets.length; i++) {
const descriptor = rawPresets[i];
if (descriptor.options !== false) {
try {
var preset = yield* loadPresetDescriptor(descriptor, presetContext);
} catch (e) {
if (e.code === "BABEL_UNKNOWN_OPTION") {
(0, _options.checkNoUnwrappedItemOptionPairs)(rawPresets, i, "preset", e);
}
throw e;
}
externalDependencies.push(preset.externalDependencies);
if (descriptor.ownPass) {
presets.push({
preset: preset.chain,
pass: []
});
} else {
presets.unshift({
preset: preset.chain,
pass: pluginDescriptorsPass
});
}
}
}
if (presets.length > 0) {
pluginDescriptorsByPass.splice(1, 0, ...presets.map(o => o.pass).filter(p => p !== pluginDescriptorsPass));
for (const {
preset,
pass
} of presets) {
if (!preset) return true;
pass.push(...preset.plugins);
const ignored = yield* recursePresetDescriptors(preset.presets, pass);
if (ignored) return true;
preset.options.forEach(opts => {
(0, _util.mergeOptions)(optionDefaults, opts);
});
}
}
})(presetsDescriptors, pluginDescriptorsByPass[0]);
if (ignored) return null;
const opts = optionDefaults;
(0, _util.mergeOptions)(opts, options);
const pluginContext = Object.assign({}, presetContext, {
assumptions: (_opts$assumptions = opts.assumptions) != null ? _opts$assumptions : {}
});
yield* enhanceError(context, function* loadPluginDescriptors() {
pluginDescriptorsByPass[0].unshift(...initialPluginsDescriptors);
for (const descs of pluginDescriptorsByPass) {
const pass = [];
passes.push(pass);
for (let i = 0; i < descs.length; i++) {
const descriptor = descs[i];
if (descriptor.options !== false) {
try {
var plugin = yield* loadPluginDescriptor(descriptor, pluginContext);
} catch (e) {
if (e.code === "BABEL_UNKNOWN_PLUGIN_PROPERTY") {
(0, _options.checkNoUnwrappedItemOptionPairs)(descs, i, "plugin", e);
}
throw e;
}
pass.push(plugin);
externalDependencies.push(plugin.externalDependencies);
}
}
}
})();
opts.plugins = passes[0];
opts.presets = passes.slice(1).filter(plugins => plugins.length > 0).map(plugins => ({
plugins
}));
opts.passPerPreset = opts.presets.length > 0;
return {
options: opts,
passes: passes,
externalDependencies: (0, _deepArray.finalize)(externalDependencies)
};
});
function enhanceError(context, fn) {
return function* (arg1, arg2) {
try {
return yield* fn(arg1, arg2);
} catch (e) {
if (!/^\[BABEL\]/.test(e.message)) {
var _context$filename;
e.message = `[BABEL] ${(_context$filename = context.filename) != null ? _context$filename : "unknown file"}: ${e.message}`;
}
throw e;
}
};
}
const makeDescriptorLoader = apiFactory => (0, _caching.makeWeakCache)(function* ({
value,
options,
dirname,
alias
}, cache) {
if (options === false) throw new Error("Assertion failure");
options = options || {};
const externalDependencies = [];
let item = value;
if (typeof value === "function") {
const factory = (0, _async.maybeAsync)(value, `You appear to be using an async plugin/preset, but Babel has been called synchronously`);
const api = Object.assign({}, context, apiFactory(cache, externalDependencies));
try {
item = yield* factory(api, options, dirname);
} catch (e) {
if (alias) {
e.message += ` (While processing: ${JSON.stringify(alias)})`;
}
throw e;
}
}
if (!item || typeof item !== "object") {
throw new Error("Plugin/Preset did not return an object.");
}
if ((0, _async.isThenable)(item)) {
yield* [];
throw new Error(`You appear to be using a promise as a plugin, ` + `which your current version of Babel does not support. ` + `If you're using a published plugin, ` + `you may need to upgrade your @babel/core version. ` + `As an alternative, you can prefix the promise with "await". ` + `(While processing: ${JSON.stringify(alias)})`);
}
if (externalDependencies.length > 0 && (!cache.configured() || cache.mode() === "forever")) {
let error = `A plugin/preset has external untracked dependencies ` + `(${externalDependencies[0]}), but the cache `;
if (!cache.configured()) {
error += `has not been configured to be invalidated when the external dependencies change. `;
} else {
error += ` has been configured to never be invalidated. `;
}
error += `Plugins/presets should configure their cache to be invalidated when the external ` + `dependencies change, for example using \`api.cache.invalidate(() => ` + `statSync(filepath).mtimeMs)\` or \`api.cache.never()\`\n` + `(While processing: ${JSON.stringify(alias)})`;
throw new Error(error);
}
return {
value: item,
options,
dirname,
alias,
externalDependencies: (0, _deepArray.finalize)(externalDependencies)
};
});
const pluginDescriptorLoader = makeDescriptorLoader(_configApi.makePluginAPI);
const presetDescriptorLoader = makeDescriptorLoader(_configApi.makePresetAPI);
const instantiatePlugin = (0, _caching.makeWeakCache)(function* ({
value,
options,
dirname,
alias,
externalDependencies
}, cache) {
const pluginObj = (0, _plugins.validatePluginObject)(value);
const plugin = Object.assign({}, pluginObj);
if (plugin.visitor) {
plugin.visitor = _traverse().default.explode(Object.assign({}, plugin.visitor));
}
if (plugin.inherits) {
const inheritsDescriptor = {
name: undefined,
alias: `${alias}$inherits`,
value: plugin.inherits,
options,
dirname
};
const inherits = yield* (0, _async.forwardAsync)(loadPluginDescriptor, run => {
return cache.invalidate(data => run(inheritsDescriptor, data));
});
plugin.pre = chainMaybeAsync(inherits.pre, plugin.pre);
plugin.post = chainMaybeAsync(inherits.post, plugin.post);
plugin.manipulateOptions = chainMaybeAsync(inherits.manipulateOptions, plugin.manipulateOptions);
plugin.visitor = _traverse().default.visitors.merge([inherits.visitor || {}, plugin.visitor || {}]);
if (inherits.externalDependencies.length > 0) {
if (externalDependencies.length === 0) {
externalDependencies = inherits.externalDependencies;
} else {
externalDependencies = (0, _deepArray.finalize)([externalDependencies, inherits.externalDependencies]);
}
}
}
return new _plugin.default(plugin, options, alias, externalDependencies);
});
function* loadPluginDescriptor(descriptor, context) {
if (descriptor.value instanceof _plugin.default) {
if (descriptor.options) {
throw new Error("Passed options to an existing Plugin instance will not work.");
}
return descriptor.value;
}
return yield* instantiatePlugin(yield* pluginDescriptorLoader(descriptor, context), context);
}
const needsFilename = val => val && typeof val !== "function";
const validateIfOptionNeedsFilename = (options, descriptor) => {
if (needsFilename(options.test) || needsFilename(options.include) || needsFilename(options.exclude)) {
const formattedPresetName = descriptor.name ? `"${descriptor.name}"` : "/* your preset */";
throw new _configError.default([`Preset ${formattedPresetName} requires a filename to be set when babel is called directly,`, `\`\`\``, `babel.transformSync(code, { filename: 'file.ts', presets: [${formattedPresetName}] });`, `\`\`\``, `See https://babeljs.io/docs/en/options#filename for more information.`].join("\n"));
}
};
const validatePreset = (preset, context, descriptor) => {
if (!context.filename) {
var _options$overrides;
const {
options
} = preset;
validateIfOptionNeedsFilename(options, descriptor);
(_options$overrides = options.overrides) == null || _options$overrides.forEach(overrideOptions => validateIfOptionNeedsFilename(overrideOptions, descriptor));
}
};
const instantiatePreset = (0, _caching.makeWeakCacheSync)(({
value,
dirname,
alias,
externalDependencies
}) => {
return {
options: (0, _options.validate)("preset", value),
alias,
dirname,
externalDependencies
};
});
function* loadPresetDescriptor(descriptor, context) {
const preset = instantiatePreset(yield* presetDescriptorLoader(descriptor, context));
validatePreset(preset, context, descriptor);
return {
chain: yield* (0, _configChain.buildPresetChain)(preset, context),
externalDependencies: preset.externalDependencies
};
}
function chainMaybeAsync(a, b) {
if (!a) return b;
if (!b) return a;
return function (...args) {
const res = a.apply(this, args);
if (res && typeof res.then === "function") {
return res.then(() => b.apply(this, args));
}
return b.apply(this, args);
};
}
0 && 0;
//# sourceMappingURL=full.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,84 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.makeConfigAPI = makeConfigAPI;
exports.makePluginAPI = makePluginAPI;
exports.makePresetAPI = makePresetAPI;
function _semver() {
const data = require("semver");
_semver = function () {
return data;
};
return data;
}
var _index = require("../../index.js");
var _caching = require("../caching.js");
function makeConfigAPI(cache) {
const env = value => cache.using(data => {
if (value === undefined) return data.envName;
if (typeof value === "function") {
return (0, _caching.assertSimpleType)(value(data.envName));
}
return (Array.isArray(value) ? value : [value]).some(entry => {
if (typeof entry !== "string") {
throw new Error("Unexpected non-string value");
}
return entry === data.envName;
});
});
const caller = cb => cache.using(data => (0, _caching.assertSimpleType)(cb(data.caller)));
return {
version: _index.version,
cache: cache.simple(),
env,
async: () => false,
caller,
assertVersion
};
}
function makePresetAPI(cache, externalDependencies) {
const targets = () => JSON.parse(cache.using(data => JSON.stringify(data.targets)));
const addExternalDependency = ref => {
externalDependencies.push(ref);
};
return Object.assign({}, makeConfigAPI(cache), {
targets,
addExternalDependency
});
}
function makePluginAPI(cache, externalDependencies) {
const assumption = name => cache.using(data => data.assumptions[name]);
return Object.assign({}, makePresetAPI(cache, externalDependencies), {
assumption
});
}
function assertVersion(range) {
if (typeof range === "number") {
if (!Number.isInteger(range)) {
throw new Error("Expected string or integer value.");
}
range = `^${range}.0.0-0`;
}
if (typeof range !== "string") {
throw new Error("Expected string or integer value.");
}
if (range === "*" || _semver().satisfies(_index.version, range)) return;
const limit = Error.stackTraceLimit;
if (typeof limit === "number" && limit < 25) {
Error.stackTraceLimit = 25;
}
const err = new Error(`Requires Babel "${range}", but was loaded with "${_index.version}". ` + `If you are sure you have a compatible version of @babel/core, ` + `it is likely that something in your build process is loading the ` + `wrong version. Inspect the stack trace of this error to look for ` + `the first entry that doesn't mention "@babel/core" or "babel-core" ` + `to see what is calling Babel.`);
if (typeof limit === "number") {
Error.stackTraceLimit = limit;
}
throw Object.assign(err, {
code: "BABEL_VERSION_UNSUPPORTED",
version: _index.version,
range
});
}
0 && 0;
//# sourceMappingURL=config-api.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,23 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.finalize = finalize;
exports.flattenToSet = flattenToSet;
function finalize(deepArr) {
return Object.freeze(deepArr);
}
function flattenToSet(arr) {
const result = new Set();
const stack = [arr];
while (stack.length > 0) {
for (const el of stack.pop()) {
if (Array.isArray(el)) stack.push(el);else result.add(el);
}
}
return result;
}
0 && 0;
//# sourceMappingURL=deep-array.js.map
@@ -0,0 +1 @@
{"version":3,"names":["finalize","deepArr","Object","freeze","flattenToSet","arr","result","Set","stack","length","el","pop","Array","isArray","push","add"],"sources":["../../../src/config/helpers/deep-array.ts"],"sourcesContent":["export type DeepArray<T> = Array<T | ReadonlyDeepArray<T>>;\n\n// Just to make sure that DeepArray<T> is not assignable to ReadonlyDeepArray<T>\ndeclare const __marker: unique symbol;\nexport type ReadonlyDeepArray<T> = ReadonlyArray<T | ReadonlyDeepArray<T>> & {\n [__marker]: true;\n};\n\nexport function finalize<T>(deepArr: DeepArray<T>): ReadonlyDeepArray<T> {\n return Object.freeze(deepArr) as ReadonlyDeepArray<T>;\n}\n\nexport function flattenToSet<T extends string>(\n arr: ReadonlyDeepArray<T>,\n): Set<T> {\n const result = new Set<T>();\n const stack = [arr];\n while (stack.length > 0) {\n for (const el of stack.pop()) {\n if (Array.isArray(el)) stack.push(el as ReadonlyDeepArray<T>);\n else result.add(el as T);\n }\n }\n return result;\n}\n"],"mappings":";;;;;;;AAQO,SAASA,QAAQA,CAAIC,OAAqB,EAAwB;EACvE,OAAOC,MAAM,CAACC,MAAM,CAACF,OAAO,CAAC;AAC/B;AAEO,SAASG,YAAYA,CAC1BC,GAAyB,EACjB;EACR,MAAMC,MAAM,GAAG,IAAIC,GAAG,CAAI,CAAC;EAC3B,MAAMC,KAAK,GAAG,CAACH,GAAG,CAAC;EACnB,OAAOG,KAAK,CAACC,MAAM,GAAG,CAAC,EAAE;IACvB,KAAK,MAAMC,EAAE,IAAIF,KAAK,CAACG,GAAG,CAAC,CAAC,EAAE;MAC5B,IAAIC,KAAK,CAACC,OAAO,CAACH,EAAE,CAAC,EAAEF,KAAK,CAACM,IAAI,CAACJ,EAA0B,CAAC,CAAC,KACzDJ,MAAM,CAACS,GAAG,CAACL,EAAO,CAAC;IAC1B;EACF;EACA,OAAOJ,MAAM;AACf;AAAC","ignoreList":[]}
@@ -0,0 +1,12 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getEnv = getEnv;
function getEnv(defaultValue = "development") {
return process.env.BABEL_ENV || process.env.NODE_ENV || defaultValue;
}
0 && 0;
//# sourceMappingURL=environment.js.map
@@ -0,0 +1 @@
{"version":3,"names":["getEnv","defaultValue","process","env","BABEL_ENV","NODE_ENV"],"sources":["../../../src/config/helpers/environment.ts"],"sourcesContent":["export function getEnv(defaultValue: string = \"development\"): string {\n return process.env.BABEL_ENV || process.env.NODE_ENV || defaultValue;\n}\n"],"mappings":";;;;;;AAAO,SAASA,MAAMA,CAACC,YAAoB,GAAG,aAAa,EAAU;EACnE,OAAOC,OAAO,CAACC,GAAG,CAACC,SAAS,IAAIF,OAAO,CAACC,GAAG,CAACE,QAAQ,IAAIJ,YAAY;AACtE;AAAC","ignoreList":[]}
@@ -0,0 +1,93 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.createConfigItem = createConfigItem;
exports.createConfigItemAsync = createConfigItemAsync;
exports.createConfigItemSync = createConfigItemSync;
Object.defineProperty(exports, "default", {
enumerable: true,
get: function () {
return _full.default;
}
});
exports.loadOptions = loadOptions;
exports.loadOptionsAsync = loadOptionsAsync;
exports.loadOptionsSync = loadOptionsSync;
exports.loadPartialConfig = loadPartialConfig;
exports.loadPartialConfigAsync = loadPartialConfigAsync;
exports.loadPartialConfigSync = loadPartialConfigSync;
function _gensync() {
const data = require("gensync");
_gensync = function () {
return data;
};
return data;
}
var _full = require("./full.js");
var _partial = require("./partial.js");
var _item = require("./item.js");
var _rewriteStackTrace = require("../errors/rewrite-stack-trace.js");
const loadPartialConfigRunner = _gensync()(_partial.loadPartialConfig);
function loadPartialConfigAsync(...args) {
return (0, _rewriteStackTrace.beginHiddenCallStack)(loadPartialConfigRunner.async)(...args);
}
function loadPartialConfigSync(...args) {
return (0, _rewriteStackTrace.beginHiddenCallStack)(loadPartialConfigRunner.sync)(...args);
}
function loadPartialConfig(opts, callback) {
if (callback !== undefined) {
(0, _rewriteStackTrace.beginHiddenCallStack)(loadPartialConfigRunner.errback)(opts, callback);
} else if (typeof opts === "function") {
(0, _rewriteStackTrace.beginHiddenCallStack)(loadPartialConfigRunner.errback)(undefined, opts);
} else {
{
return loadPartialConfigSync(opts);
}
}
}
function* loadOptionsImpl(opts) {
var _config$options;
const config = yield* (0, _full.default)(opts);
return (_config$options = config == null ? void 0 : config.options) != null ? _config$options : null;
}
const loadOptionsRunner = _gensync()(loadOptionsImpl);
function loadOptionsAsync(...args) {
return (0, _rewriteStackTrace.beginHiddenCallStack)(loadOptionsRunner.async)(...args);
}
function loadOptionsSync(...args) {
return (0, _rewriteStackTrace.beginHiddenCallStack)(loadOptionsRunner.sync)(...args);
}
function loadOptions(opts, callback) {
if (callback !== undefined) {
(0, _rewriteStackTrace.beginHiddenCallStack)(loadOptionsRunner.errback)(opts, callback);
} else if (typeof opts === "function") {
(0, _rewriteStackTrace.beginHiddenCallStack)(loadOptionsRunner.errback)(undefined, opts);
} else {
{
return loadOptionsSync(opts);
}
}
}
const createConfigItemRunner = _gensync()(_item.createConfigItem);
function createConfigItemAsync(...args) {
return (0, _rewriteStackTrace.beginHiddenCallStack)(createConfigItemRunner.async)(...args);
}
function createConfigItemSync(...args) {
return (0, _rewriteStackTrace.beginHiddenCallStack)(createConfigItemRunner.sync)(...args);
}
function createConfigItem(target, options, callback) {
if (callback !== undefined) {
(0, _rewriteStackTrace.beginHiddenCallStack)(createConfigItemRunner.errback)(target, options, callback);
} else if (typeof options === "function") {
(0, _rewriteStackTrace.beginHiddenCallStack)(createConfigItemRunner.errback)(target, undefined, callback);
} else {
{
return createConfigItemSync(target, options);
}
}
}
0 && 0;
//# sourceMappingURL=index.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,67 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.createConfigItem = createConfigItem;
exports.createItemFromDescriptor = createItemFromDescriptor;
exports.getItemDescriptor = getItemDescriptor;
function _path() {
const data = require("path");
_path = function () {
return data;
};
return data;
}
var _configDescriptors = require("./config-descriptors.js");
function createItemFromDescriptor(desc) {
return new ConfigItem(desc);
}
function* createConfigItem(value, {
dirname = ".",
type
} = {}) {
const descriptor = yield* (0, _configDescriptors.createDescriptor)(value, _path().resolve(dirname), {
type,
alias: "programmatic item"
});
return createItemFromDescriptor(descriptor);
}
const CONFIG_ITEM_BRAND = Symbol.for("@babel/core@7 - ConfigItem");
function getItemDescriptor(item) {
if (item != null && item[CONFIG_ITEM_BRAND]) {
return item._descriptor;
}
return undefined;
}
class ConfigItem {
constructor(descriptor) {
this._descriptor = void 0;
this[CONFIG_ITEM_BRAND] = true;
this.value = void 0;
this.options = void 0;
this.dirname = void 0;
this.name = void 0;
this.file = void 0;
this._descriptor = descriptor;
Object.defineProperty(this, "_descriptor", {
enumerable: false
});
Object.defineProperty(this, CONFIG_ITEM_BRAND, {
enumerable: false
});
this.value = this._descriptor.value;
this.options = this._descriptor.options;
this.dirname = this._descriptor.dirname;
this.name = this._descriptor.name;
this.file = this._descriptor.file ? {
request: this._descriptor.file.request,
resolved: this._descriptor.file.resolved
} : undefined;
Object.freeze(this);
}
}
Object.freeze(ConfigItem.prototype);
0 && 0;
//# sourceMappingURL=item.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,158 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = loadPrivatePartialConfig;
exports.loadPartialConfig = loadPartialConfig;
function _path() {
const data = require("path");
_path = function () {
return data;
};
return data;
}
var _plugin = require("./plugin.js");
var _util = require("./util.js");
var _item = require("./item.js");
var _configChain = require("./config-chain.js");
var _environment = require("./helpers/environment.js");
var _options = require("./validation/options.js");
var _index = require("./files/index.js");
var _resolveTargets = require("./resolve-targets.js");
const _excluded = ["showIgnoredFiles"];
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
function resolveRootMode(rootDir, rootMode) {
switch (rootMode) {
case "root":
return rootDir;
case "upward-optional":
{
const upwardRootDir = (0, _index.findConfigUpwards)(rootDir);
return upwardRootDir === null ? rootDir : upwardRootDir;
}
case "upward":
{
const upwardRootDir = (0, _index.findConfigUpwards)(rootDir);
if (upwardRootDir !== null) return upwardRootDir;
throw Object.assign(new Error(`Babel was run with rootMode:"upward" but a root could not ` + `be found when searching upward from "${rootDir}".\n` + `One of the following config files must be in the directory tree: ` + `"${_index.ROOT_CONFIG_FILENAMES.join(", ")}".`), {
code: "BABEL_ROOT_NOT_FOUND",
dirname: rootDir
});
}
default:
throw new Error(`Assertion failure - unknown rootMode value.`);
}
}
function* loadPrivatePartialConfig(inputOpts) {
if (inputOpts != null && (typeof inputOpts !== "object" || Array.isArray(inputOpts))) {
throw new Error("Babel options must be an object, null, or undefined");
}
const args = inputOpts ? (0, _options.validate)("arguments", inputOpts) : {};
const {
envName = (0, _environment.getEnv)(),
cwd = ".",
root: rootDir = ".",
rootMode = "root",
caller,
cloneInputAst = true
} = args;
const absoluteCwd = _path().resolve(cwd);
const absoluteRootDir = resolveRootMode(_path().resolve(absoluteCwd, rootDir), rootMode);
const filename = typeof args.filename === "string" ? _path().resolve(cwd, args.filename) : undefined;
const showConfigPath = yield* (0, _index.resolveShowConfigPath)(absoluteCwd);
const context = {
filename,
cwd: absoluteCwd,
root: absoluteRootDir,
envName,
caller,
showConfig: showConfigPath === filename
};
const configChain = yield* (0, _configChain.buildRootChain)(args, context);
if (!configChain) return null;
const merged = {
assumptions: {}
};
configChain.options.forEach(opts => {
(0, _util.mergeOptions)(merged, opts);
});
const options = Object.assign({}, merged, {
targets: (0, _resolveTargets.resolveTargets)(merged, absoluteRootDir),
cloneInputAst,
babelrc: false,
configFile: false,
browserslistConfigFile: false,
passPerPreset: false,
envName: context.envName,
cwd: context.cwd,
root: context.root,
rootMode: "root",
filename: typeof context.filename === "string" ? context.filename : undefined,
plugins: configChain.plugins.map(descriptor => (0, _item.createItemFromDescriptor)(descriptor)),
presets: configChain.presets.map(descriptor => (0, _item.createItemFromDescriptor)(descriptor))
});
return {
options,
context,
fileHandling: configChain.fileHandling,
ignore: configChain.ignore,
babelrc: configChain.babelrc,
config: configChain.config,
files: configChain.files
};
}
function* loadPartialConfig(opts) {
let showIgnoredFiles = false;
if (typeof opts === "object" && opts !== null && !Array.isArray(opts)) {
var _opts = opts;
({
showIgnoredFiles
} = _opts);
opts = _objectWithoutPropertiesLoose(_opts, _excluded);
_opts;
}
const result = yield* loadPrivatePartialConfig(opts);
if (!result) return null;
const {
options,
babelrc,
ignore,
config,
fileHandling,
files
} = result;
if (fileHandling === "ignored" && !showIgnoredFiles) {
return null;
}
(options.plugins || []).forEach(item => {
if (item.value instanceof _plugin.default) {
throw new Error("Passing cached plugin instances is not supported in " + "babel.loadPartialConfig()");
}
});
return new PartialConfig(options, babelrc ? babelrc.filepath : undefined, ignore ? ignore.filepath : undefined, config ? config.filepath : undefined, fileHandling, files);
}
class PartialConfig {
constructor(options, babelrc, ignore, config, fileHandling, files) {
this.options = void 0;
this.babelrc = void 0;
this.babelignore = void 0;
this.config = void 0;
this.fileHandling = void 0;
this.files = void 0;
this.options = options;
this.babelignore = ignore;
this.babelrc = babelrc;
this.config = config;
this.fileHandling = fileHandling;
this.files = files;
Object.freeze(this);
}
hasFilesystemConfig() {
return this.babelrc !== undefined || this.config !== undefined;
}
}
Object.freeze(PartialConfig.prototype);
0 && 0;
//# sourceMappingURL=partial.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,38 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = pathToPattern;
function _path() {
const data = require("path");
_path = function () {
return data;
};
return data;
}
const sep = `\\${_path().sep}`;
const endSep = `(?:${sep}|$)`;
const substitution = `[^${sep}]+`;
const starPat = `(?:${substitution}${sep})`;
const starPatLast = `(?:${substitution}${endSep})`;
const starStarPat = `${starPat}*?`;
const starStarPatLast = `${starPat}*?${starPatLast}?`;
function escapeRegExp(string) {
return string.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&");
}
function pathToPattern(pattern, dirname) {
const parts = _path().resolve(dirname, pattern).split(_path().sep);
return new RegExp(["^", ...parts.map((part, i) => {
const last = i === parts.length - 1;
if (part === "**") return last ? starStarPatLast : starStarPat;
if (part === "*") return last ? starPatLast : starPat;
if (part.indexOf("*.") === 0) {
return substitution + escapeRegExp(part.slice(1)) + (last ? endSep : sep);
}
return escapeRegExp(part) + (last ? endSep : sep);
})].join(""));
}
0 && 0;
//# sourceMappingURL=pattern-to-regex.js.map
@@ -0,0 +1 @@
{"version":3,"names":["_path","data","require","sep","path","endSep","substitution","starPat","starPatLast","starStarPat","starStarPatLast","escapeRegExp","string","replace","pathToPattern","pattern","dirname","parts","resolve","split","RegExp","map","part","i","last","length","indexOf","slice","join"],"sources":["../../src/config/pattern-to-regex.ts"],"sourcesContent":["import path from \"node:path\";\n\nconst sep = `\\\\${path.sep}`;\nconst endSep = `(?:${sep}|$)`;\n\nconst substitution = `[^${sep}]+`;\n\nconst starPat = `(?:${substitution}${sep})`;\nconst starPatLast = `(?:${substitution}${endSep})`;\n\nconst starStarPat = `${starPat}*?`;\nconst starStarPatLast = `${starPat}*?${starPatLast}?`;\n\nfunction escapeRegExp(string: string) {\n return string.replace(/[|\\\\{}()[\\]^$+*?.]/g, \"\\\\$&\");\n}\n\n/**\n * Implement basic pattern matching that will allow users to do the simple\n * tests with * and **. If users want full complex pattern matching, then can\n * always use regex matching, or function validation.\n */\nexport default function pathToPattern(\n pattern: string,\n dirname: string,\n): RegExp {\n const parts = path.resolve(dirname, pattern).split(path.sep);\n\n return new RegExp(\n [\n \"^\",\n ...parts.map((part, i) => {\n const last = i === parts.length - 1;\n\n // ** matches 0 or more path parts.\n if (part === \"**\") return last ? starStarPatLast : starStarPat;\n\n // * matches 1 path part.\n if (part === \"*\") return last ? starPatLast : starPat;\n\n // *.ext matches a wildcard with an extension.\n if (part.indexOf(\"*.\") === 0) {\n return (\n substitution + escapeRegExp(part.slice(1)) + (last ? endSep : sep)\n );\n }\n\n // Otherwise match the pattern text.\n return escapeRegExp(part) + (last ? endSep : sep);\n }),\n ].join(\"\"),\n );\n}\n"],"mappings":";;;;;;AAAA,SAAAA,MAAA;EAAA,MAAAC,IAAA,GAAAC,OAAA;EAAAF,KAAA,YAAAA,CAAA;IAAA,OAAAC,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AAEA,MAAME,GAAG,GAAG,KAAKC,MAAGA,CAAC,CAACD,GAAG,EAAE;AAC3B,MAAME,MAAM,GAAG,MAAMF,GAAG,KAAK;AAE7B,MAAMG,YAAY,GAAG,KAAKH,GAAG,IAAI;AAEjC,MAAMI,OAAO,GAAG,MAAMD,YAAY,GAAGH,GAAG,GAAG;AAC3C,MAAMK,WAAW,GAAG,MAAMF,YAAY,GAAGD,MAAM,GAAG;AAElD,MAAMI,WAAW,GAAG,GAAGF,OAAO,IAAI;AAClC,MAAMG,eAAe,GAAG,GAAGH,OAAO,KAAKC,WAAW,GAAG;AAErD,SAASG,YAAYA,CAACC,MAAc,EAAE;EACpC,OAAOA,MAAM,CAACC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC;AACtD;AAOe,SAASC,aAAaA,CACnCC,OAAe,EACfC,OAAe,EACP;EACR,MAAMC,KAAK,GAAGb,MAAGA,CAAC,CAACc,OAAO,CAACF,OAAO,EAAED,OAAO,CAAC,CAACI,KAAK,CAACf,MAAGA,CAAC,CAACD,GAAG,CAAC;EAE5D,OAAO,IAAIiB,MAAM,CACf,CACE,GAAG,EACH,GAAGH,KAAK,CAACI,GAAG,CAAC,CAACC,IAAI,EAAEC,CAAC,KAAK;IACxB,MAAMC,IAAI,GAAGD,CAAC,KAAKN,KAAK,CAACQ,MAAM,GAAG,CAAC;IAGnC,IAAIH,IAAI,KAAK,IAAI,EAAE,OAAOE,IAAI,GAAGd,eAAe,GAAGD,WAAW;IAG9D,IAAIa,IAAI,KAAK,GAAG,EAAE,OAAOE,IAAI,GAAGhB,WAAW,GAAGD,OAAO;IAGrD,IAAIe,IAAI,CAACI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;MAC5B,OACEpB,YAAY,GAAGK,YAAY,CAACW,IAAI,CAACK,KAAK,CAAC,CAAC,CAAC,CAAC,IAAIH,IAAI,GAAGnB,MAAM,GAAGF,GAAG,CAAC;IAEtE;IAGA,OAAOQ,YAAY,CAACW,IAAI,CAAC,IAAIE,IAAI,GAAGnB,MAAM,GAAGF,GAAG,CAAC;EACnD,CAAC,CAAC,CACH,CAACyB,IAAI,CAAC,EAAE,CACX,CAAC;AACH;AAAC","ignoreList":[]}
@@ -0,0 +1,33 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _deepArray = require("./helpers/deep-array.js");
class Plugin {
constructor(plugin, options, key, externalDependencies = (0, _deepArray.finalize)([])) {
this.key = void 0;
this.manipulateOptions = void 0;
this.post = void 0;
this.pre = void 0;
this.visitor = void 0;
this.parserOverride = void 0;
this.generatorOverride = void 0;
this.options = void 0;
this.externalDependencies = void 0;
this.key = plugin.name || key;
this.manipulateOptions = plugin.manipulateOptions;
this.post = plugin.post;
this.pre = plugin.pre;
this.visitor = plugin.visitor || {};
this.parserOverride = plugin.parserOverride;
this.generatorOverride = plugin.generatorOverride;
this.options = options;
this.externalDependencies = externalDependencies;
}
}
exports.default = Plugin;
0 && 0;
//# sourceMappingURL=plugin.js.map

Some files were not shown because too many files have changed in this diff Show More