@orxataguy/tyr 1.0.0 → 1.0.2
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 -21
- package/README.md +408 -408
- package/bin/tyr.js +10 -7
- package/bin/tyr.ts +13 -13
- package/config/map.yml +4 -7
- package/package.json +66 -60
- package/src/commands/di.tyr.ts +112 -112
- package/src/commands/dw.tyr.ts +115 -115
- package/src/commands/install.tyr.ts +30 -104
- package/src/core/Container.ts +56 -56
- package/src/core/Kernel.ts +213 -165
- package/src/core/Logger.ts +51 -48
- package/src/core/TyrError.ts +57 -57
- package/src/core/sys/ai.ts +160 -162
- package/src/core/sys/config.ts +231 -0
- package/src/core/sys/doc.ts +324 -324
- package/src/core/sys/gen.ts +75 -72
- package/src/core/sys/rem.ts +61 -57
- package/src/index.ts +5 -0
- package/src/lib/DockerManager.ts +108 -108
- package/src/lib/FileSystemManager.ts +152 -152
- package/src/lib/GitManager.ts +75 -75
- package/src/lib/PackageManager.ts +87 -87
- package/src/lib/SQLManager.ts +112 -120
- package/src/lib/ShellManager.ts +117 -117
- package/src/lib/SystemManager.ts +83 -83
- package/src/lib/WebManager.ts +62 -62
package/bin/tyr.js
CHANGED
|
@@ -2,24 +2,27 @@
|
|
|
2
2
|
import { fileURLToPath } from 'url';
|
|
3
3
|
import { dirname, resolve, join } from 'path';
|
|
4
4
|
import { spawn } from 'child_process';
|
|
5
|
+
import { readFileSync } from 'fs';
|
|
5
6
|
|
|
6
7
|
const __filename = fileURLToPath(import.meta.url);
|
|
7
8
|
const __dirname = dirname(__filename);
|
|
8
9
|
const packageRoot = resolve(__dirname, '..');
|
|
9
|
-
const isWindows = process.platform === 'win32';
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
// Locate tsx's CLI entry directly from its package.json — no shell, no .cmd wrappers
|
|
12
|
+
const tsxPkg = JSON.parse(readFileSync(join(packageRoot, 'node_modules', 'tsx', 'package.json'), 'utf-8'));
|
|
13
|
+
const tsxBinField = tsxPkg.bin;
|
|
14
|
+
const tsxBinRelative = typeof tsxBinField === 'string' ? tsxBinField : (tsxBinField.tsx ?? tsxBinField['tsx']);
|
|
15
|
+
const tsxEntry = join(packageRoot, 'node_modules', 'tsx', tsxBinRelative);
|
|
12
16
|
const entry = join(__dirname, 'tyr.ts');
|
|
13
17
|
|
|
14
|
-
const child = spawn(
|
|
15
|
-
stdio: 'inherit'
|
|
16
|
-
shell: isWindows
|
|
18
|
+
const child = spawn(process.execPath, [tsxEntry, entry, ...process.argv.slice(2)], {
|
|
19
|
+
stdio: 'inherit'
|
|
17
20
|
});
|
|
18
21
|
|
|
19
22
|
child.on('exit', (code) => process.exit(code ?? 0));
|
|
20
23
|
child.on('error', (err) => {
|
|
21
24
|
console.error(`Error: Could not start tyr. ${err.message}`);
|
|
22
|
-
console.error(`tsx not found at: ${
|
|
23
|
-
console.error(
|
|
25
|
+
console.error(`tsx not found at: ${tsxEntry}`);
|
|
26
|
+
console.error('Try reinstalling: npm install -g @orxataguy/tyr');
|
|
24
27
|
process.exit(1);
|
|
25
28
|
});
|
package/bin/tyr.ts
CHANGED
|
@@ -1,14 +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
|
-
}
|
|
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
14
|
})();
|
package/config/map.yml
CHANGED
package/package.json
CHANGED
|
@@ -1,60 +1,66 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@orxataguy/tyr",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"type": "module",
|
|
5
|
-
"bin": {
|
|
6
|
-
"tyr": "./bin/tyr.js"
|
|
7
|
-
},
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
"test
|
|
18
|
-
"test:
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
|
|
60
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@orxataguy/tyr",
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"bin": {
|
|
6
|
+
"tyr": "./bin/tyr.js"
|
|
7
|
+
},
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./src/index.ts"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"bin/",
|
|
13
|
+
"src/",
|
|
14
|
+
"config/"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"test": "vitest run",
|
|
18
|
+
"test:smoke": "tsx tests/test-runner.ts",
|
|
19
|
+
"test:watch": "vitest",
|
|
20
|
+
"test:ui": "vitest --ui",
|
|
21
|
+
"test:coverage": "vitest run --coverage",
|
|
22
|
+
"prepare": "node -e \"const{existsSync}=require('fs'),cp=require('child_process'),p=require('path');if(!process.env.CI&&existsSync('.git')){const b=p.join('node_modules','.bin','husky'+(process.platform==='win32'?'.cmd':''));cp.execSync(b,{stdio:'inherit',shell:process.platform==='win32'});}\"",
|
|
23
|
+
"release:patch": "npm version patch && git push --follow-tags",
|
|
24
|
+
"release:minor": "npm version minor && git push --follow-tags",
|
|
25
|
+
"release:major": "npm version major && git push --follow-tags",
|
|
26
|
+
"config": "node bin/tyr.js install"
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"CLI",
|
|
30
|
+
"scripting",
|
|
31
|
+
"system management",
|
|
32
|
+
"task scheduling",
|
|
33
|
+
"DevOps",
|
|
34
|
+
"cross-platform"
|
|
35
|
+
],
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public"
|
|
38
|
+
},
|
|
39
|
+
"author": "Manel Andreu Pérez",
|
|
40
|
+
"license": "MIT",
|
|
41
|
+
"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.",
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@types/inquirer": "^9.0.9",
|
|
44
|
+
"@types/mssql": "^9.1.8",
|
|
45
|
+
"axios": "^1.13.2",
|
|
46
|
+
"chalk": "^5.6.2",
|
|
47
|
+
"cheerio": "^1.1.2",
|
|
48
|
+
"dotenv": "^17.2.3",
|
|
49
|
+
"execa": "^6.1.0",
|
|
50
|
+
"find-config": "^1.0.0",
|
|
51
|
+
"inquirer": "^13.2.1",
|
|
52
|
+
"js-yaml": "^4.1.1",
|
|
53
|
+
"mssql": "^12.2.0",
|
|
54
|
+
"tsx": "^4.21.0"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@types/js-yaml": "^4.0.9",
|
|
58
|
+
"@types/node": "^25.0.10",
|
|
59
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
60
|
+
"@vitest/ui": "^3.2.4",
|
|
61
|
+
"husky": "^9.1.7",
|
|
62
|
+
"typescript": "^5.9.3",
|
|
63
|
+
"vite": "^7.3.1",
|
|
64
|
+
"vitest": "^3.2.4"
|
|
65
|
+
}
|
|
66
|
+
}
|
package/src/commands/di.tyr.ts
CHANGED
|
@@ -1,113 +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: []
|
|
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
113
|
// }
|