codecrypto-cli 1.0.21 → 1.0.22
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/dist/commands/deploy-mcp.d.ts.map +1 -1
- package/dist/commands/deploy-mcp.js +149 -33
- package/dist/commands/deploy-mcp.js.map +1 -1
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +149 -33
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +199 -14
- package/dist/commands/doctor.js.map +1 -1
- package/package.json +1 -1
- package/src/commands/deploy-mcp.ts +173 -39
- package/src/commands/deploy.ts +173 -39
- package/src/commands/doctor.ts +206 -19
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import ora from 'ora';
|
|
4
|
+
import inquirer from 'inquirer';
|
|
4
5
|
import { execSync, spawn } from 'child_process';
|
|
5
6
|
import * as fs from 'fs';
|
|
6
7
|
import * as path from 'path';
|
|
@@ -59,8 +60,8 @@ export const deployMcpCommand = new Command('deploy-mcp')
|
|
|
59
60
|
projectName = path.basename(resolvedProjectPath).toLowerCase().replace(/[^a-z0-9._-]/g, '-');
|
|
60
61
|
}
|
|
61
62
|
|
|
62
|
-
// Obtener el prefijo de imagen desde
|
|
63
|
-
const dockerHubUsername = getDockerHubUsernameFromToken();
|
|
63
|
+
// Obtener el prefijo de imagen desde Docker config o solicitar por teclado
|
|
64
|
+
const dockerHubUsername = await getDockerHubUsernameFromToken();
|
|
64
65
|
const imageBase = `${dockerHubUsername}/${projectName}`;
|
|
65
66
|
const imageName = `${imageBase}:${version}`;
|
|
66
67
|
const imageLatest = `${imageBase}:latest`;
|
|
@@ -564,49 +565,182 @@ echo "✅ Deployment preparation completed inside container"
|
|
|
564
565
|
}
|
|
565
566
|
});
|
|
566
567
|
|
|
567
|
-
// Función para obtener el username de Docker Hub desde
|
|
568
|
-
function getDockerHubUsernameFromToken(): string {
|
|
569
|
-
|
|
568
|
+
// Función para obtener el username de Docker Hub desde Docker config o solicitar por teclado
|
|
569
|
+
async function getDockerHubUsernameFromToken(): Promise<string> {
|
|
570
|
+
// Obtener el username desde Docker config (requerido para poder hacer push)
|
|
571
|
+
const dockerConfigPath = path.join(os.homedir(), '.docker', 'config.json');
|
|
570
572
|
|
|
571
|
-
if (!fs.existsSync(
|
|
572
|
-
throw new Error(
|
|
573
|
+
if (!fs.existsSync(dockerConfigPath)) {
|
|
574
|
+
throw new Error(
|
|
575
|
+
'Docker authentication not found. Please login to Docker first.\n' +
|
|
576
|
+
' Run: docker login\n' +
|
|
577
|
+
' This is required to push images to Docker Hub.'
|
|
578
|
+
);
|
|
573
579
|
}
|
|
574
580
|
|
|
575
|
-
let tokenData: any;
|
|
576
581
|
try {
|
|
577
|
-
|
|
582
|
+
const dockerConfig = JSON.parse(fs.readFileSync(dockerConfigPath, 'utf-8'));
|
|
583
|
+
|
|
584
|
+
// Verificar si hay credsStore (las credenciales están en el keychain del sistema)
|
|
585
|
+
const hasCredsStore = dockerConfig.credsStore && dockerConfig.credsStore !== '';
|
|
586
|
+
|
|
587
|
+
// Buscar username en Docker Hub auth
|
|
588
|
+
let dockerHubKeys: string[] = [];
|
|
589
|
+
if (dockerConfig.auths && Object.keys(dockerConfig.auths).length > 0) {
|
|
590
|
+
dockerHubKeys = Object.keys(dockerConfig.auths).filter(reg =>
|
|
591
|
+
reg.includes('docker.io') ||
|
|
592
|
+
reg.includes('hub.docker.com') ||
|
|
593
|
+
reg === 'https://index.docker.io/v1/'
|
|
594
|
+
);
|
|
595
|
+
|
|
596
|
+
// Si hay credsStore, los auths pueden estar vacíos pero las credenciales están en el keychain
|
|
597
|
+
if (hasCredsStore && dockerHubKeys.length > 0) {
|
|
598
|
+
// Intentar obtener username desde docker info
|
|
599
|
+
try {
|
|
600
|
+
const dockerInfo = execSync('docker info', { encoding: 'utf-8', stdio: 'pipe', timeout: 5000 });
|
|
601
|
+
const usernameMatch = dockerInfo.match(/Username:\s*(.+)/i);
|
|
602
|
+
if (usernameMatch && usernameMatch[1]) {
|
|
603
|
+
let username = usernameMatch[1].trim();
|
|
604
|
+
|
|
605
|
+
// Si el username es un email, extraer solo la parte antes del @
|
|
606
|
+
if (username.includes('@')) {
|
|
607
|
+
username = username.split('@')[0];
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
// Sanitizar el username para Docker Hub
|
|
611
|
+
username = username.toLowerCase()
|
|
612
|
+
.replace(/[^a-z0-9._-]/g, '-')
|
|
613
|
+
.replace(/^-+|-+$/g, '')
|
|
614
|
+
.replace(/-+/g, '-')
|
|
615
|
+
.replace(/\.+/g, '.')
|
|
616
|
+
.substring(0, 30);
|
|
617
|
+
|
|
618
|
+
if (username) {
|
|
619
|
+
return username;
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
} catch (infoError) {
|
|
623
|
+
// Si docker info falla, continuar con otros métodos
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
// Si no hay credsStore, buscar username directamente en auths
|
|
628
|
+
if (!hasCredsStore) {
|
|
629
|
+
for (const key of dockerHubKeys) {
|
|
630
|
+
const authData = dockerConfig.auths[key];
|
|
631
|
+
if (authData && authData.username) {
|
|
632
|
+
let username = authData.username;
|
|
633
|
+
|
|
634
|
+
// Si el username es un email, extraer solo la parte antes del @
|
|
635
|
+
if (username.includes('@')) {
|
|
636
|
+
username = username.split('@')[0];
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
// Sanitizar el username para Docker Hub
|
|
640
|
+
username = username.toLowerCase()
|
|
641
|
+
.replace(/[^a-z0-9._-]/g, '-')
|
|
642
|
+
.replace(/^-+|-+$/g, '')
|
|
643
|
+
.replace(/-+/g, '-')
|
|
644
|
+
.replace(/\.+/g, '.')
|
|
645
|
+
.substring(0, 30);
|
|
646
|
+
|
|
647
|
+
if (username) {
|
|
648
|
+
return username;
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
// Si hay credsStore pero no encontramos username, intentar con docker info
|
|
656
|
+
if (hasCredsStore) {
|
|
657
|
+
try {
|
|
658
|
+
const dockerInfo = execSync('docker info', { encoding: 'utf-8', stdio: 'pipe', timeout: 5000 });
|
|
659
|
+
const usernameMatch = dockerInfo.match(/Username:\s*(.+)/i);
|
|
660
|
+
if (usernameMatch && usernameMatch[1]) {
|
|
661
|
+
let username = usernameMatch[1].trim();
|
|
662
|
+
|
|
663
|
+
// Si el username es un email, extraer solo la parte antes del @
|
|
664
|
+
if (username.includes('@')) {
|
|
665
|
+
username = username.split('@')[0];
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// Sanitizar el username para Docker Hub
|
|
669
|
+
username = username.toLowerCase()
|
|
670
|
+
.replace(/[^a-z0-9._-]/g, '-')
|
|
671
|
+
.replace(/^-+|-+$/g, '')
|
|
672
|
+
.replace(/-+/g, '-')
|
|
673
|
+
.replace(/\.+/g, '.')
|
|
674
|
+
.substring(0, 30);
|
|
675
|
+
|
|
676
|
+
if (username) {
|
|
677
|
+
return username;
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
} catch (infoError) {
|
|
681
|
+
// Continuar con el error
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
// Si llegamos aquí, no encontramos el username - solicitar por teclado
|
|
686
|
+
console.log(chalk.yellow('\n⚠️ Could not automatically detect Docker Hub username.'));
|
|
687
|
+
console.log(chalk.gray(' Please enter your Docker Hub username manually.\n'));
|
|
688
|
+
|
|
689
|
+
const answer = await inquirer.prompt([
|
|
690
|
+
{
|
|
691
|
+
type: 'input',
|
|
692
|
+
name: 'username',
|
|
693
|
+
message: 'Docker Hub username:',
|
|
694
|
+
validate: (input: string) => {
|
|
695
|
+
if (!input || input.trim().length === 0) {
|
|
696
|
+
return 'Username is required';
|
|
697
|
+
}
|
|
698
|
+
// Validar formato básico de username Docker Hub
|
|
699
|
+
const sanitized = input.toLowerCase().replace(/[^a-z0-9._-]/g, '');
|
|
700
|
+
if (sanitized !== input.toLowerCase()) {
|
|
701
|
+
return 'Username can only contain lowercase letters, numbers, dots, hyphens, and underscores';
|
|
702
|
+
}
|
|
703
|
+
if (input.length > 30) {
|
|
704
|
+
return 'Username must be 30 characters or less';
|
|
705
|
+
}
|
|
706
|
+
return true;
|
|
707
|
+
},
|
|
708
|
+
filter: (input: string) => {
|
|
709
|
+
// Si el input es un email, extraer solo la parte antes del @
|
|
710
|
+
if (input.includes('@')) {
|
|
711
|
+
return input.split('@')[0].trim();
|
|
712
|
+
}
|
|
713
|
+
return input.trim();
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
]);
|
|
717
|
+
|
|
718
|
+
let username = answer.username.toLowerCase();
|
|
719
|
+
|
|
720
|
+
// Sanitizar el username para Docker Hub
|
|
721
|
+
username = username
|
|
722
|
+
.replace(/[^a-z0-9._-]/g, '-')
|
|
723
|
+
.replace(/^-+|-+$/g, '')
|
|
724
|
+
.replace(/-+/g, '-')
|
|
725
|
+
.replace(/\.+/g, '.')
|
|
726
|
+
.substring(0, 30);
|
|
727
|
+
|
|
728
|
+
if (!username) {
|
|
729
|
+
throw new Error('Invalid username provided');
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
return username;
|
|
578
733
|
} catch (error: any) {
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
// Extraer el username del email (parte antes del @) y sanitizarlo para Docker Hub
|
|
589
|
-
const emailParts = email.split('@');
|
|
590
|
-
if (emailParts.length < 2) {
|
|
591
|
-
throw new Error(`Invalid email format in token.json: ${email}`);
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
let username = emailParts[0].toLowerCase();
|
|
595
|
-
|
|
596
|
-
// Sanitizar el username para Docker Hub
|
|
597
|
-
// Docker Hub permite: letras minúsculas, números, guiones, guiones bajos
|
|
598
|
-
username = username
|
|
599
|
-
.replace(/[^a-z0-9._-]/g, '-') // Reemplazar caracteres inválidos con guiones
|
|
600
|
-
.replace(/^-+|-+$/g, '') // Eliminar guiones al inicio y final
|
|
601
|
-
.replace(/-+/g, '-') // Reemplazar múltiples guiones con uno solo
|
|
602
|
-
.replace(/\.+/g, '.') // Reemplazar múltiples puntos con uno solo
|
|
603
|
-
.substring(0, 30); // Limitar longitud (Docker Hub tiene límites)
|
|
604
|
-
|
|
605
|
-
if (!username) {
|
|
606
|
-
throw new Error(`Could not extract valid username from email: ${email}`);
|
|
734
|
+
// Si el error ya tiene mensaje, relanzarlo
|
|
735
|
+
if (error.message && (error.message.includes('Docker') || error.message.includes('username'))) {
|
|
736
|
+
throw error;
|
|
737
|
+
}
|
|
738
|
+
// Si hay error leyendo Docker config, lanzar error
|
|
739
|
+
throw new Error(
|
|
740
|
+
`Failed to read Docker config: ${error.message || String(error)}\n` +
|
|
741
|
+
' Please ensure you are logged in to Docker: docker login'
|
|
742
|
+
);
|
|
607
743
|
}
|
|
608
|
-
|
|
609
|
-
return username;
|
|
610
744
|
}
|
|
611
745
|
|
|
612
746
|
// Función para leer certificados Docker desde token.json
|
package/src/commands/deploy.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import ora from 'ora';
|
|
4
|
+
import inquirer from 'inquirer';
|
|
4
5
|
import { execSync, spawn } from 'child_process';
|
|
5
6
|
import * as fs from 'fs';
|
|
6
7
|
import * as path from 'path';
|
|
@@ -134,8 +135,8 @@ export const deployCommand = new Command('deploy')
|
|
|
134
135
|
projectName = path.basename(resolvedProjectPath).toLowerCase().replace(/[^a-z0-9._-]/g, '-');
|
|
135
136
|
}
|
|
136
137
|
|
|
137
|
-
// Obtener el prefijo de imagen desde
|
|
138
|
-
const dockerHubUsername = getDockerHubUsernameFromToken();
|
|
138
|
+
// Obtener el prefijo de imagen desde Docker config o solicitar por teclado
|
|
139
|
+
const dockerHubUsername = await getDockerHubUsernameFromToken();
|
|
139
140
|
const imageBase = `${dockerHubUsername}/${projectName}`;
|
|
140
141
|
const imageName = `${imageBase}:${version}`;
|
|
141
142
|
const imageLatest = `${imageBase}:latest`;
|
|
@@ -702,49 +703,182 @@ CMD ${JSON.stringify(startCmd)}
|
|
|
702
703
|
}
|
|
703
704
|
});
|
|
704
705
|
|
|
705
|
-
// Función para obtener el username de Docker Hub desde
|
|
706
|
-
function getDockerHubUsernameFromToken(): string {
|
|
707
|
-
|
|
706
|
+
// Función para obtener el username de Docker Hub desde Docker config o solicitar por teclado
|
|
707
|
+
async function getDockerHubUsernameFromToken(): Promise<string> {
|
|
708
|
+
// Obtener el username desde Docker config (requerido para poder hacer push)
|
|
709
|
+
const dockerConfigPath = path.join(os.homedir(), '.docker', 'config.json');
|
|
708
710
|
|
|
709
|
-
if (!fs.existsSync(
|
|
710
|
-
throw new Error(
|
|
711
|
+
if (!fs.existsSync(dockerConfigPath)) {
|
|
712
|
+
throw new Error(
|
|
713
|
+
'Docker authentication not found. Please login to Docker first.\n' +
|
|
714
|
+
' Run: docker login\n' +
|
|
715
|
+
' This is required to push images to Docker Hub.'
|
|
716
|
+
);
|
|
711
717
|
}
|
|
712
718
|
|
|
713
|
-
let tokenData: any;
|
|
714
719
|
try {
|
|
715
|
-
|
|
720
|
+
const dockerConfig = JSON.parse(fs.readFileSync(dockerConfigPath, 'utf-8'));
|
|
721
|
+
|
|
722
|
+
// Verificar si hay credsStore (las credenciales están en el keychain del sistema)
|
|
723
|
+
const hasCredsStore = dockerConfig.credsStore && dockerConfig.credsStore !== '';
|
|
724
|
+
|
|
725
|
+
// Buscar username en Docker Hub auth
|
|
726
|
+
let dockerHubKeys: string[] = [];
|
|
727
|
+
if (dockerConfig.auths && Object.keys(dockerConfig.auths).length > 0) {
|
|
728
|
+
dockerHubKeys = Object.keys(dockerConfig.auths).filter(reg =>
|
|
729
|
+
reg.includes('docker.io') ||
|
|
730
|
+
reg.includes('hub.docker.com') ||
|
|
731
|
+
reg === 'https://index.docker.io/v1/'
|
|
732
|
+
);
|
|
733
|
+
|
|
734
|
+
// Si hay credsStore, los auths pueden estar vacíos pero las credenciales están en el keychain
|
|
735
|
+
if (hasCredsStore && dockerHubKeys.length > 0) {
|
|
736
|
+
// Intentar obtener username desde docker info
|
|
737
|
+
try {
|
|
738
|
+
const dockerInfo = execSync('docker info', { encoding: 'utf-8', stdio: 'pipe', timeout: 5000 });
|
|
739
|
+
const usernameMatch = dockerInfo.match(/Username:\s*(.+)/i);
|
|
740
|
+
if (usernameMatch && usernameMatch[1]) {
|
|
741
|
+
let username = usernameMatch[1].trim();
|
|
742
|
+
|
|
743
|
+
// Si el username es un email, extraer solo la parte antes del @
|
|
744
|
+
if (username.includes('@')) {
|
|
745
|
+
username = username.split('@')[0];
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
// Sanitizar el username para Docker Hub
|
|
749
|
+
username = username.toLowerCase()
|
|
750
|
+
.replace(/[^a-z0-9._-]/g, '-')
|
|
751
|
+
.replace(/^-+|-+$/g, '')
|
|
752
|
+
.replace(/-+/g, '-')
|
|
753
|
+
.replace(/\.+/g, '.')
|
|
754
|
+
.substring(0, 30);
|
|
755
|
+
|
|
756
|
+
if (username) {
|
|
757
|
+
return username;
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
} catch (infoError) {
|
|
761
|
+
// Si docker info falla, continuar con otros métodos
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
// Si no hay credsStore, buscar username directamente en auths
|
|
766
|
+
if (!hasCredsStore) {
|
|
767
|
+
for (const key of dockerHubKeys) {
|
|
768
|
+
const authData = dockerConfig.auths[key];
|
|
769
|
+
if (authData && authData.username) {
|
|
770
|
+
let username = authData.username;
|
|
771
|
+
|
|
772
|
+
// Si el username es un email, extraer solo la parte antes del @
|
|
773
|
+
if (username.includes('@')) {
|
|
774
|
+
username = username.split('@')[0];
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
// Sanitizar el username para Docker Hub
|
|
778
|
+
username = username.toLowerCase()
|
|
779
|
+
.replace(/[^a-z0-9._-]/g, '-')
|
|
780
|
+
.replace(/^-+|-+$/g, '')
|
|
781
|
+
.replace(/-+/g, '-')
|
|
782
|
+
.replace(/\.+/g, '.')
|
|
783
|
+
.substring(0, 30);
|
|
784
|
+
|
|
785
|
+
if (username) {
|
|
786
|
+
return username;
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
// Si hay credsStore pero no encontramos username, intentar con docker info
|
|
794
|
+
if (hasCredsStore) {
|
|
795
|
+
try {
|
|
796
|
+
const dockerInfo = execSync('docker info', { encoding: 'utf-8', stdio: 'pipe', timeout: 5000 });
|
|
797
|
+
const usernameMatch = dockerInfo.match(/Username:\s*(.+)/i);
|
|
798
|
+
if (usernameMatch && usernameMatch[1]) {
|
|
799
|
+
let username = usernameMatch[1].trim();
|
|
800
|
+
|
|
801
|
+
// Si el username es un email, extraer solo la parte antes del @
|
|
802
|
+
if (username.includes('@')) {
|
|
803
|
+
username = username.split('@')[0];
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
// Sanitizar el username para Docker Hub
|
|
807
|
+
username = username.toLowerCase()
|
|
808
|
+
.replace(/[^a-z0-9._-]/g, '-')
|
|
809
|
+
.replace(/^-+|-+$/g, '')
|
|
810
|
+
.replace(/-+/g, '-')
|
|
811
|
+
.replace(/\.+/g, '.')
|
|
812
|
+
.substring(0, 30);
|
|
813
|
+
|
|
814
|
+
if (username) {
|
|
815
|
+
return username;
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
} catch (infoError) {
|
|
819
|
+
// Continuar con el error
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
// Si llegamos aquí, no encontramos el username - solicitar por teclado
|
|
824
|
+
console.log(chalk.yellow('\n⚠️ Could not automatically detect Docker Hub username.'));
|
|
825
|
+
console.log(chalk.gray(' Please enter your Docker Hub username manually.\n'));
|
|
826
|
+
|
|
827
|
+
const answer = await inquirer.prompt([
|
|
828
|
+
{
|
|
829
|
+
type: 'input',
|
|
830
|
+
name: 'username',
|
|
831
|
+
message: 'Docker Hub username:',
|
|
832
|
+
validate: (input: string) => {
|
|
833
|
+
if (!input || input.trim().length === 0) {
|
|
834
|
+
return 'Username is required';
|
|
835
|
+
}
|
|
836
|
+
// Validar formato básico de username Docker Hub
|
|
837
|
+
const sanitized = input.toLowerCase().replace(/[^a-z0-9._-]/g, '');
|
|
838
|
+
if (sanitized !== input.toLowerCase()) {
|
|
839
|
+
return 'Username can only contain lowercase letters, numbers, dots, hyphens, and underscores';
|
|
840
|
+
}
|
|
841
|
+
if (input.length > 30) {
|
|
842
|
+
return 'Username must be 30 characters or less';
|
|
843
|
+
}
|
|
844
|
+
return true;
|
|
845
|
+
},
|
|
846
|
+
filter: (input: string) => {
|
|
847
|
+
// Si el input es un email, extraer solo la parte antes del @
|
|
848
|
+
if (input.includes('@')) {
|
|
849
|
+
return input.split('@')[0].trim();
|
|
850
|
+
}
|
|
851
|
+
return input.trim();
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
]);
|
|
855
|
+
|
|
856
|
+
let username = answer.username.toLowerCase();
|
|
857
|
+
|
|
858
|
+
// Sanitizar el username para Docker Hub
|
|
859
|
+
username = username
|
|
860
|
+
.replace(/[^a-z0-9._-]/g, '-')
|
|
861
|
+
.replace(/^-+|-+$/g, '')
|
|
862
|
+
.replace(/-+/g, '-')
|
|
863
|
+
.replace(/\.+/g, '.')
|
|
864
|
+
.substring(0, 30);
|
|
865
|
+
|
|
866
|
+
if (!username) {
|
|
867
|
+
throw new Error('Invalid username provided');
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
return username;
|
|
716
871
|
} catch (error: any) {
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
// Extraer el username del email (parte antes del @) y sanitizarlo para Docker Hub
|
|
727
|
-
const emailParts = email.split('@');
|
|
728
|
-
if (emailParts.length < 2) {
|
|
729
|
-
throw new Error(`Invalid email format in token.json: ${email}`);
|
|
730
|
-
}
|
|
731
|
-
|
|
732
|
-
let username = emailParts[0].toLowerCase();
|
|
733
|
-
|
|
734
|
-
// Sanitizar el username para Docker Hub
|
|
735
|
-
// Docker Hub permite: letras minúsculas, números, guiones, guiones bajos
|
|
736
|
-
username = username
|
|
737
|
-
.replace(/[^a-z0-9._-]/g, '-') // Reemplazar caracteres inválidos con guiones
|
|
738
|
-
.replace(/^-+|-+$/g, '') // Eliminar guiones al inicio y final
|
|
739
|
-
.replace(/-+/g, '-') // Reemplazar múltiples guiones con uno solo
|
|
740
|
-
.replace(/\.+/g, '.') // Reemplazar múltiples puntos con uno solo
|
|
741
|
-
.substring(0, 30); // Limitar longitud (Docker Hub tiene límites)
|
|
742
|
-
|
|
743
|
-
if (!username) {
|
|
744
|
-
throw new Error(`Could not extract valid username from email: ${email}`);
|
|
872
|
+
// Si el error ya tiene mensaje, relanzarlo
|
|
873
|
+
if (error.message && (error.message.includes('Docker') || error.message.includes('username'))) {
|
|
874
|
+
throw error;
|
|
875
|
+
}
|
|
876
|
+
// Si hay error leyendo Docker config, lanzar error
|
|
877
|
+
throw new Error(
|
|
878
|
+
`Failed to read Docker config: ${error.message || String(error)}\n` +
|
|
879
|
+
' Please ensure you are logged in to Docker: docker login'
|
|
880
|
+
);
|
|
745
881
|
}
|
|
746
|
-
|
|
747
|
-
return username;
|
|
748
882
|
}
|
|
749
883
|
|
|
750
884
|
// Función para leer certificados Docker desde token.json
|