Files
amayo/README/ENVMANAGER_Y_MEJORAS.md

505 lines
11 KiB
Markdown
Raw Normal View History

# 📋 Resumen de Mejoras - EnvManager y Sistema de Archivos
## 🎯 Problemas Resueltos
### 1. ❌ Problema de Eliminación de Archivos
**Problema:** No se podían eliminar archivos, no estaba claro si era por permisos.
**Solución Implementada:**
- ✅ Mejorado el manejo de errores en `delete_file` y `delete_folder` (Rust)
- ✅ Ahora muestra mensajes específicos según el tipo de error:
- **Permiso denegado**: "Ejecuta el editor como administrador"
- **Archivo no encontrado**: "El archivo no existe"
- **No es un archivo**: "La ruta no es un archivo válido"
**Ubicación:** `AEditor/src-tauri/src/lib.rs` líneas 468-525
**Cómo usar:**
```bash
# Si ves "Permiso denegado", ejecuta como administrador:
# Windows: Click derecho → Ejecutar como administrador
# O usa PowerShell con privilegios elevados
```
---
### 2. 🔐 Problema del EnvManager
**Problema:**
- No leía correctamente el .env
- No guardaba bien los cambios
- No mostraba las ubicaciones exactas donde se usan las variables
**Soluciones Implementadas:**
#### a) Lectura Mejorada
```typescript
// Ahora con logs detallados para debugging
console.log('📂 Cargando .env desde:', props.projectRoot);
console.log('✅ .env cargado, contenido:', content);
```
#### b) Parseo Mejorado
- ✅ Acepta valores vacíos: `KEY=`
- ✅ Maneja comillas: `KEY="value with spaces"`
- ✅ Ignora comentarios: `# This is a comment`
- ✅ Valida nombres de variables: Solo `A-Z`, `0-9`, `_`
#### c) Guardado Mejorado
```typescript
// Ahora sincroniza antes de guardar para evitar pérdida de datos
isUpdatingRaw.value = true;
parseEnvContent(rawEnvContent.value);
await nextTick();
isUpdatingRaw.value = false;
```
#### d) **NUEVO:** Ubicaciones Exactas
**Backend Rust - Nueva función:**
```rust
#[tauri::command]
fn scan_env_variables_with_locations(project_root: String) -> Result<Vec<VarLocation>, String>
```
**Devuelve:**
```json
[
{
"variable": "DATABASE_URL",
"file": "src/prisma.ts",
"line": 5,
"snippet": "const url = process.env.DATABASE_URL"
},
{
"variable": "API_KEY",
"file": "src/server/api.ts",
"line": 12,
"snippet": "headers: { 'X-API-Key': process.env.API_KEY }"
}
]
```
**Vista en el UI:**
```
📍 Usada en 2 ubicación(es)
├─ src/prisma.ts:5 → const url = process.env.DATABASE_URL
└─ src/server/api.ts:12 → headers: { 'X-API-Key': process.env.API_KEY }
```
---
## 📚 Documentación de Funciones
### 🔍 `loadEnvFile()`
**¿Qué hace?**
1. Lee el archivo .env del proyecto
2. Muestra el contenido en el editor raw
3. Parsea las variables al formato de objetos
4. Si no existe, inicia vacío
**Errores comunes:**
- `No such file`: Normal en proyectos nuevos
- `Permission denied`: Necesitas permisos de admin
---
### 🔍 `parseEnvContent(content, markAsChanged)`
**¿Qué hace?**
Convierte texto plano a objeto JavaScript.
**Ejemplo:**
```env
# Input (texto)
DATABASE_URL=postgres://localhost:5432
API_KEY="abc123"
DEBUG=true
# Output (objeto)
{
"DATABASE_URL": "postgres://localhost:5432",
"API_KEY": "abc123",
"DEBUG": "true"
}
```
**Reglas:**
- Ignora líneas que empiezan con `#`
- Ignora líneas vacías
- Remueve comillas del valor
- Solo acepta claves válidas: `[A-Z_][A-Z0-9_]*`
---
### 🔍 `scanProjectVars()`
**¿Qué hace?**
Busca en todo el código fuente las variables de entorno.
**Proceso:**
1. Escanea archivos `.ts`, `.js`, `.prisma`
2. Busca patrones: `process.env.VARIABLE_NAME`
3. Devuelve ubicaciones exactas (archivo, línea, código)
4. Auto-agrega variables faltantes
**Ejemplo de uso:**
```typescript
// En tu código:
const dbUrl = process.env.DATABASE_URL;
const apiKey = process.env.API_KEY;
// EnvManager detecta:
// ✅ DATABASE_URL (src/prisma.ts:5)
// ✅ API_KEY (src/server/api.ts:12)
```
---
### 🔍 `updateRawContent()`
**¿Qué hace?**
Convierte el objeto de variables a texto plano.
**Reglas de formato:**
- Si el valor tiene espacios → agrega comillas: `KEY="value with spaces"`
- Si no tiene espacios → sin comillas: `KEY=value`
- Si tiene `#` o `=` → agrega comillas: `KEY="value#123"`
---
### 🔍 `syncFromRaw()`
**¿Qué hace?**
Sincroniza del editor raw al formulario.
**¿Por qué el flag `isUpdatingRaw`?**
**Sin flag (loop infinito):**
```
1. Cambias raw → se parsea → actualiza envVariables
2. Watch de envVariables → actualiza raw
3. raw cambia → se parsea → actualiza envVariables
4. Watch de envVariables → actualiza raw
5. Loop infinito 💥
```
**Con flag (correcto):**
```
1. Flag ON
2. Cambias raw → se parsea → actualiza envVariables
3. Watch ve flag ON → NO actualiza raw
4. Flag OFF
5. Siguiente cambio funciona normal ✅
```
---
### 💾 `saveEnvFile()`
**¿Qué hace?**
Escribe los cambios al disco.
**Proceso:**
1. Sincroniza del raw (por si editaste ahí)
2. Llama a Rust `write_env_file`
3. Escribe archivo en `{projectRoot}/.env`
4. Marca sin cambios
**Ubicación del archivo:**
```
Windows: C:/Users/Shnimlz/Documents/GitHub/amayo/.env
Linux/Mac: /home/user/projects/amayo/.env
```
---
## 🧩 Pregunta: ¿Sistema de Extensiones?
**TL;DR:** Sí, es posible pero avanzado. Aquí está el plan:
### Opción 1: Sistema Simple de Plugins (Más Fácil)
**Concepto:**
```
plugins/
├── theme-dracula/
│ ├── plugin.json
│ └── theme.css
├── snippets-react/
│ ├── plugin.json
│ └── snippets.json
└── formatter-prettier/
├── plugin.json
└── format.js
```
**Estructura de plugin:**
```json
{
"name": "theme-dracula",
"version": "1.0.0",
"type": "theme",
"main": "theme.css",
"author": "You",
"description": "Dracula theme for Monaco"
}
```
**Implementación:**
1. **Manager de Plugins** (Vue component)
```typescript
class PluginManager {
plugins: Plugin[] = [];
async loadPlugin(path: string) {
const config = await readPluginConfig(path);
if (config.type === 'theme') {
await loadTheme(config.main);
} else if (config.type === 'snippets') {
await loadSnippets(config.main);
}
}
}
```
2. **UI de Extensiones**
```vue
<div class="extensions-panel">
<h2>🧩 Extensiones Instaladas</h2>
<div v-for="plugin in plugins">
<h3>{{ plugin.name }}</h3>
<button @click="togglePlugin(plugin)">
{{ plugin.enabled ? 'Desactivar' : 'Activar' }}
</button>
</div>
<button @click="installFromFile">
📦 Instalar desde ZIP
</button>
</div>
```
3. **Backend Rust**
```rust
#[tauri::command]
fn list_plugins(app_data_dir: String) -> Vec<PluginInfo> {
// Escanear carpeta plugins/
}
#[tauri::command]
fn install_plugin(zip_path: String) -> Result<(), String> {
// Extraer ZIP a plugins/
}
```
**Tipos de Extensiones:**
- 🎨 **Temas**: CSS para Monaco
- 📝 **Snippets**: JSON con snippets personalizados
- 🔧 **Formatters**: JS que formatea código
- 🌐 **Language Support**: Definiciones de TypeScript
- 🎯 **Commands**: Nuevos comandos personalizados
---
### Opción 2: Sistema Avanzado tipo VS Code (Más Complejo)
**API de Extensiones:**
```typescript
// extension-api.d.ts
export interface Extension {
activate(context: ExtensionContext): void;
deactivate(): void;
}
export interface ExtensionContext {
subscriptions: Disposable[];
workspaceState: Memento;
globalState: Memento;
}
export namespace commands {
export function registerCommand(
command: string,
callback: (...args: any[]) => any
): Disposable;
}
export namespace languages {
export function registerCompletionItemProvider(
selector: DocumentSelector,
provider: CompletionItemProvider
): Disposable;
}
```
**Ejemplo de extensión:**
```typescript
// my-extension/src/extension.ts
import * as vscode from '@editor/api';
export function activate(context: vscode.ExtensionContext) {
// Registrar comando
let disposable = vscode.commands.registerCommand(
'myExtension.helloWorld',
() => {
vscode.window.showInformationMessage('Hello from Extension!');
}
);
context.subscriptions.push(disposable);
// Registrar autocompletado
context.subscriptions.push(
vscode.languages.registerCompletionItemProvider('typescript', {
provideCompletionItems() {
return [
{
label: 'myFunction',
kind: vscode.CompletionItemKind.Function,
insertText: 'myFunction($1)',
}
];
}
})
);
}
```
**Arquitectura:**
```
Extension Host (Worker)
├── Sandbox aislado para cada extensión
├── Comunicación vía postMessage
└── API restringida por seguridad
Main Thread (Editor)
├── Recibe comandos del Extension Host
├── Ejecuta cambios en Monaco
└── Maneja UI
```
---
### 🚀 Plan de Implementación Recomendado
**Fase 1: Sistema Simple** (1-2 semanas)
1. ✅ Crear carpeta `plugins/` en appData
2. ✅ Componente `ExtensionManager.vue`
3. ✅ Backend Rust para leer/instalar
4. ✅ Soporte para temas CSS
5. ✅ Soporte para snippets JSON
**Fase 2: Marketplace Básico** (2-3 semanas)
1. ✅ UI de búsqueda de extensiones
2. ✅ Servidor simple con lista de extensiones
3. ✅ Instalación desde URL
4. ✅ Auto-actualización
**Fase 3: API Avanzada** (1-2 meses)
1. ✅ Extension Host con Workers
2. ✅ API tipo VS Code
3. ✅ Sandboxing de seguridad
4. ✅ Debugging de extensiones
---
### 📦 Ejemplo Completo: Extensión de Tema
**Estructura:**
```
theme-dracula.zip
├── manifest.json
├── theme.json
└── README.md
```
**manifest.json:**
```json
{
"name": "Dracula Theme",
"id": "dracula-theme",
"version": "1.0.0",
"publisher": "dracula",
"description": "Dark theme for vampires",
"type": "theme",
"main": "theme.json",
"engines": {
"aeditor": "^1.0.0"
}
}
```
**theme.json:**
```json
{
"name": "Dracula",
"type": "dark",
"colors": {
"editor.background": "#282a36",
"editor.foreground": "#f8f8f2",
"editorCursor.foreground": "#f8f8f0",
"editor.lineHighlightBackground": "#44475a"
},
"tokenColors": [
{
"scope": ["comment"],
"settings": {
"foreground": "#6272a4",
"fontStyle": "italic"
}
},
{
"scope": ["string"],
"settings": {
"foreground": "#f1fa8c"
}
}
]
}
```
**Instalación:**
1. Usuario descarga `theme-dracula.zip`
2. Click en "Instalar Extensión"
3. Selecciona el ZIP
4. Backend extrae a `plugins/dracula-theme/`
5. Frontend carga el tema
6. Usuario lo activa desde la UI
---
## 🎓 Resumen
### Mejoras Completadas ✅
1. **Sistema de eliminación** con errores detallados
2. **EnvManager mejorado:**
- Lectura robusta del .env
- Parseo mejorado con logs
- Guardado con sincronización
- **Ubicaciones exactas** de cada variable (archivo, línea, código)
- Documentación completa de cada función
### Sistema de Extensiones 🚀
- **Factible:** Sí, totalmente posible
- **Complejidad:** Media-Alta
- **Recomendación:** Empezar con sistema simple
- **Beneficios:**
- Comunidad puede crear extensiones
- Personalización infinita
- Marketplace propio
- Competencia con VS Code en features
### Siguiente Paso Sugerido
1. Crear prototipo del ExtensionManager
2. Implementar soporte básico de temas
3. Si funciona bien, expandir a otros tipos
---
## 📞 Necesitas Ayuda?
Si quieres implementar el sistema de extensiones, puedo ayudarte con:
1. Arquitectura detallada
2. Código del ExtensionManager
3. API de extensiones
4. Ejemplos de extensiones
5. Sistema de marketplace
¡Solo pregunta! 🚀