@orxataguy/tyr 1.4.0 → 1.6.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.ts +13 -13
- package/config/map.yml +4 -7
- package/package.json +60 -60
- package/src/commands/di.tyr.ts +112 -112
- package/src/commands/dw.tyr.ts +115 -115
- package/src/commands/install.tyr.ts +61 -61
- package/src/core/Container.ts +56 -56
- package/src/core/Kernel.ts +1 -1
- package/src/core/Logger.ts +48 -48
- package/src/core/TyrError.ts +57 -57
- package/src/core/sys/ai.ts +162 -162
- package/src/core/sys/config.ts +121 -83
- package/src/core/sys/doc.ts +324 -324
- 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 +117 -117
- package/src/lib/ShellManager.ts +117 -117
- package/src/lib/SystemManager.ts +83 -83
- package/src/lib/WebManager.ts +62 -62
package/src/lib/GitManager.ts
CHANGED
|
@@ -1,76 +1,76 @@
|
|
|
1
|
-
import { ShellManager } from './ShellManager.js';
|
|
2
|
-
import { Logger } from '../core/Logger.js';
|
|
3
|
-
import { TyrError } from '../core/TyrError.js';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @class GitManager
|
|
7
|
-
* @description Wrapper for common Git operations. Automates repository initialization, commits and cloning.
|
|
8
|
-
*/
|
|
9
|
-
export class GitManager {
|
|
10
|
-
private shell: ShellManager;
|
|
11
|
-
private logger: Logger;
|
|
12
|
-
|
|
13
|
-
constructor(shell: ShellManager, logger: Logger) {
|
|
14
|
-
this.shell = shell;
|
|
15
|
-
this.logger = logger;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @method init
|
|
20
|
-
* @description Initializes a Git repository in the current directory and renames the default branch to 'main'.
|
|
21
|
-
* @example
|
|
22
|
-
* await git.init();
|
|
23
|
-
*/
|
|
24
|
-
public async init(): Promise<void> {
|
|
25
|
-
try { await this.shell.exec('git init'); await this.shell.exec('git branch -M main'); } catch (e) {
|
|
26
|
-
throw new TyrError(`Could not init git repository`, e, 'Check if the current directory still exists.');
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* @method addAll
|
|
32
|
-
* @description Stages all files in the current directory (git add .).
|
|
33
|
-
* @example
|
|
34
|
-
* await git.addAll();
|
|
35
|
-
*/
|
|
36
|
-
public async addAll(): Promise<void> {
|
|
37
|
-
await this.shell.exec('git add .');
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* @method commit
|
|
42
|
-
* @description Creates a commit with the provided message.
|
|
43
|
-
* @param {string} message - The commit message.
|
|
44
|
-
* @example
|
|
45
|
-
* await git.commit("feat: initial project structure");
|
|
46
|
-
*/
|
|
47
|
-
public async commit(message: string): Promise<void> {
|
|
48
|
-
await this.shell.exec(`git commit -m "${message}"`);
|
|
49
|
-
this.logger.success(`Commit created: "${message}"`);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* @method clone
|
|
54
|
-
* @description Clones a remote repository into the current directory.
|
|
55
|
-
* @param {string} repoUrl - The HTTPS or SSH URL of the repository.
|
|
56
|
-
* @example
|
|
57
|
-
* await git.clone('https://github.com/user/repo.git');
|
|
58
|
-
*/
|
|
59
|
-
public async clone(repoUrl: string): Promise<void> {
|
|
60
|
-
this.logger.info(`Cloning ${repoUrl}...`);
|
|
61
|
-
try {
|
|
62
|
-
await this.shell.exec(`git clone ${repoUrl}`);
|
|
63
|
-
} catch (e) {
|
|
64
|
-
throw new TyrError(`Could not find the repository ` + repoUrl, e, 'Check if the repository exists or if you have the right permissions to clone it.');
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* @object GitManagerTests
|
|
71
|
-
* @description Test parameters to validate GitManager functionality.
|
|
72
|
-
*/
|
|
73
|
-
export const GitManagerTests = {
|
|
74
|
-
init: { directory: '/tmp/tyr-git-test' },
|
|
75
|
-
addAll: { directory: '/tmp/tyr-git-test' },
|
|
1
|
+
import { ShellManager } from './ShellManager.js';
|
|
2
|
+
import { Logger } from '../core/Logger.js';
|
|
3
|
+
import { TyrError } from '../core/TyrError.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @class GitManager
|
|
7
|
+
* @description Wrapper for common Git operations. Automates repository initialization, commits and cloning.
|
|
8
|
+
*/
|
|
9
|
+
export class GitManager {
|
|
10
|
+
private shell: ShellManager;
|
|
11
|
+
private logger: Logger;
|
|
12
|
+
|
|
13
|
+
constructor(shell: ShellManager, logger: Logger) {
|
|
14
|
+
this.shell = shell;
|
|
15
|
+
this.logger = logger;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @method init
|
|
20
|
+
* @description Initializes a Git repository in the current directory and renames the default branch to 'main'.
|
|
21
|
+
* @example
|
|
22
|
+
* await git.init();
|
|
23
|
+
*/
|
|
24
|
+
public async init(): Promise<void> {
|
|
25
|
+
try { await this.shell.exec('git init'); await this.shell.exec('git branch -M main'); } catch (e) {
|
|
26
|
+
throw new TyrError(`Could not init git repository`, e, 'Check if the current directory still exists.');
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @method addAll
|
|
32
|
+
* @description Stages all files in the current directory (git add .).
|
|
33
|
+
* @example
|
|
34
|
+
* await git.addAll();
|
|
35
|
+
*/
|
|
36
|
+
public async addAll(): Promise<void> {
|
|
37
|
+
await this.shell.exec('git add .');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @method commit
|
|
42
|
+
* @description Creates a commit with the provided message.
|
|
43
|
+
* @param {string} message - The commit message.
|
|
44
|
+
* @example
|
|
45
|
+
* await git.commit("feat: initial project structure");
|
|
46
|
+
*/
|
|
47
|
+
public async commit(message: string): Promise<void> {
|
|
48
|
+
await this.shell.exec(`git commit -m "${message}"`);
|
|
49
|
+
this.logger.success(`Commit created: "${message}"`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @method clone
|
|
54
|
+
* @description Clones a remote repository into the current directory.
|
|
55
|
+
* @param {string} repoUrl - The HTTPS or SSH URL of the repository.
|
|
56
|
+
* @example
|
|
57
|
+
* await git.clone('https://github.com/user/repo.git');
|
|
58
|
+
*/
|
|
59
|
+
public async clone(repoUrl: string): Promise<void> {
|
|
60
|
+
this.logger.info(`Cloning ${repoUrl}...`);
|
|
61
|
+
try {
|
|
62
|
+
await this.shell.exec(`git clone ${repoUrl}`);
|
|
63
|
+
} catch (e) {
|
|
64
|
+
throw new TyrError(`Could not find the repository ` + repoUrl, e, 'Check if the repository exists or if you have the right permissions to clone it.');
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @object GitManagerTests
|
|
71
|
+
* @description Test parameters to validate GitManager functionality.
|
|
72
|
+
*/
|
|
73
|
+
export const GitManagerTests = {
|
|
74
|
+
init: { directory: '/tmp/tyr-git-test' },
|
|
75
|
+
addAll: { directory: '/tmp/tyr-git-test' },
|
|
76
76
|
};
|
|
@@ -1,87 +1,87 @@
|
|
|
1
|
-
import { ShellManager } from './ShellManager.js';
|
|
2
|
-
import { Logger } from '../core/Logger.js';
|
|
3
|
-
import { TyrError } from '../core/TyrError.js';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @class PackageManager
|
|
7
|
-
* @description OS-agnostic package manager. Automatically detects whether the system uses apt, brew or dnf and installs native software.
|
|
8
|
-
*/
|
|
9
|
-
export class PackageManager {
|
|
10
|
-
private shell: ShellManager;
|
|
11
|
-
private logger: Logger;
|
|
12
|
-
private manager: string | null;
|
|
13
|
-
|
|
14
|
-
constructor(shell: ShellManager, logger: Logger) {
|
|
15
|
-
this.shell = shell;
|
|
16
|
-
this.logger = logger;
|
|
17
|
-
this.manager = null;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* @method detect
|
|
22
|
-
* @description Attempts to identify the package manager installed on the host system.
|
|
23
|
-
* @returns {Promise<string>} The name of the detected binary ('apt', 'brew', 'dnf').
|
|
24
|
-
* @example
|
|
25
|
-
* const mgr = await pkg.detect();
|
|
26
|
-
* logger.info(`Using: ${mgr}`);
|
|
27
|
-
*/
|
|
28
|
-
public async detect(): Promise<string> {
|
|
29
|
-
if (this.manager) return this.manager;
|
|
30
|
-
|
|
31
|
-
const isWindows = process.platform === 'win32';
|
|
32
|
-
const checkCmd = isWindows ? 'where' : 'which';
|
|
33
|
-
|
|
34
|
-
const candidates: [string, string][] = isWindows
|
|
35
|
-
? [['winget', 'winget'], ['choco', 'choco'], ['scoop', 'scoop']]
|
|
36
|
-
: [['apt-get', 'apt'], ['brew', 'brew'], ['dnf', 'dnf']];
|
|
37
|
-
|
|
38
|
-
for (const [bin, name] of candidates) {
|
|
39
|
-
try {
|
|
40
|
-
await this.shell.exec(`${checkCmd} ${bin}`);
|
|
41
|
-
this.manager = name;
|
|
42
|
-
return name;
|
|
43
|
-
} catch (e) {}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
throw new TyrError(
|
|
47
|
-
'No supported package manager detected.',
|
|
48
|
-
null,
|
|
49
|
-
isWindows
|
|
50
|
-
? 'Install winget (Windows Package Manager), Chocolatey, or Scoop.'
|
|
51
|
-
: 'Make sure apt, brew or dnf is installed on your system.'
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* @method install
|
|
57
|
-
* @description Installs a system package using the detected package manager.
|
|
58
|
-
* @param {string} packageName - Name of the package to install (e.g. 'nginx', 'python3').
|
|
59
|
-
* @example
|
|
60
|
-
* await pkg.install('nginx');
|
|
61
|
-
*/
|
|
62
|
-
public async install(packageName: string): Promise<void> {
|
|
63
|
-
const mgr = await this.detect();
|
|
64
|
-
this.logger.info(`Installing ${packageName} using ${mgr}...`);
|
|
65
|
-
|
|
66
|
-
const commands: Record<string, string> = {
|
|
67
|
-
apt: `sudo apt-get install -y ${packageName}`,
|
|
68
|
-
brew: `brew install ${packageName}`,
|
|
69
|
-
dnf: `sudo dnf install -y ${packageName}`,
|
|
70
|
-
winget: `winget install ${packageName}`,
|
|
71
|
-
choco: `choco install -y ${packageName}`,
|
|
72
|
-
scoop: `scoop install ${packageName}`,
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
try {
|
|
76
|
-
await this.shell.exec(commands[mgr]);
|
|
77
|
-
this.logger.success(`Package ${packageName} installed.`);
|
|
78
|
-
} catch (e) {
|
|
79
|
-
if (e instanceof TyrError) throw e;
|
|
80
|
-
throw new TyrError(`Could not install package: ${packageName}`, e, `Try running the install command manually with ${mgr}.`);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export const PackageManagerTests = {
|
|
86
|
-
detect: {},
|
|
87
|
-
};
|
|
1
|
+
import { ShellManager } from './ShellManager.js';
|
|
2
|
+
import { Logger } from '../core/Logger.js';
|
|
3
|
+
import { TyrError } from '../core/TyrError.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @class PackageManager
|
|
7
|
+
* @description OS-agnostic package manager. Automatically detects whether the system uses apt, brew or dnf and installs native software.
|
|
8
|
+
*/
|
|
9
|
+
export class PackageManager {
|
|
10
|
+
private shell: ShellManager;
|
|
11
|
+
private logger: Logger;
|
|
12
|
+
private manager: string | null;
|
|
13
|
+
|
|
14
|
+
constructor(shell: ShellManager, logger: Logger) {
|
|
15
|
+
this.shell = shell;
|
|
16
|
+
this.logger = logger;
|
|
17
|
+
this.manager = null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @method detect
|
|
22
|
+
* @description Attempts to identify the package manager installed on the host system.
|
|
23
|
+
* @returns {Promise<string>} The name of the detected binary ('apt', 'brew', 'dnf').
|
|
24
|
+
* @example
|
|
25
|
+
* const mgr = await pkg.detect();
|
|
26
|
+
* logger.info(`Using: ${mgr}`);
|
|
27
|
+
*/
|
|
28
|
+
public async detect(): Promise<string> {
|
|
29
|
+
if (this.manager) return this.manager;
|
|
30
|
+
|
|
31
|
+
const isWindows = process.platform === 'win32';
|
|
32
|
+
const checkCmd = isWindows ? 'where' : 'which';
|
|
33
|
+
|
|
34
|
+
const candidates: [string, string][] = isWindows
|
|
35
|
+
? [['winget', 'winget'], ['choco', 'choco'], ['scoop', 'scoop']]
|
|
36
|
+
: [['apt-get', 'apt'], ['brew', 'brew'], ['dnf', 'dnf']];
|
|
37
|
+
|
|
38
|
+
for (const [bin, name] of candidates) {
|
|
39
|
+
try {
|
|
40
|
+
await this.shell.exec(`${checkCmd} ${bin}`);
|
|
41
|
+
this.manager = name;
|
|
42
|
+
return name;
|
|
43
|
+
} catch (e) {}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
throw new TyrError(
|
|
47
|
+
'No supported package manager detected.',
|
|
48
|
+
null,
|
|
49
|
+
isWindows
|
|
50
|
+
? 'Install winget (Windows Package Manager), Chocolatey, or Scoop.'
|
|
51
|
+
: 'Make sure apt, brew or dnf is installed on your system.'
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @method install
|
|
57
|
+
* @description Installs a system package using the detected package manager.
|
|
58
|
+
* @param {string} packageName - Name of the package to install (e.g. 'nginx', 'python3').
|
|
59
|
+
* @example
|
|
60
|
+
* await pkg.install('nginx');
|
|
61
|
+
*/
|
|
62
|
+
public async install(packageName: string): Promise<void> {
|
|
63
|
+
const mgr = await this.detect();
|
|
64
|
+
this.logger.info(`Installing ${packageName} using ${mgr}...`);
|
|
65
|
+
|
|
66
|
+
const commands: Record<string, string> = {
|
|
67
|
+
apt: `sudo apt-get install -y ${packageName}`,
|
|
68
|
+
brew: `brew install ${packageName}`,
|
|
69
|
+
dnf: `sudo dnf install -y ${packageName}`,
|
|
70
|
+
winget: `winget install ${packageName}`,
|
|
71
|
+
choco: `choco install -y ${packageName}`,
|
|
72
|
+
scoop: `scoop install ${packageName}`,
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
await this.shell.exec(commands[mgr]);
|
|
77
|
+
this.logger.success(`Package ${packageName} installed.`);
|
|
78
|
+
} catch (e) {
|
|
79
|
+
if (e instanceof TyrError) throw e;
|
|
80
|
+
throw new TyrError(`Could not install package: ${packageName}`, e, `Try running the install command manually with ${mgr}.`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export const PackageManagerTests = {
|
|
86
|
+
detect: {},
|
|
87
|
+
};
|
package/src/lib/SQLManager.ts
CHANGED
|
@@ -1,118 +1,118 @@
|
|
|
1
|
-
import dotenv from 'dotenv';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import { homedir } from 'os';
|
|
4
|
-
import sql, { config as SQLConfig } from 'mssql';
|
|
5
|
-
|
|
6
|
-
// Load credentials from ~/.tyr/.env — silently, optional
|
|
7
|
-
(dotenv as any).config({ path: path.join(homedir(), '.tyr', '.env'), quiet: true });
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* @class SQLManager
|
|
11
|
-
* @description Conector con la base de datos SQL Server.
|
|
12
|
-
*/
|
|
13
|
-
export class SQLManager {
|
|
14
|
-
private pool!: sql.ConnectionPool;
|
|
15
|
-
private connected = false;
|
|
16
|
-
|
|
17
|
-
constructor() {
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
private async init(): Promise<void> {
|
|
21
|
-
if (!this.connected) {
|
|
22
|
-
|
|
23
|
-
const db_config: SQLConfig = {
|
|
24
|
-
user: process.env.MSSQL_USER,
|
|
25
|
-
password: process.env.MSSQL_PASSWORD,
|
|
26
|
-
server: process.env.MSSQL_SERVER || '',
|
|
27
|
-
database: process.env.MSSQL_DATABASE,
|
|
28
|
-
options: {
|
|
29
|
-
encrypt: false,
|
|
30
|
-
trustServerCertificate: true
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
this.pool = await sql.connect(db_config);
|
|
35
|
-
this.connected = true;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* @method select
|
|
41
|
-
* @description Ejecuta un comando SELECT en SQL Server y devuelve el resultado como JSON.
|
|
42
|
-
* @param {string} query - El comando SELECT completo.
|
|
43
|
-
* @returns {Promise<any[]>} Los registros del resultado.
|
|
44
|
-
* @example
|
|
45
|
-
* await dbManager.init();
|
|
46
|
-
* const data = await dbManager.select('SELECT * FROM tabla');
|
|
47
|
-
*/
|
|
48
|
-
public async select(query: string): Promise<any[]> {
|
|
49
|
-
await this.init();
|
|
50
|
-
|
|
51
|
-
const result = await this.pool.request().query(query);
|
|
52
|
-
|
|
53
|
-
await this.close();
|
|
54
|
-
return result.recordset;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* @method searchBrokerOnDB
|
|
59
|
-
* @description Busca broker por hostname usando la query encoded.
|
|
60
|
-
* @param {string | URL} url - URL o string para extraer hostname.
|
|
61
|
-
* @returns {Promise<string>} Nombre del broker.
|
|
62
|
-
* @example
|
|
63
|
-
* const broker = await db.searchBrokerOnDB('https://www.foo.com');
|
|
64
|
-
*/
|
|
65
|
-
public async searchBrokerOnDB(url: string | URL): Promise<string> {
|
|
66
|
-
let urlString = url.toString();
|
|
67
|
-
|
|
68
|
-
if (!urlString.startsWith("http://") && !urlString.startsWith("https://")) {
|
|
69
|
-
urlString = "https://" + urlString;
|
|
70
|
-
}
|
|
71
|
-
let urlObj = new URL(urlString).hostname;
|
|
72
|
-
|
|
73
|
-
if (urlObj.split('.').length < 3) {
|
|
74
|
-
urlObj = ['www', urlObj].join('.');
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const isWeb = urlObj.startsWith('www') ||
|
|
78
|
-
urlObj.startsWith('horizon') ||
|
|
79
|
-
urlObj.startsWith('ambiance') ||
|
|
80
|
-
urlObj.startsWith('panorama') ||
|
|
81
|
-
urlObj.startsWith('flow') ||
|
|
82
|
-
urlObj.startsWith('panorama') ||
|
|
83
|
-
urlObj.startsWith('avantio') ||
|
|
84
|
-
urlObj.startsWith('demo');
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const query = isWeb ? `SELECT basedir as BROKER from ftpUsers where CONCAT(prefijo, '.', dominio) = '${urlObj}'` : `SELECT LOGIN_DS AS BROKER from CR_CANALVENTAS WHERE WEB_DS = '${urlObj}'`;
|
|
88
|
-
|
|
89
|
-
await this.init();
|
|
90
|
-
|
|
91
|
-
const result = await this.pool.request().query(query);
|
|
92
|
-
|
|
93
|
-
await this.close();
|
|
94
|
-
|
|
95
|
-
if (!result.recordset[0] || !result.recordset[0].BROKER) {
|
|
96
|
-
throw new Error(`No se encontró broker para ${urlObj}`);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
return result.recordset[0].BROKER as string;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
private async close(): Promise<void> {
|
|
103
|
-
if (this.connected && this.pool) {
|
|
104
|
-
await this.pool.close();
|
|
105
|
-
this.connected = false;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* @object SQLManagerTests
|
|
112
|
-
* @description Parámetros de pruebas para validar la funcionalidad de SQLManager.
|
|
113
|
-
*/
|
|
114
|
-
export const SQLManagerTests = {
|
|
115
|
-
// init: {},
|
|
116
|
-
// select: { query: 'SELECT 1 as test_value' },
|
|
117
|
-
// connectionPool: { queries: ['SELECT 1 as q1', 'SELECT 2 as q2', 'SELECT 3 as q3'] }
|
|
1
|
+
import dotenv from 'dotenv';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { homedir } from 'os';
|
|
4
|
+
import sql, { config as SQLConfig } from 'mssql';
|
|
5
|
+
|
|
6
|
+
// Load credentials from ~/.tyr/.env — silently, optional
|
|
7
|
+
(dotenv as any).config({ path: path.join(homedir(), '.tyr', '.env'), quiet: true });
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @class SQLManager
|
|
11
|
+
* @description Conector con la base de datos SQL Server.
|
|
12
|
+
*/
|
|
13
|
+
export class SQLManager {
|
|
14
|
+
private pool!: sql.ConnectionPool;
|
|
15
|
+
private connected = false;
|
|
16
|
+
|
|
17
|
+
constructor() {
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
private async init(): Promise<void> {
|
|
21
|
+
if (!this.connected) {
|
|
22
|
+
|
|
23
|
+
const db_config: SQLConfig = {
|
|
24
|
+
user: process.env.MSSQL_USER,
|
|
25
|
+
password: process.env.MSSQL_PASSWORD,
|
|
26
|
+
server: process.env.MSSQL_SERVER || '',
|
|
27
|
+
database: process.env.MSSQL_DATABASE,
|
|
28
|
+
options: {
|
|
29
|
+
encrypt: false,
|
|
30
|
+
trustServerCertificate: true
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
this.pool = await sql.connect(db_config);
|
|
35
|
+
this.connected = true;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @method select
|
|
41
|
+
* @description Ejecuta un comando SELECT en SQL Server y devuelve el resultado como JSON.
|
|
42
|
+
* @param {string} query - El comando SELECT completo.
|
|
43
|
+
* @returns {Promise<any[]>} Los registros del resultado.
|
|
44
|
+
* @example
|
|
45
|
+
* await dbManager.init();
|
|
46
|
+
* const data = await dbManager.select('SELECT * FROM tabla');
|
|
47
|
+
*/
|
|
48
|
+
public async select(query: string): Promise<any[]> {
|
|
49
|
+
await this.init();
|
|
50
|
+
|
|
51
|
+
const result = await this.pool.request().query(query);
|
|
52
|
+
|
|
53
|
+
await this.close();
|
|
54
|
+
return result.recordset;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @method searchBrokerOnDB
|
|
59
|
+
* @description Busca broker por hostname usando la query encoded.
|
|
60
|
+
* @param {string | URL} url - URL o string para extraer hostname.
|
|
61
|
+
* @returns {Promise<string>} Nombre del broker.
|
|
62
|
+
* @example
|
|
63
|
+
* const broker = await db.searchBrokerOnDB('https://www.foo.com');
|
|
64
|
+
*/
|
|
65
|
+
public async searchBrokerOnDB(url: string | URL): Promise<string> {
|
|
66
|
+
let urlString = url.toString();
|
|
67
|
+
|
|
68
|
+
if (!urlString.startsWith("http://") && !urlString.startsWith("https://")) {
|
|
69
|
+
urlString = "https://" + urlString;
|
|
70
|
+
}
|
|
71
|
+
let urlObj = new URL(urlString).hostname;
|
|
72
|
+
|
|
73
|
+
if (urlObj.split('.').length < 3) {
|
|
74
|
+
urlObj = ['www', urlObj].join('.');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const isWeb = urlObj.startsWith('www') ||
|
|
78
|
+
urlObj.startsWith('horizon') ||
|
|
79
|
+
urlObj.startsWith('ambiance') ||
|
|
80
|
+
urlObj.startsWith('panorama') ||
|
|
81
|
+
urlObj.startsWith('flow') ||
|
|
82
|
+
urlObj.startsWith('panorama') ||
|
|
83
|
+
urlObj.startsWith('avantio') ||
|
|
84
|
+
urlObj.startsWith('demo');
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
const query = isWeb ? `SELECT basedir as BROKER from ftpUsers where CONCAT(prefijo, '.', dominio) = '${urlObj}'` : `SELECT LOGIN_DS AS BROKER from CR_CANALVENTAS WHERE WEB_DS = '${urlObj}'`;
|
|
88
|
+
|
|
89
|
+
await this.init();
|
|
90
|
+
|
|
91
|
+
const result = await this.pool.request().query(query);
|
|
92
|
+
|
|
93
|
+
await this.close();
|
|
94
|
+
|
|
95
|
+
if (!result.recordset[0] || !result.recordset[0].BROKER) {
|
|
96
|
+
throw new Error(`No se encontró broker para ${urlObj}`);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return result.recordset[0].BROKER as string;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
private async close(): Promise<void> {
|
|
103
|
+
if (this.connected && this.pool) {
|
|
104
|
+
await this.pool.close();
|
|
105
|
+
this.connected = false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* @object SQLManagerTests
|
|
112
|
+
* @description Parámetros de pruebas para validar la funcionalidad de SQLManager.
|
|
113
|
+
*/
|
|
114
|
+
export const SQLManagerTests = {
|
|
115
|
+
// init: {},
|
|
116
|
+
// select: { query: 'SELECT 1 as test_value' },
|
|
117
|
+
// connectionPool: { queries: ['SELECT 1 as q1', 'SELECT 2 as q2', 'SELECT 3 as q3'] }
|
|
118
118
|
};
|