codecrypto-cli 1.0.17 → 1.0.18

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.
@@ -17,7 +17,7 @@ export const deployCommand = new Command('deploy')
17
17
  .option('--service-name <name>', 'Service name for remote deployment')
18
18
  .option('--env-file <path>', 'Path to .env file with environment variables')
19
19
  .option('--port <port>', 'Application port', '3000')
20
- .option('--domain-base <domain>', 'Domain base for deployment', 'proyectos.codecrypto.academy')
20
+ .option('--domain-base <domain>', 'Domain base for deployment', 'codecrypto.academy')
21
21
  .option('--image-version <version>', 'Image version/tag to deploy (overrides package.json version)')
22
22
  .option('--skip-git-check', 'Skip Git repository status check', false)
23
23
  .action(async (projectPath: string, destFolder: string, options) => {
@@ -958,6 +958,7 @@ async function deployToRemoteServer(config: {
958
958
  '-l', `traefik.http.routers.${serviceName}-router.entrypoints=websecure`,
959
959
  '-l', `traefik.http.routers.${serviceName}-router.tls=true`,
960
960
  '-l', `traefik.http.services.${serviceName}-service.loadbalancer.server.port=${config.port}`,
961
+ '-l', `traefik.http.services.${serviceName}-service.loadbalancer.passHostHeader=true`,
961
962
  config.imageName
962
963
  ];
963
964
 
@@ -976,6 +977,7 @@ async function deployToRemoteServer(config: {
976
977
  -l traefik.http.routers.${serviceName}-router.entrypoints=websecure \\
977
978
  -l traefik.http.routers.${serviceName}-router.tls=true \\
978
979
  -l traefik.http.services.${serviceName}-service.loadbalancer.server.port=${config.port} \\
980
+ -l traefik.http.services.${serviceName}-service.loadbalancer.passHostHeader=true \\
979
981
  ${config.imageName}`;
980
982
 
981
983
  console.log(chalk.gray('\n🚀 Deployment command (executing on remote Docker):'));
@@ -155,7 +155,9 @@ export const doctorCommand = new Command('doctor')
155
155
  const tokenData = JSON.parse(fs.readFileSync(tokenFilePath, 'utf-8'));
156
156
  if (tokenData.token && tokenData.email) {
157
157
  // Validar el token con el servidor
158
- const serverUrl = tokenData.serverUrl || process.env.CODECRYPTO_API_URL || process.env.API_URL || 'https://proyectos.codecrypto.academy';
158
+ // Siempre usar la URL correcta, ignorando serverUrl guardado si es diferente
159
+ const defaultServerUrl = 'https://proyectos.proyectos.codecrypto.academy';
160
+ const serverUrl = process.env.CODECRYPTO_API_URL || process.env.API_URL || defaultServerUrl;
159
161
  const token = String(tokenData.token).trim();
160
162
 
161
163
  try {
@@ -184,18 +186,25 @@ export const doctorCommand = new Command('doctor')
184
186
  } else {
185
187
  const errorText = await response.text();
186
188
  let errorMessage = 'Token validation failed';
189
+ let errorCode = '';
187
190
  try {
188
191
  const errorJson = JSON.parse(errorText);
189
192
  errorMessage = errorJson.error || errorJson.message || errorMessage;
193
+ errorCode = errorJson.code || errorJson.errorCode || '';
190
194
  } catch {
191
195
  errorMessage = errorText || errorMessage;
192
196
  }
193
197
 
198
+ // Construir mensaje con código de error si existe
199
+ const fullErrorMessage = errorCode
200
+ ? `${errorMessage}\n\n${errorCode}`
201
+ : errorMessage;
202
+
194
203
  tokenCheck.fail(`Token validation failed: ${errorMessage}`);
195
204
  checks.push({
196
205
  name: 'CodeCrypto Token',
197
206
  status: 'error',
198
- message: `Token validation failed: ${errorMessage}`,
207
+ message: `Token validation failed: ${fullErrorMessage}`,
199
208
  details: 'Run "codecrypto auth --force" to refresh your token'
200
209
  });
201
210
  }
@@ -255,10 +264,10 @@ export const doctorCommand = new Command('doctor')
255
264
  });
256
265
  }
257
266
 
258
- // 8. Check server access (proyectos.codecrypto.academy)
259
- const serverCheck = ora('Checking access to proyectos.codecrypto.academy...').start();
267
+ // 8. Check server access (proyectos.proyectos.codecrypto.academy)
268
+ const serverCheck = ora('Checking access to proyectos.proyectos.codecrypto.academy...').start();
260
269
  try {
261
- const serverUrl = 'https://proyectos.codecrypto.academy';
270
+ const serverUrl = 'https://proyectos.proyectos.codecrypto.academy';
262
271
  const controller = new AbortController();
263
272
  const timeoutId = setTimeout(() => controller.abort(), 10000); // 10 seconds timeout
264
273
 
@@ -296,7 +305,7 @@ export const doctorCommand = new Command('doctor')
296
305
  name: 'Server Access',
297
306
  status: 'error',
298
307
  message: 'Server connection timeout',
299
- details: `Cannot reach https://proyectos.codecrypto.academy. Check your internet connection.`
308
+ details: `Cannot reach https://proyectos.proyectos.codecrypto.academy. Check your internet connection.`
300
309
  });
301
310
  } else if (errorMsg.includes('ECONNREFUSED') || errorMsg.includes('ENOTFOUND') || errorMsg.includes('getaddrinfo')) {
302
311
  serverCheck.fail('Cannot resolve server address');
@@ -304,7 +313,7 @@ export const doctorCommand = new Command('doctor')
304
313
  name: 'Server Access',
305
314
  status: 'error',
306
315
  message: 'Cannot resolve server address',
307
- details: `Cannot reach https://proyectos.codecrypto.academy. Check DNS resolution and network connectivity.`
316
+ details: `Cannot reach https://proyectos.proyectos.codecrypto.academy. Check DNS resolution and network connectivity.`
308
317
  });
309
318
  } else {
310
319
  serverCheck.fail('Cannot access server');
@@ -312,7 +321,7 @@ export const doctorCommand = new Command('doctor')
312
321
  name: 'Server Access',
313
322
  status: 'error',
314
323
  message: 'Cannot access server',
315
- details: `Error: ${errorMsg}. Check if https://proyectos.codecrypto.academy is accessible.`
324
+ details: `Error: ${errorMsg}. Check if https://proyectos.proyectos.codecrypto.academy is accessible.`
316
325
  });
317
326
  }
318
327
  }
@@ -448,37 +457,17 @@ export const doctorCommand = new Command('doctor')
448
457
  });
449
458
  }
450
459
 
451
- // 13. Check anvil
452
- const anvilCheck = ora('Checking anvil...').start();
460
+ // 13. Check Besu1 network access (main blockchain)
461
+ const besu1Check = ora('Checking Besu1 network (https://besu1.proyectos.codecrypto.academy, chain-id: 81234)...').start();
453
462
  try {
454
- const anvilVersion = execSync('anvil --version', { encoding: 'utf-8', stdio: 'pipe' }).trim();
455
- anvilCheck.succeed(`anvil: ${anvilVersion}`);
456
- checks.push({
457
- name: 'anvil',
458
- status: 'success',
459
- message: `anvil installed: ${anvilVersion}`
460
- });
461
- } catch (error) {
462
- anvilCheck.fail('anvil not found');
463
- checks.push({
464
- name: 'anvil',
465
- status: 'error',
466
- message: 'anvil is not installed or not in PATH',
467
- details: 'anvil comes with Foundry. Run "foundryup" to update.'
468
- });
469
- }
470
-
471
- // 14. Check if Anvil is running on correct port and chain-id
472
- const anvilRunningCheck = ora('Checking if Anvil is running (port 8545, chain-id 31337)...').start();
473
- try {
474
- // Try to get chain id from the RPC
475
- const rpcUrl = 'http://localhost:8545';
463
+ const rpcUrl = 'https://besu1.proyectos.codecrypto.academy';
464
+
465
+ // Verificar chain-id
476
466
  const chainIdResponse = execSync(
477
467
  `cast chain-id --rpc-url ${rpcUrl}`,
478
- { encoding: 'utf-8', stdio: 'pipe', timeout: 5000 }
468
+ { encoding: 'utf-8', stdio: 'pipe', timeout: 10000 }
479
469
  ).trim();
480
470
 
481
- // cast chain-id returns decimal number, but handle hex if needed
482
471
  let chainId: number;
483
472
  if (chainIdResponse.startsWith('0x') || chainIdResponse.startsWith('0X')) {
484
473
  chainId = parseInt(chainIdResponse, 16);
@@ -486,98 +475,36 @@ export const doctorCommand = new Command('doctor')
486
475
  chainId = parseInt(chainIdResponse, 10);
487
476
  }
488
477
 
489
- if (chainId === 31337) {
490
- anvilRunningCheck.succeed(`Anvil running on port 8545 with chain-id ${chainId}`);
478
+ // Verificar que el chain-id es correcto
479
+ if (chainId !== 81234) {
480
+ besu1Check.fail(`Besu1 network chain-id mismatch: ${chainId} (expected 81234)`);
491
481
  checks.push({
492
- name: 'Anvil Running',
493
- status: 'success',
494
- message: `Anvil running on port 8545 with chain-id ${chainId}`
495
- });
496
- } else {
497
- anvilRunningCheck.fail(`Anvil running but wrong chain-id: ${chainId} (expected 31337)`);
498
- checks.push({
499
- name: 'Anvil Running',
500
- status: 'error',
501
- message: `Anvil running but wrong chain-id: ${chainId}`,
502
- details: 'Start Anvil with: anvil --chain-id 31337 --port 8545'
503
- });
504
- }
505
- } catch (error: any) {
506
- const errorMsg = error.message || String(error);
507
- if (errorMsg.includes('ECONNREFUSED') || errorMsg.includes('Connection refused')) {
508
- anvilRunningCheck.fail('Anvil is not running');
509
- checks.push({
510
- name: 'Anvil Running',
511
- status: 'error',
512
- message: 'Anvil is not running on port 8545',
513
- details: 'Start Anvil with: anvil --chain-id 31337 --port 8545'
514
- });
515
- } else if (errorMsg.includes('timeout') || errorMsg.includes('ETIMEDOUT')) {
516
- anvilRunningCheck.fail('Anvil connection timeout');
517
- checks.push({
518
- name: 'Anvil Running',
482
+ name: 'Besu1 Network',
519
483
  status: 'error',
520
- message: 'Anvil connection timeout',
521
- details: 'Check if Anvil is running: anvil --chain-id 31337 --port 8545'
484
+ message: `Besu1 network chain-id mismatch: ${chainId} (expected 81234)`,
485
+ details: 'Check if https://besu1.proyectos.codecrypto.academy is the correct network'
522
486
  });
523
487
  } else {
524
- anvilRunningCheck.fail('Cannot connect to Anvil');
488
+ // Verificar que puede obtener el block number (confirma que la blockchain está operativa)
489
+ const blockNumberResponse = execSync(
490
+ `cast block-number --rpc-url ${rpcUrl}`,
491
+ { encoding: 'utf-8', stdio: 'pipe', timeout: 10000 }
492
+ ).trim();
493
+
494
+ let blockNumber: number;
495
+ if (blockNumberResponse.startsWith('0x') || blockNumberResponse.startsWith('0X')) {
496
+ blockNumber = parseInt(blockNumberResponse, 16);
497
+ } else {
498
+ blockNumber = parseInt(blockNumberResponse, 10);
499
+ }
500
+
501
+ besu1Check.succeed(`Besu1 network accessible (chain-id: ${chainId}, block: ${blockNumber})`);
525
502
  checks.push({
526
- name: 'Anvil Running',
527
- status: 'error',
528
- message: 'Cannot connect to Anvil',
529
- details: `Error: ${errorMsg}. Start Anvil with: anvil --chain-id 31337 --port 8545`
503
+ name: 'Besu1 Network',
504
+ status: 'success',
505
+ message: `Besu1 network accessible: ${rpcUrl} (chain-id: ${chainId}, block: ${blockNumber})`
530
506
  });
531
507
  }
532
- }
533
-
534
- // 15. Check Anvil account 0
535
- const anvilAccountCheck = ora('Checking Anvil account 0...').start();
536
- try {
537
- const rpcUrl = 'http://localhost:8545';
538
- const balance = execSync(
539
- `cast balance 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 --rpc-url ${rpcUrl}`,
540
- { encoding: 'utf-8', stdio: 'pipe', timeout: 5000 }
541
- ).trim();
542
-
543
- anvilAccountCheck.succeed(`Account 0 balance: ${balance} wei`);
544
- checks.push({
545
- name: 'Anvil Account 0',
546
- status: 'success',
547
- message: `Account 0 available with balance: ${balance} wei`
548
- });
549
- } catch (error: any) {
550
- anvilAccountCheck.fail('Cannot access Anvil account 0');
551
- checks.push({
552
- name: 'Anvil Account 0',
553
- status: 'error',
554
- message: 'Cannot access Anvil account 0',
555
- details: 'Make sure Anvil is running and account 0 is unlocked'
556
- });
557
- }
558
-
559
- // 16. Check Besu1 network access
560
- const besu1Check = ora('Checking Besu1 network (https://besu1.proyectos.codecrypto.academy)...').start();
561
- try {
562
- const rpcUrl = 'https://besu1.proyectos.codecrypto.academy';
563
- const chainIdResponse = execSync(
564
- `cast chain-id --rpc-url ${rpcUrl}`,
565
- { encoding: 'utf-8', stdio: 'pipe', timeout: 10000 }
566
- ).trim();
567
-
568
- let chainId: number;
569
- if (chainIdResponse.startsWith('0x') || chainIdResponse.startsWith('0X')) {
570
- chainId = parseInt(chainIdResponse, 16);
571
- } else {
572
- chainId = parseInt(chainIdResponse, 10);
573
- }
574
-
575
- besu1Check.succeed(`Besu1 network accessible (chain-id: ${chainId})`);
576
- checks.push({
577
- name: 'Besu1 Network',
578
- status: 'success',
579
- message: `Besu1 network accessible: ${rpcUrl} (chain-id: ${chainId})`
580
- });
581
508
  } catch (error: any) {
582
509
  const errorMsg = error.message || String(error);
583
510
  if (errorMsg.includes('ECONNREFUSED') || errorMsg.includes('Connection refused')) {
@@ -607,10 +534,12 @@ export const doctorCommand = new Command('doctor')
607
534
  }
608
535
  }
609
536
 
610
- // 17. Check Besu2 network access
537
+ // 14. Check Besu2 network access
611
538
  const besu2Check = ora('Checking Besu2 network (https://besu2.proyectos.codecrypto.academy)...').start();
612
539
  try {
613
540
  const rpcUrl = 'https://besu2.proyectos.codecrypto.academy';
541
+
542
+ // Verificar chain-id
614
543
  const chainIdResponse = execSync(
615
544
  `cast chain-id --rpc-url ${rpcUrl}`,
616
545
  { encoding: 'utf-8', stdio: 'pipe', timeout: 10000 }
@@ -623,11 +552,24 @@ export const doctorCommand = new Command('doctor')
623
552
  chainId = parseInt(chainIdResponse, 10);
624
553
  }
625
554
 
626
- besu2Check.succeed(`Besu2 network accessible (chain-id: ${chainId})`);
555
+ // Verificar que puede obtener el block number (confirma que la blockchain está operativa)
556
+ const blockNumberResponse = execSync(
557
+ `cast block-number --rpc-url ${rpcUrl}`,
558
+ { encoding: 'utf-8', stdio: 'pipe', timeout: 10000 }
559
+ ).trim();
560
+
561
+ let blockNumber: number;
562
+ if (blockNumberResponse.startsWith('0x') || blockNumberResponse.startsWith('0X')) {
563
+ blockNumber = parseInt(blockNumberResponse, 16);
564
+ } else {
565
+ blockNumber = parseInt(blockNumberResponse, 10);
566
+ }
567
+
568
+ besu2Check.succeed(`Besu2 network accessible (chain-id: ${chainId}, block: ${blockNumber})`);
627
569
  checks.push({
628
570
  name: 'Besu2 Network',
629
571
  status: 'success',
630
- message: `Besu2 network accessible: ${rpcUrl} (chain-id: ${chainId})`
572
+ message: `Besu2 network accessible: ${rpcUrl} (chain-id: ${chainId}, block: ${blockNumber})`
631
573
  });
632
574
  } catch (error: any) {
633
575
  const errorMsg = error.message || String(error);
package/src/index.ts CHANGED
@@ -5,6 +5,7 @@ import * as fs from 'fs';
5
5
  import * as path from 'path';
6
6
  import * as os from 'os';
7
7
  import { deployCommand } from './commands/deploy';
8
+ import { deployMcpCommand } from './commands/deploy-mcp';
8
9
  import { deployScCommand } from './commands/deploy-sc';
9
10
  import { authCommand } from './commands/auth';
10
11
  import { doctorCommand } from './commands/doctor';
@@ -53,6 +54,7 @@ program
53
54
 
54
55
  // Registrar comandos
55
56
  program.addCommand(deployCommand);
57
+ program.addCommand(deployMcpCommand);
56
58
  program.addCommand(deployScCommand);
57
59
  program.addCommand(authCommand);
58
60
  program.addCommand(doctorCommand);