@orxataguy/tyr 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +408 -0
- package/bin/tyr.js +25 -0
- package/bin/tyr.ts +14 -0
- package/config/map.yml +7 -0
- package/package.json +60 -0
- package/src/commands/di.tyr.ts +113 -0
- package/src/commands/dw.tyr.ts +116 -0
- package/src/commands/install.tyr.ts +135 -0
- package/src/core/Container.ts +56 -0
- package/src/core/Kernel.ts +165 -0
- package/src/core/Logger.ts +48 -0
- package/src/core/TyrError.ts +57 -0
- package/src/core/sys/ai.ts +162 -0
- package/src/core/sys/doc.ts +325 -0
- package/src/core/sys/gen.ts +72 -0
- package/src/core/sys/rem.ts +57 -0
- package/src/lib/DockerManager.ts +108 -0
- package/src/lib/FileSystemManager.ts +152 -0
- package/src/lib/GitManager.ts +76 -0
- package/src/lib/PackageManager.ts +87 -0
- package/src/lib/SQLManager.ts +121 -0
- package/src/lib/ShellManager.ts +118 -0
- package/src/lib/SystemManager.ts +83 -0
- package/src/lib/WebManager.ts +62 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Manel Andreu Pérez
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
# Tyr Framework - Guía Completa del Proyecto
|
|
2
|
+
|
|
3
|
+
**Autor:** Manel Andreu Pérez
|
|
4
|
+
**Versión:** 1.0.0
|
|
5
|
+
**Licencia:** MIT
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 📋 Descripción del Proyecto
|
|
10
|
+
|
|
11
|
+
Tyr Framework es un entorno de ejecución basado en TypeScript que permite crear, ejecutar y automatizar herramientas CLI de manera declarativa.
|
|
12
|
+
|
|
13
|
+
La arquitectura se construye sobre **inyección de dependencias**: el "Kernel" proporciona un contexto de ejecución donde los "Managers" exponen su funcionalidad a través de una API auto-generada. Gracias a un sistema de introspección de código, el entorno analiza tipos y documentación en tiempo real.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 📁 Estructura del Proyecto
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
/
|
|
21
|
+
├── bin/
|
|
22
|
+
│ └── tyr.ts // Punto de entrada del CLI
|
|
23
|
+
│
|
|
24
|
+
├── src/
|
|
25
|
+
│ ├── core/
|
|
26
|
+
│ │ ├── Kernel.ts // Motor principal de ejecución
|
|
27
|
+
│ │ ├── Container.ts // Contenedor de servicios (inyección de dependencias)
|
|
28
|
+
│ │ ├── TyrError.ts // Manejo de errores personalizado
|
|
29
|
+
│ │ └── sys/
|
|
30
|
+
│ │ ├── gen.ts // Comando: generar nuevos comandos
|
|
31
|
+
│ │ ├── rem.ts // Comando: remover comandos
|
|
32
|
+
│ │ └── doc.ts // Comando: generar documentación
|
|
33
|
+
│ │
|
|
34
|
+
│ ├── commands/
|
|
35
|
+
│ │ ├── install.tyr.ts // Comando: instalar el framework
|
|
36
|
+
│ │ └── dw.tyr.ts // Comando: descargar dependencias
|
|
37
|
+
│ │
|
|
38
|
+
│ └── lib/
|
|
39
|
+
│ ├── ShellManager.ts // Ejecución de comandos shell
|
|
40
|
+
│ ├── FileSystemManager.ts // Operaciones del sistema de archivos
|
|
41
|
+
│ ├── PackageManager.ts // Gestión de paquetes (npm)
|
|
42
|
+
│ ├── DockerManager.ts // Integración con Docker
|
|
43
|
+
│ ├── GitManager.ts // Operaciones de Git
|
|
44
|
+
│ ├── SystemManager.ts // Gestión del sistema
|
|
45
|
+
│ ├── SQLManager.ts // Consultas a bases de datos MSSQL
|
|
46
|
+
│ └── WebManager.ts // Requests HTTP
|
|
47
|
+
│
|
|
48
|
+
├── tests/
|
|
49
|
+
│ ├── commands.test.ts // Tests de comandos (Vitest)
|
|
50
|
+
│ ├── test-runner.ts // Runner de smoke tests
|
|
51
|
+
│ └── setup.ts // Configuración de mocks
|
|
52
|
+
│
|
|
53
|
+
├── config/
|
|
54
|
+
│ └── map.yml // Configuración de comandos del framework
|
|
55
|
+
│
|
|
56
|
+
├── local/
|
|
57
|
+
│ ├── aliases.sh // Alias de shell personalizados
|
|
58
|
+
│ └── plugins.sh // Plugins para shell
|
|
59
|
+
│
|
|
60
|
+
├── package.json // Dependencias y scripts
|
|
61
|
+
├── tsconfig.json // Configuración de TypeScript
|
|
62
|
+
├── vitest.config.ts // Configuración de tests
|
|
63
|
+
└── html-reporter.ts // Generador de reportes HTML
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## 🎯 Conceptos Clave
|
|
69
|
+
|
|
70
|
+
### 1. KERNEL (`src/core/Kernel.ts`)
|
|
71
|
+
|
|
72
|
+
- **Orquestador principal** del framework
|
|
73
|
+
- Carga configuración desde `config/map.yml`
|
|
74
|
+
- Enruta comandos hacia sus manejadores
|
|
75
|
+
- Proporciona el contexto de ejecución (`TyrContext`)
|
|
76
|
+
- **Métodos principales:**
|
|
77
|
+
- `boot(args)`: Inicializa el framework
|
|
78
|
+
- `handle(args)`: Ejecuta comandos
|
|
79
|
+
|
|
80
|
+
### 2. CONTAINER (`src/core/Container.ts`)
|
|
81
|
+
|
|
82
|
+
- Contenedor de **inyección de dependencias**
|
|
83
|
+
- Instancia todos los servicios (Managers)
|
|
84
|
+
- Expone interfaz `ServiceContainer` con todos los servicios
|
|
85
|
+
- Implementa patrón Singleton para servicios
|
|
86
|
+
|
|
87
|
+
### 3. MANAGERS (`src/lib/*.ts`)
|
|
88
|
+
|
|
89
|
+
Conjunto de abstracciones sobre librerías externas. Ejecutar comando de documentación para saber más.
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
tyr doc
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### 4. COMANDOS
|
|
96
|
+
|
|
97
|
+
Son funciones que siguen el patrón:
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
export default ({ task, fail, logger, fs, shell }: TyrContext) => {
|
|
101
|
+
return async (args: string[]) => {
|
|
102
|
+
// Lógica del comando
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Los comandos personalizados se registran en `config/map.yml`
|
|
108
|
+
|
|
109
|
+
### 5. CONFIGURACIÓN (`config/map.yml`)
|
|
110
|
+
|
|
111
|
+
Define los comandos disponibles:
|
|
112
|
+
|
|
113
|
+
```yaml
|
|
114
|
+
commands:
|
|
115
|
+
install: ./src/commands/install.tyr.ts
|
|
116
|
+
dw: ./src/commands/dw.tyr.ts
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## 🚀 Cómo Usar el Framework
|
|
122
|
+
|
|
123
|
+
### Instalación
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
npm install
|
|
127
|
+
npm run install # Ejecuta el comando install
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Ejecutar Comandos
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
tyr <nombre-comando> [argumentos]
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**Ejemplos:**
|
|
137
|
+
- `tyr install` - Instala y configura el framework
|
|
138
|
+
- `tyr gen micomando` - Genera un nuevo comando
|
|
139
|
+
- `tyr rem micomando` - Elimina un comando
|
|
140
|
+
- `tyr doc` - Genera documentación
|
|
141
|
+
- `tyr dw` - Descarga dependencias
|
|
142
|
+
|
|
143
|
+
### Crear un Nuevo Comando
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
tyr gen <nombre-comando> <nombre-archivo>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Se creará el archivo en `src/commands/<nombre-archivo>.tyr.ts`:
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
import { TyrContext } from '../core/Kernel';
|
|
153
|
+
|
|
154
|
+
export default ({ task, fail, logger, fs, shell }: TyrContext) => {
|
|
155
|
+
return async (args: string[]) => {
|
|
156
|
+
// Validar argumentos
|
|
157
|
+
if (args.length === 0) {
|
|
158
|
+
fail('Se requiere al menos un argumento');
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Usar tareas con descripción
|
|
162
|
+
await task('Realizando acción', async () => {
|
|
163
|
+
logger.info('Procesando...');
|
|
164
|
+
// Tu lógica aquí
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
logger.success('¡Listo!');
|
|
168
|
+
};
|
|
169
|
+
};
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Eliminarc un Comando Existente
|
|
173
|
+
```bash
|
|
174
|
+
tyr rem <nombre-comando>
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## 🧪 Testing
|
|
181
|
+
|
|
182
|
+
El framework incluye un sistema de testing completo:
|
|
183
|
+
|
|
184
|
+
### Tests Unitarios (Vitest)
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
npm run test # Ejecutar tests
|
|
188
|
+
npm run test:watch # Modo watch
|
|
189
|
+
npm run test:ui # UI interactivo
|
|
190
|
+
npm run test:coverage # Cobertura
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Smoke Tests
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
npm run test:smoke # Valida que todos los comandos cargan correctamente
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
**Verifica:**
|
|
200
|
+
- Comandos cargan como módulos
|
|
201
|
+
- Exportan función por defecto
|
|
202
|
+
- Se instancian con contexto
|
|
203
|
+
- Se ejecutan sin excepciones no controladas
|
|
204
|
+
|
|
205
|
+
### Mocks
|
|
206
|
+
|
|
207
|
+
El archivo `tests/setup.ts` proporciona `createMockContext()` que mocka:
|
|
208
|
+
- Logger
|
|
209
|
+
- ShellManager
|
|
210
|
+
- FileSystemManager
|
|
211
|
+
- Todos los managers
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## 📊 Flujo de Ejecución
|
|
216
|
+
|
|
217
|
+
```
|
|
218
|
+
1. Usuario ejecuta: tyr micomando arg1 arg2
|
|
219
|
+
↓
|
|
220
|
+
2. bin/tyr.ts captura el comando
|
|
221
|
+
↓
|
|
222
|
+
3. Kernel.boot() inicializa el framework
|
|
223
|
+
↓
|
|
224
|
+
4. Container.init() crea todos los Managers
|
|
225
|
+
↓
|
|
226
|
+
5. Carga config/map.yml
|
|
227
|
+
↓
|
|
228
|
+
6. Kernel.handle() recibe [micomando, arg1, arg2]
|
|
229
|
+
↓
|
|
230
|
+
7. Busca el comando en la configuración
|
|
231
|
+
↓
|
|
232
|
+
8. Importa el módulo dinámicamente
|
|
233
|
+
↓
|
|
234
|
+
9. Instancia el comando pasando TyrContext
|
|
235
|
+
↓
|
|
236
|
+
10. Ejecuta comando(args)
|
|
237
|
+
↓
|
|
238
|
+
11. Retorna resultado o error
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## 📦 Dependencias Principales
|
|
244
|
+
|
|
245
|
+
### Runtime
|
|
246
|
+
|
|
247
|
+
- **chalk** - Colores en terminal
|
|
248
|
+
- **execa** - Ejecución de shell mejorada
|
|
249
|
+
- **axios** - HTTP client
|
|
250
|
+
- **mssql** - Driver MSSQL
|
|
251
|
+
- **js-yaml** - Parser YAML
|
|
252
|
+
- **inquirer** - Prompts interactivos
|
|
253
|
+
- **dotenv** - Variables de entorno
|
|
254
|
+
- **cheerio** - Web scraping
|
|
255
|
+
- **find-config** - Búsqueda de archivos de config
|
|
256
|
+
|
|
257
|
+
### Dev
|
|
258
|
+
|
|
259
|
+
- **TypeScript** - Lenguaje
|
|
260
|
+
- **Vitest** - Testing framework
|
|
261
|
+
- **tsx** - Ejecutor TypeScript
|
|
262
|
+
- **Vite** - Build tool
|
|
263
|
+
- **Husky** - Git hooks
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## 🔧 Configuración Importante
|
|
268
|
+
|
|
269
|
+
### tsconfig.json
|
|
270
|
+
- `target`: ES2020
|
|
271
|
+
- `module`: ES2020
|
|
272
|
+
- `moduleResolution`: node
|
|
273
|
+
|
|
274
|
+
### package.json
|
|
275
|
+
- `type`: module (módulos ES)
|
|
276
|
+
- `bin`: { tyr: ./bin/tyr.ts }
|
|
277
|
+
|
|
278
|
+
### vitest.config.ts
|
|
279
|
+
- Test runner del proyecto
|
|
280
|
+
- Configuración de mocks y setup
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## 🎨 Patrones y Best Practices
|
|
285
|
+
|
|
286
|
+
### Inyección de Dependencias
|
|
287
|
+
|
|
288
|
+
```typescript
|
|
289
|
+
const command = ({ logger, fs, shell }: TyrContext) => {
|
|
290
|
+
// Los managers se inyectan automáticamente
|
|
291
|
+
return async (args) => { ... };
|
|
292
|
+
};
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### Manejo de Errores
|
|
296
|
+
|
|
297
|
+
- Usa `fail(message, suggestion?)` para errores controlados
|
|
298
|
+
- `fail()` lanza `TyrError`
|
|
299
|
+
- Los comandos pueden capturar y manejar excepciones
|
|
300
|
+
|
|
301
|
+
### Tareas con Descripción
|
|
302
|
+
|
|
303
|
+
```typescript
|
|
304
|
+
await task('Descripción', async () => {
|
|
305
|
+
// Operación
|
|
306
|
+
});
|
|
307
|
+
// Muestra progreso en terminal
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### Logging
|
|
311
|
+
|
|
312
|
+
```typescript
|
|
313
|
+
logger.info() // Información general
|
|
314
|
+
logger.success() // Operación exitosa
|
|
315
|
+
logger.error() // Error (solo en debug)
|
|
316
|
+
logger.warn() // Advertencia (solo en debug)
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### Argumentos de Comando
|
|
320
|
+
|
|
321
|
+
Siempre valida los argumentos al inicio:
|
|
322
|
+
|
|
323
|
+
```typescript
|
|
324
|
+
if (args.length < 2) {
|
|
325
|
+
fail('Se requieren 2 argumentos', 'Sintaxis: tyr cmd arg1 arg2');
|
|
326
|
+
}
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
## 📚 Comandos Disponibles
|
|
332
|
+
|
|
333
|
+
### Comandos del Sistema
|
|
334
|
+
|
|
335
|
+
#### `tyr gen <nombre-comando> [archivo-salida]`
|
|
336
|
+
Genera un nuevo comando con template
|
|
337
|
+
- Crea archivo en `src/commands/`
|
|
338
|
+
- Registra en `config/map.yml`
|
|
339
|
+
|
|
340
|
+
#### `tyr rem <nombre-comando>`
|
|
341
|
+
Elimina un comando
|
|
342
|
+
- Borra archivo del comando
|
|
343
|
+
- Elimina entrada en `config/map.yml`
|
|
344
|
+
|
|
345
|
+
#### `tyr doc`
|
|
346
|
+
Genera documentación completa del sistema
|
|
347
|
+
- Analiza todos los comandos
|
|
348
|
+
- Extrae tipos y comentarios JSDoc
|
|
349
|
+
- Genera HTML interactivo
|
|
350
|
+
|
|
351
|
+
### Comandos Personalizados
|
|
352
|
+
|
|
353
|
+
#### `tyr install`
|
|
354
|
+
Instala y configura el framework
|
|
355
|
+
- Crea estructura de carpetas
|
|
356
|
+
- Copia templates
|
|
357
|
+
- Configura alias 'tyre' en .zshrc
|
|
358
|
+
|
|
359
|
+
#### `tyr dw`
|
|
360
|
+
Descarga y configura dependencias
|
|
361
|
+
- Instala paquetes npm
|
|
362
|
+
- Configura variables de entorno
|
|
363
|
+
- Verifica instalaciones externas
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
## 🐛 Debugging
|
|
368
|
+
|
|
369
|
+
Ejecuta con flag `--debug` para ver más información:
|
|
370
|
+
|
|
371
|
+
```bash
|
|
372
|
+
tyr micomando --debug
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
- Activa logging de errores y warnings
|
|
376
|
+
- Muestra detalles de operaciones
|
|
377
|
+
|
|
378
|
+
---
|
|
379
|
+
|
|
380
|
+
## 📝 Notas de Desarrollo
|
|
381
|
+
|
|
382
|
+
- El framework usa módulos ES6, asegúrate de `"type": "module"` en `package.json`
|
|
383
|
+
- Los comandos deben ser `async`
|
|
384
|
+
- Siempre retorna del handler o lanza error
|
|
385
|
+
- Usa la inyección de dependencias, no importes managers directamente
|
|
386
|
+
- Los tests usan mocks automáticos del `setup.ts`
|
|
387
|
+
- El smoke test valida que todos los comandos cargan correctamente
|
|
388
|
+
|
|
389
|
+
---
|
|
390
|
+
|
|
391
|
+
## 🔗 Referencias Útiles
|
|
392
|
+
|
|
393
|
+
Archivos principales para empezar:
|
|
394
|
+
|
|
395
|
+
- [src/core/Kernel.ts](src/core/Kernel.ts) - Entender cómo funciona el motor
|
|
396
|
+
- [src/core/Container.ts](src/core/Container.ts) - Ver cómo se inyectan dependencias
|
|
397
|
+
- [src/commands/install.tyr.ts](src/commands/install.tyr.ts) - Ejemplo de comando completo
|
|
398
|
+
- [src/core/sys/gen.ts](src/core/sys/gen.ts) - Cómo generar nuevos comandos
|
|
399
|
+
- [tests/test-runner.ts](tests/test-runner.ts) - Sistema de testing
|
|
400
|
+
|
|
401
|
+
---
|
|
402
|
+
|
|
403
|
+
## Licencia
|
|
404
|
+
|
|
405
|
+
**Autor:** Manel Andreu Pérez
|
|
406
|
+
**Versión:** 1.0.0
|
|
407
|
+
**Licencia:** MIT
|
|
408
|
+
**Tipo de proyecto:** CLI Framework para Automatización DevOps
|
package/bin/tyr.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
3
|
+
import { dirname, resolve, join } from 'path';
|
|
4
|
+
import { spawn } from 'child_process';
|
|
5
|
+
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = dirname(__filename);
|
|
8
|
+
const packageRoot = resolve(__dirname, '..');
|
|
9
|
+
const isWindows = process.platform === 'win32';
|
|
10
|
+
|
|
11
|
+
const tsxBin = join(packageRoot, 'node_modules', '.bin', isWindows ? 'tsx.cmd' : 'tsx');
|
|
12
|
+
const entry = join(__dirname, 'tyr.ts');
|
|
13
|
+
|
|
14
|
+
const child = spawn(tsxBin, [entry, ...process.argv.slice(2)], {
|
|
15
|
+
stdio: 'inherit',
|
|
16
|
+
shell: isWindows
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
child.on('exit', (code) => process.exit(code ?? 0));
|
|
20
|
+
child.on('error', (err) => {
|
|
21
|
+
console.error(`Error: Could not start tyr. ${err.message}`);
|
|
22
|
+
console.error(`tsx not found at: ${tsxBin}`);
|
|
23
|
+
console.error(`Try reinstalling: npm install -g tyr.framework.cli`);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
});
|
package/bin/tyr.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Kernel } from '../src/core/Kernel.ts';
|
|
2
|
+
|
|
3
|
+
(async () => {
|
|
4
|
+
try {
|
|
5
|
+
const kernel = new Kernel();
|
|
6
|
+
const args = process.argv.slice(2);
|
|
7
|
+
await kernel.boot(args);
|
|
8
|
+
await kernel.handle(args);
|
|
9
|
+
} catch (error) {
|
|
10
|
+
console.error("Error fatal:");
|
|
11
|
+
console.error(error);
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
})();
|
package/config/map.yml
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@orxataguy/tyr",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"bin": {
|
|
6
|
+
"tyr": "./bin/tyr.js"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"bin/",
|
|
10
|
+
"src/",
|
|
11
|
+
"config/"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"test": "vitest run",
|
|
15
|
+
"test:smoke": "tsx tests/test-runner.ts",
|
|
16
|
+
"test:watch": "vitest",
|
|
17
|
+
"test:ui": "vitest --ui",
|
|
18
|
+
"test:coverage": "vitest run --coverage",
|
|
19
|
+
"prepare": "node -e \"const{existsSync}=require('fs');if(!process.env.CI&&existsSync('.git'))require('child_process').execSync('husky',{stdio:'inherit'})\"",
|
|
20
|
+
"release:patch": "npm version patch && git push --follow-tags",
|
|
21
|
+
"release:minor": "npm version minor && git push --follow-tags",
|
|
22
|
+
"release:major": "npm version major && git push --follow-tags",
|
|
23
|
+
"config": "node bin/tyr.js install"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"CLI",
|
|
27
|
+
"scripting",
|
|
28
|
+
"system management",
|
|
29
|
+
"task scheduling",
|
|
30
|
+
"DevOps",
|
|
31
|
+
"cross-platform"
|
|
32
|
+
],
|
|
33
|
+
"author": "Manel Andreu Pérez",
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"description": "Tyr is a TypeScript-based environment that resolves this fragmentation through the creation, execution, and automation of CLI tools. Its architecture is built on dependency injection: the \"Kernel\" provides an execution context where \"Managers\" expose their functionality via an auto-generated API. Thanks to a code introspection system, the environment analyzes types and documentation in real-time, offering the programmer a ready-to-use catalog of tools. This completely decouples command logic from underlying libraries, allowing developers to invoke complex functions without needing to manage external packages or configurations.",
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@types/inquirer": "^9.0.9",
|
|
38
|
+
"@types/mssql": "^9.1.8",
|
|
39
|
+
"axios": "^1.13.2",
|
|
40
|
+
"chalk": "^5.6.2",
|
|
41
|
+
"cheerio": "^1.1.2",
|
|
42
|
+
"dotenv": "^17.2.3",
|
|
43
|
+
"execa": "^6.1.0",
|
|
44
|
+
"find-config": "^1.0.0",
|
|
45
|
+
"inquirer": "^13.2.1",
|
|
46
|
+
"js-yaml": "^4.1.1",
|
|
47
|
+
"mssql": "^12.2.0",
|
|
48
|
+
"tsx": "^4.21.0"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@types/js-yaml": "^4.0.9",
|
|
52
|
+
"@types/node": "^25.0.10",
|
|
53
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
54
|
+
"@vitest/ui": "^3.2.4",
|
|
55
|
+
"husky": "^9.1.7",
|
|
56
|
+
"typescript": "^5.9.3",
|
|
57
|
+
"vite": "^7.3.1",
|
|
58
|
+
"vitest": "^3.2.4"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { TyrContext } from '../core/Kernel';
|
|
2
|
+
|
|
3
|
+
export default ({ task, fail, logger, shell, db, git, fs }: TyrContext) => {
|
|
4
|
+
/**
|
|
5
|
+
* @method extractBranchName
|
|
6
|
+
* @description Extrae el nombre de rama de una URL o devuelve el nombre tal cual
|
|
7
|
+
*/
|
|
8
|
+
const extractBranchName = (input: string): string => {
|
|
9
|
+
if (input.includes('/')) {
|
|
10
|
+
const parts = input.split('/');
|
|
11
|
+
return parts[parts.length - 1];
|
|
12
|
+
}
|
|
13
|
+
return input;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
return async (args: string[]) => {
|
|
17
|
+
|
|
18
|
+
// Validación de argumentos
|
|
19
|
+
if (args.length === 0) {
|
|
20
|
+
fail(
|
|
21
|
+
'No se especificó la URL del cliente',
|
|
22
|
+
'Uso: clone-client <url-cliente> [url-rama-opcional]'
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const clientUrl = args[0];
|
|
27
|
+
const branchUrlOrName = args[1] || null;
|
|
28
|
+
|
|
29
|
+
logger.info('Navegando al directorio de clientes...');
|
|
30
|
+
shell.cd('~/dev/wolbenvironment/dev/online-booking/htdocs/datosBroker');
|
|
31
|
+
|
|
32
|
+
const broker = await task('Buscando broker en la base de datos', async () => {
|
|
33
|
+
const result = await db.searchBrokerOnDB(clientUrl);
|
|
34
|
+
|
|
35
|
+
if (!result) {
|
|
36
|
+
fail(
|
|
37
|
+
`No se encontró broker para la URL: ${clientUrl}`,
|
|
38
|
+
'Verifica que la URL sea correcta y esté registrada en la BD'
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
logger.success(`Broker encontrado: ${result}`);
|
|
43
|
+
return result;
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const brokerPath = `~/dev/wolbenvironment/dev/online-booking/htdocs/datosBroker/${broker}`;
|
|
47
|
+
const dirExists = fs.exists(brokerPath);
|
|
48
|
+
|
|
49
|
+
if (dirExists) {
|
|
50
|
+
logger.warn(`El directorio '${broker}' ya existe`);
|
|
51
|
+
|
|
52
|
+
const choice = await shell.input(
|
|
53
|
+
'¿Qué deseas hacer? (s)obrescribir / (m)antener / (r)enombrar: '
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
if (choice.toLowerCase() === 'm' || choice.toLowerCase() === 'mantener') {
|
|
57
|
+
logger.info('Manteniendo directorio existente. Finalizando...');
|
|
58
|
+
return;
|
|
59
|
+
} else if (choice.toLowerCase() === 'r' || choice.toLowerCase() === 'renombrar') {
|
|
60
|
+
await task('Renombrando directorio existente', async () => {
|
|
61
|
+
await shell.exec(`mv ${broker} ${broker}.bak`);
|
|
62
|
+
logger.success(`Directorio renombrado a: ${broker}.bak`);
|
|
63
|
+
});
|
|
64
|
+
} else if (choice.toLowerCase() === 's' || choice.toLowerCase() === 'sobrescribir') {
|
|
65
|
+
await task('Eliminando directorio existente', async () => {
|
|
66
|
+
await shell.exec(`rm -rf ${broker}`);
|
|
67
|
+
logger.success('Directorio eliminado');
|
|
68
|
+
});
|
|
69
|
+
} else {
|
|
70
|
+
fail('Opción no válida', 'Usa: s (sobrescribir), m (mantener) o r (renombrar)');
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const repoUrl = `git@github.com:Avantio/${broker}`;
|
|
75
|
+
logger.info(`Repositorio: ${repoUrl}`);
|
|
76
|
+
|
|
77
|
+
const loader = shell.showLoader('Clonando repositorio desde GitHub...');
|
|
78
|
+
|
|
79
|
+
await task('Clonando repositorio', async () => {
|
|
80
|
+
await git.clone(repoUrl);
|
|
81
|
+
loader.stop();
|
|
82
|
+
logger.success('Repositorio clonado exitosamente');
|
|
83
|
+
}, false, () => loader.stop());
|
|
84
|
+
|
|
85
|
+
shell.cd(broker);
|
|
86
|
+
|
|
87
|
+
let branchName: string;
|
|
88
|
+
|
|
89
|
+
if (branchUrlOrName) {
|
|
90
|
+
branchName = extractBranchName(branchUrlOrName);
|
|
91
|
+
logger.info(`Rama extraída: ${branchName}`);
|
|
92
|
+
} else {
|
|
93
|
+
const answer = await shell.input('🌿 ¿Qué rama quieres usar? (nombre o URL): ');
|
|
94
|
+
branchName = extractBranchName(answer);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
await task(`Cambiando a la rama: ${branchName}`, async () => {
|
|
98
|
+
if (branchName.length > 0) {
|
|
99
|
+
await shell.exec(`git checkout -b ${branchName}`);
|
|
100
|
+
logger.success(`Ahora estás en la rama: ${branchName}`);
|
|
101
|
+
} else {
|
|
102
|
+
logger.info('No se va a generar ninguna rama nueva')
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
logger.success(`Repositorio ${broker} clonado y configurado exitosamente`);
|
|
106
|
+
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
// export const Test = {
|
|
112
|
+
// args: []
|
|
113
|
+
// }
|