codecrypto-cli 1.0.5 → 1.0.6

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.
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const authCommand: Command;
3
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA+BpC,eAAO,MAAM,WAAW,SA6RpB,CAAC"}
@@ -0,0 +1,298 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.authCommand = void 0;
40
+ const commander_1 = require("commander");
41
+ const chalk_1 = __importDefault(require("chalk"));
42
+ const ora_1 = __importDefault(require("ora"));
43
+ const fs = __importStar(require("fs"));
44
+ const path = __importStar(require("path"));
45
+ const os = __importStar(require("os"));
46
+ const jose_1 = require("jose");
47
+ const API_BASE_URL = 'http://localhost:3000';
48
+ const POLL_INTERVAL = 3000; // 3 segundos
49
+ const MAX_POLL_ATTEMPTS = 100; // Máximo 5 minutos (100 * 3 segundos)
50
+ exports.authCommand = new commander_1.Command('auth')
51
+ .description('Authenticate with CodeCrypto platform')
52
+ .option('--server-url <url>', 'Server URL', API_BASE_URL)
53
+ .option('--poll-interval <seconds>', 'Polling interval in seconds', '3')
54
+ .option('--debug', 'Show debug information', false)
55
+ .action(async (options) => {
56
+ console.log(chalk_1.default.blue('\n🔐 CodeCrypto Authentication\n'));
57
+ const serverUrl = options.serverUrl || API_BASE_URL;
58
+ const pollInterval = parseInt(options.pollInterval || '3', 10) * 1000;
59
+ try {
60
+ // Paso 1: Solicitar código de autenticación
61
+ const requestSpinner = (0, ora_1.default)('Requesting authentication code...').start();
62
+ let tokenData;
63
+ try {
64
+ const response = await fetch(`${serverUrl}/api/tokens`, {
65
+ method: 'POST',
66
+ headers: {
67
+ 'Content-Type': 'application/json',
68
+ },
69
+ });
70
+ if (!response.ok) {
71
+ throw new Error(`HTTP error! status: ${response.status}`);
72
+ }
73
+ const jsonData = await response.json();
74
+ if (options.debug) {
75
+ console.log(chalk_1.default.gray(`\n[DEBUG] POST Response: ${JSON.stringify(jsonData, null, 2)}`));
76
+ }
77
+ tokenData = jsonData;
78
+ // Validar estructura de respuesta
79
+ if (!tokenData || typeof tokenData !== 'object') {
80
+ throw new Error('Invalid response format from server');
81
+ }
82
+ if (!tokenData.success) {
83
+ throw new Error(`Server returned error: ${tokenData.error || 'Unknown error'}`);
84
+ }
85
+ if (!tokenData.data || typeof tokenData.data !== 'object') {
86
+ throw new Error('Response data is missing or invalid');
87
+ }
88
+ // Extraer y validar _id y code de la respuesta
89
+ const responseId = tokenData.data._id;
90
+ const responseCode = tokenData.data.code;
91
+ if (!responseId || typeof responseId !== 'string' || responseId.trim() === '') {
92
+ console.error(chalk_1.default.red(`❌ Error: Invalid or missing _id in response`));
93
+ if (options.debug) {
94
+ console.log(chalk_1.default.gray(`\n[DEBUG] Full response: ${JSON.stringify(tokenData, null, 2)}`));
95
+ }
96
+ throw new Error('Invalid token ID received from server');
97
+ }
98
+ if (!responseCode || typeof responseCode !== 'string' || responseCode.trim() === '') {
99
+ console.error(chalk_1.default.red(`❌ Error: Invalid or missing code in response`));
100
+ if (options.debug) {
101
+ console.log(chalk_1.default.gray(`\n[DEBUG] Full response: ${JSON.stringify(tokenData, null, 2)}`));
102
+ }
103
+ throw new Error('Invalid code received from server');
104
+ }
105
+ requestSpinner.succeed('Authentication code received');
106
+ }
107
+ catch (error) {
108
+ requestSpinner.fail('Failed to request authentication code');
109
+ console.error(chalk_1.default.red(`❌ Error: ${error.message}`));
110
+ if (options.debug && error.stack) {
111
+ console.error(chalk_1.default.gray(`\n[DEBUG] Stack: ${error.stack}`));
112
+ }
113
+ process.exit(1);
114
+ }
115
+ // EXTRAER DIRECTAMENTE DE LA RESPUESTA - NUNCA HARDCODEADO
116
+ // Obtener el _id y code directamente de la respuesta del POST
117
+ const tokenId = String(tokenData.data._id).trim();
118
+ const code = String(tokenData.data.code).trim();
119
+ // Verificación final (no debería fallar si llegamos aquí, pero por seguridad)
120
+ if (!tokenId || tokenId === '' || !code || code === '') {
121
+ console.error(chalk_1.default.red(`❌ Error: Missing tokenId or code after extraction`));
122
+ console.error(chalk_1.default.red(` tokenId: "${tokenId}"`));
123
+ console.error(chalk_1.default.red(` code: "${code}"`));
124
+ console.error(chalk_1.default.red(` Full response data: ${JSON.stringify(tokenData.data, null, 2)}`));
125
+ process.exit(1);
126
+ }
127
+ const tokenUrl = `${serverUrl}/token`;
128
+ // Mostrar información al usuario con el ID REAL obtenido
129
+ console.log(chalk_1.default.green('\n✅ Authentication code generated!'));
130
+ console.log(chalk_1.default.white(`\n Code: ${chalk_1.default.cyan(code)}`));
131
+ console.log(chalk_1.default.white(` Token ID: ${chalk_1.default.gray(tokenId)}`));
132
+ console.log(chalk_1.default.white(`\n Please visit: ${chalk_1.default.cyan.underline(tokenUrl)}`));
133
+ console.log(chalk_1.default.gray(' Enter the code above to complete authentication.\n'));
134
+ // Log explícito del ID que se va a usar
135
+ console.log(chalk_1.default.gray(`[INFO] Will poll using token ID: ${chalk_1.default.yellow(tokenId)}\n`));
136
+ // Paso 2: Polling para verificar el token
137
+ const pollSpinner = (0, ora_1.default)('Waiting for token verification...').start();
138
+ let verifiedToken = null;
139
+ let tokenEmail = null;
140
+ let attempts = 0;
141
+ // Función helper para extraer el token JWT y el email de la respuesta
142
+ const extractToken = (data) => {
143
+ if (!data)
144
+ return { token: null, email: null };
145
+ let jwtToken = null;
146
+ let email = null;
147
+ // Estructura real: data.success && data.data.jwt (el JWT está en data.jwt)
148
+ if (data.success && data.data) {
149
+ // El JWT puede estar en data.jwt o data.token
150
+ jwtToken = data.data.jwt || data.data.token || null;
151
+ // El email está directamente en data.email
152
+ email = data.data.email || null;
153
+ }
154
+ // Estructura alternativa: data.jwt directamente
155
+ else if (data.jwt && typeof data.jwt === 'string') {
156
+ jwtToken = data.jwt;
157
+ email = data.email || null;
158
+ }
159
+ // Estructura alternativa: data.token
160
+ else if (data.token && typeof data.token === 'string') {
161
+ jwtToken = data.token;
162
+ email = data.email || null;
163
+ }
164
+ if (!jwtToken) {
165
+ return { token: null, email: null };
166
+ }
167
+ // Si no tenemos email de la respuesta, intentar extraerlo del JWT
168
+ if (!email) {
169
+ try {
170
+ const decoded = (0, jose_1.decodeJwt)(jwtToken);
171
+ // El email puede estar en diferentes campos del payload
172
+ email = decoded.email ||
173
+ decoded.sub ||
174
+ decoded.user?.email ||
175
+ null;
176
+ if (options.debug) {
177
+ console.log(chalk_1.default.gray(`[DEBUG] JWT decoded payload: ${JSON.stringify(decoded, null, 2)}`));
178
+ console.log(chalk_1.default.gray(`[DEBUG] Email extracted from JWT: ${email}`));
179
+ }
180
+ }
181
+ catch (error) {
182
+ if (options.debug) {
183
+ console.log(chalk_1.default.yellow(`[DEBUG] Could not decode JWT: ${error.message}`));
184
+ }
185
+ }
186
+ }
187
+ else {
188
+ if (options.debug) {
189
+ console.log(chalk_1.default.gray(`[DEBUG] Email from response data: ${email}`));
190
+ }
191
+ }
192
+ return { token: jwtToken, email };
193
+ };
194
+ while (!verifiedToken && attempts < MAX_POLL_ATTEMPTS) {
195
+ try {
196
+ // Esperar antes de cada intento excepto el primero
197
+ if (attempts > 0) {
198
+ await new Promise(resolve => setTimeout(resolve, pollInterval));
199
+ }
200
+ // CONSTRUIR URL CON EL TOKEN ID OBTENIDO DEL POST - NUNCA HARDCODEADO
201
+ // Asegurarse de que tokenId es el valor real de la respuesta
202
+ const currentTokenId = tokenId; // Variable local para asegurar que usamos el valor correcto
203
+ const verifyUrl = `${serverUrl}/api/tokens/${currentTokenId}`;
204
+ // SIEMPRE mostrar el ID que se está usando (no solo en debug)
205
+ if (attempts === 0) {
206
+ console.log(chalk_1.default.yellow(`\n[POLLING] Using Token ID: ${chalk_1.default.cyan(currentTokenId)}`));
207
+ console.log(chalk_1.default.yellow(`[POLLING] URL: ${chalk_1.default.cyan(verifyUrl)}\n`));
208
+ }
209
+ if (options.debug) {
210
+ console.log(chalk_1.default.gray(`[DEBUG] Attempt ${attempts + 1}`));
211
+ console.log(chalk_1.default.gray(`[DEBUG] Token ID from POST response: ${currentTokenId}`));
212
+ console.log(chalk_1.default.gray(`[DEBUG] Code from POST response: ${code}`));
213
+ console.log(chalk_1.default.gray(`[DEBUG] Full verification URL: ${verifyUrl}`));
214
+ }
215
+ const verifyResponse = await fetch(verifyUrl, {
216
+ method: 'GET',
217
+ headers: {
218
+ 'Content-Type': 'application/json',
219
+ },
220
+ });
221
+ if (verifyResponse.ok) {
222
+ const verifyData = await verifyResponse.json();
223
+ if (options.debug) {
224
+ console.log(chalk_1.default.gray(`\n[DEBUG] Attempt ${attempts + 1} - Response: ${JSON.stringify(verifyData, null, 2)}`));
225
+ }
226
+ // Intentar extraer el token
227
+ const extracted = extractToken(verifyData);
228
+ if (extracted.token) {
229
+ verifiedToken = extracted.token;
230
+ tokenEmail = extracted.email;
231
+ break;
232
+ }
233
+ }
234
+ else {
235
+ // Si la respuesta no es OK, mostrar el status para debug
236
+ if (options.debug) {
237
+ const errorText = await verifyResponse.text();
238
+ console.log(chalk_1.default.yellow(`[DEBUG] HTTP Status: ${verifyResponse.status}, Response: ${errorText}`));
239
+ }
240
+ }
241
+ attempts++;
242
+ pollSpinner.text = `Waiting for token verification... (attempt ${attempts}/${MAX_POLL_ATTEMPTS})`;
243
+ }
244
+ catch (error) {
245
+ // Continuar intentando en caso de error de red
246
+ if (options.debug) {
247
+ console.log(chalk_1.default.yellow(`[DEBUG] Error: ${error.message}`));
248
+ }
249
+ attempts++;
250
+ pollSpinner.text = `Waiting for token verification... (attempt ${attempts}/${MAX_POLL_ATTEMPTS})`;
251
+ }
252
+ }
253
+ if (!verifiedToken) {
254
+ pollSpinner.fail('Token verification timeout');
255
+ console.error(chalk_1.default.red('\n❌ Authentication timeout. Please try again.'));
256
+ console.error(chalk_1.default.yellow('\n💡 Tip: Use --debug flag to see detailed response information'));
257
+ console.error(chalk_1.default.yellow(` Example: codecrypto auth --debug\n`));
258
+ process.exit(1);
259
+ }
260
+ pollSpinner.succeed('Token verified successfully');
261
+ // Paso 3: Guardar token en ~/.codecrypto
262
+ const homeDir = os.homedir();
263
+ const codecryptoDir = path.join(homeDir, '.codecrypto');
264
+ const tokenFile = path.join(codecryptoDir, 'token.json');
265
+ const saveSpinner = (0, ora_1.default)('Saving authentication token...').start();
266
+ try {
267
+ // Crear directorio si no existe
268
+ if (!fs.existsSync(codecryptoDir)) {
269
+ fs.mkdirSync(codecryptoDir, { recursive: true });
270
+ }
271
+ // Guardar token
272
+ const tokenContent = {
273
+ token: verifiedToken,
274
+ email: tokenEmail,
275
+ serverUrl: serverUrl,
276
+ createdAt: new Date().toISOString(),
277
+ };
278
+ fs.writeFileSync(tokenFile, JSON.stringify(tokenContent, null, 2), 'utf-8');
279
+ saveSpinner.succeed('Token saved successfully');
280
+ }
281
+ catch (error) {
282
+ saveSpinner.fail('Failed to save token');
283
+ console.error(chalk_1.default.red(`❌ Error: ${error.message}`));
284
+ process.exit(1);
285
+ }
286
+ console.log(chalk_1.default.green('\n✅ Authentication completed successfully!'));
287
+ console.log(chalk_1.default.gray(` Token saved to: ${chalk_1.default.cyan(tokenFile)}`));
288
+ if (tokenEmail) {
289
+ console.log(chalk_1.default.gray(` Email: ${chalk_1.default.cyan(tokenEmail)}`));
290
+ }
291
+ console.log('');
292
+ }
293
+ catch (error) {
294
+ console.error(chalk_1.default.red(`\n❌ Error: ${error.message}`));
295
+ process.exit(1);
296
+ }
297
+ });
298
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
4
4
  const commander_1 = require("commander");
5
5
  const deploy_1 = require("./commands/deploy");
6
6
  const deploy_sc_1 = require("./commands/deploy-sc");
7
+ const auth_1 = require("./commands/auth");
7
8
  const program = new commander_1.Command();
8
9
  program
9
10
  .name('codecrypto')
@@ -12,5 +13,6 @@ program
12
13
  // Registrar comandos
13
14
  program.addCommand(deploy_1.deployCommand);
14
15
  program.addCommand(deploy_sc_1.deployScCommand);
16
+ program.addCommand(auth_1.authCommand);
15
17
  program.parse(process.argv);
16
18
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAEA,yCAAoC;AACpC,8CAAkD;AAClD,oDAAuD;AAEvD,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,YAAY,CAAC;KAClB,WAAW,CAAC,oCAAoC,CAAC;KACjD,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,qBAAqB;AACrB,OAAO,CAAC,UAAU,CAAC,sBAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,2BAAe,CAAC,CAAC;AAEpC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAEA,yCAAoC;AACpC,8CAAkD;AAClD,oDAAuD;AACvD,0CAA8C;AAE9C,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,YAAY,CAAC;KAClB,WAAW,CAAC,oCAAoC,CAAC;KACjD,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,qBAAqB;AACrB,OAAO,CAAC,UAAU,CAAC,sBAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,2BAAe,CAAC,CAAC;AACpC,OAAO,CAAC,UAAU,CAAC,kBAAW,CAAC,CAAC;AAEhC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codecrypto-cli",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "CLI tool for CodeCrypto operations",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -20,16 +20,17 @@
20
20
  "author": "",
21
21
  "license": "MIT",
22
22
  "dependencies": {
23
- "commander": "^12.0.0",
24
23
  "chalk": "^4.1.2",
25
- "ora": "^5.4.1",
26
- "inquirer": "^8.2.5"
24
+ "commander": "^12.0.0",
25
+ "inquirer": "^8.2.5",
26
+ "jose": "^6.1.3",
27
+ "ora": "^5.4.1"
27
28
  },
28
29
  "devDependencies": {
29
- "@types/node": "^20.10.0",
30
30
  "@types/inquirer": "^9.0.7",
31
- "typescript": "^5.3.0",
32
- "tsx": "^4.7.0"
31
+ "@types/node": "^20.10.0",
32
+ "tsx": "^4.7.0",
33
+ "typescript": "^5.3.0"
33
34
  },
34
35
  "engines": {
35
36
  "node": ">=16.0.0"
@@ -0,0 +1,318 @@
1
+ import { Command } from 'commander';
2
+ import chalk from 'chalk';
3
+ import ora from 'ora';
4
+ import * as fs from 'fs';
5
+ import * as path from 'path';
6
+ import * as os from 'os';
7
+ import { decodeJwt } from 'jose';
8
+
9
+ interface TokenResponse {
10
+ success: boolean;
11
+ data: {
12
+ _id: string;
13
+ code: string;
14
+ createdAt: string;
15
+ };
16
+ }
17
+
18
+ interface TokenVerificationResponse {
19
+ success: boolean;
20
+ data?: {
21
+ token?: string;
22
+ email?: string;
23
+ [key: string]: any;
24
+ };
25
+ error?: string;
26
+ }
27
+
28
+ const API_BASE_URL = 'http://localhost:3000';
29
+ const POLL_INTERVAL = 3000; // 3 segundos
30
+ const MAX_POLL_ATTEMPTS = 100; // Máximo 5 minutos (100 * 3 segundos)
31
+
32
+ export const authCommand = new Command('auth')
33
+ .description('Authenticate with CodeCrypto platform')
34
+ .option('--server-url <url>', 'Server URL', API_BASE_URL)
35
+ .option('--poll-interval <seconds>', 'Polling interval in seconds', '3')
36
+ .option('--debug', 'Show debug information', false)
37
+ .action(async (options) => {
38
+ console.log(chalk.blue('\n🔐 CodeCrypto Authentication\n'));
39
+
40
+ const serverUrl = options.serverUrl || API_BASE_URL;
41
+ const pollInterval = parseInt(options.pollInterval || '3', 10) * 1000;
42
+
43
+ try {
44
+ // Paso 1: Solicitar código de autenticación
45
+ const requestSpinner = ora('Requesting authentication code...').start();
46
+
47
+ let tokenData: TokenResponse;
48
+ try {
49
+ const response = await fetch(`${serverUrl}/api/tokens`, {
50
+ method: 'POST',
51
+ headers: {
52
+ 'Content-Type': 'application/json',
53
+ },
54
+ });
55
+
56
+ if (!response.ok) {
57
+ throw new Error(`HTTP error! status: ${response.status}`);
58
+ }
59
+
60
+ const jsonData = await response.json();
61
+
62
+ if (options.debug) {
63
+ console.log(chalk.gray(`\n[DEBUG] POST Response: ${JSON.stringify(jsonData, null, 2)}`));
64
+ }
65
+
66
+ tokenData = jsonData as TokenResponse;
67
+
68
+ // Validar estructura de respuesta
69
+ if (!tokenData || typeof tokenData !== 'object') {
70
+ throw new Error('Invalid response format from server');
71
+ }
72
+
73
+ if (!tokenData.success) {
74
+ throw new Error(`Server returned error: ${(tokenData as any).error || 'Unknown error'}`);
75
+ }
76
+
77
+ if (!tokenData.data || typeof tokenData.data !== 'object') {
78
+ throw new Error('Response data is missing or invalid');
79
+ }
80
+
81
+ // Extraer y validar _id y code de la respuesta
82
+ const responseId = tokenData.data._id;
83
+ const responseCode = tokenData.data.code;
84
+
85
+ if (!responseId || typeof responseId !== 'string' || responseId.trim() === '') {
86
+ console.error(chalk.red(`❌ Error: Invalid or missing _id in response`));
87
+ if (options.debug) {
88
+ console.log(chalk.gray(`\n[DEBUG] Full response: ${JSON.stringify(tokenData, null, 2)}`));
89
+ }
90
+ throw new Error('Invalid token ID received from server');
91
+ }
92
+
93
+ if (!responseCode || typeof responseCode !== 'string' || responseCode.trim() === '') {
94
+ console.error(chalk.red(`❌ Error: Invalid or missing code in response`));
95
+ if (options.debug) {
96
+ console.log(chalk.gray(`\n[DEBUG] Full response: ${JSON.stringify(tokenData, null, 2)}`));
97
+ }
98
+ throw new Error('Invalid code received from server');
99
+ }
100
+
101
+ requestSpinner.succeed('Authentication code received');
102
+ } catch (error: any) {
103
+ requestSpinner.fail('Failed to request authentication code');
104
+ console.error(chalk.red(`❌ Error: ${error.message}`));
105
+ if (options.debug && error.stack) {
106
+ console.error(chalk.gray(`\n[DEBUG] Stack: ${error.stack}`));
107
+ }
108
+ process.exit(1);
109
+ }
110
+
111
+ // EXTRAER DIRECTAMENTE DE LA RESPUESTA - NUNCA HARDCODEADO
112
+ // Obtener el _id y code directamente de la respuesta del POST
113
+ const tokenId = String(tokenData.data._id).trim();
114
+ const code = String(tokenData.data.code).trim();
115
+
116
+ // Verificación final (no debería fallar si llegamos aquí, pero por seguridad)
117
+ if (!tokenId || tokenId === '' || !code || code === '') {
118
+ console.error(chalk.red(`❌ Error: Missing tokenId or code after extraction`));
119
+ console.error(chalk.red(` tokenId: "${tokenId}"`));
120
+ console.error(chalk.red(` code: "${code}"`));
121
+ console.error(chalk.red(` Full response data: ${JSON.stringify(tokenData.data, null, 2)}`));
122
+ process.exit(1);
123
+ }
124
+
125
+ const tokenUrl = `${serverUrl}/token`;
126
+
127
+ // Mostrar información al usuario con el ID REAL obtenido
128
+ console.log(chalk.green('\n✅ Authentication code generated!'));
129
+ console.log(chalk.white(`\n Code: ${chalk.cyan(code)}`));
130
+ console.log(chalk.white(` Token ID: ${chalk.gray(tokenId)}`));
131
+ console.log(chalk.white(`\n Please visit: ${chalk.cyan.underline(tokenUrl)}`));
132
+ console.log(chalk.gray(' Enter the code above to complete authentication.\n'));
133
+
134
+ // Log explícito del ID que se va a usar
135
+ console.log(chalk.gray(`[INFO] Will poll using token ID: ${chalk.yellow(tokenId)}\n`));
136
+
137
+ // Paso 2: Polling para verificar el token
138
+ const pollSpinner = ora('Waiting for token verification...').start();
139
+
140
+ let verifiedToken: string | null = null;
141
+ let tokenEmail: string | null = null;
142
+ let attempts = 0;
143
+
144
+ // Función helper para extraer el token JWT y el email de la respuesta
145
+ const extractToken = (data: any): { token: string | null; email: string | null } => {
146
+ if (!data) return { token: null, email: null };
147
+
148
+ let jwtToken: string | null = null;
149
+ let email: string | null = null;
150
+
151
+ // Estructura real: data.success && data.data.jwt (el JWT está en data.jwt)
152
+ if (data.success && data.data) {
153
+ // El JWT puede estar en data.jwt o data.token
154
+ jwtToken = data.data.jwt || data.data.token || null;
155
+ // El email está directamente en data.email
156
+ email = data.data.email || null;
157
+ }
158
+ // Estructura alternativa: data.jwt directamente
159
+ else if (data.jwt && typeof data.jwt === 'string') {
160
+ jwtToken = data.jwt;
161
+ email = data.email || null;
162
+ }
163
+ // Estructura alternativa: data.token
164
+ else if (data.token && typeof data.token === 'string') {
165
+ jwtToken = data.token;
166
+ email = data.email || null;
167
+ }
168
+
169
+ if (!jwtToken) {
170
+ return { token: null, email: null };
171
+ }
172
+
173
+ // Si no tenemos email de la respuesta, intentar extraerlo del JWT
174
+ if (!email) {
175
+ try {
176
+ const decoded = decodeJwt(jwtToken) as any;
177
+ // El email puede estar en diferentes campos del payload
178
+ email = decoded.email ||
179
+ decoded.sub ||
180
+ decoded.user?.email ||
181
+ null;
182
+
183
+ if (options.debug) {
184
+ console.log(chalk.gray(`[DEBUG] JWT decoded payload: ${JSON.stringify(decoded, null, 2)}`));
185
+ console.log(chalk.gray(`[DEBUG] Email extracted from JWT: ${email}`));
186
+ }
187
+ } catch (error: any) {
188
+ if (options.debug) {
189
+ console.log(chalk.yellow(`[DEBUG] Could not decode JWT: ${error.message}`));
190
+ }
191
+ }
192
+ } else {
193
+ if (options.debug) {
194
+ console.log(chalk.gray(`[DEBUG] Email from response data: ${email}`));
195
+ }
196
+ }
197
+
198
+ return { token: jwtToken, email };
199
+ };
200
+
201
+ while (!verifiedToken && attempts < MAX_POLL_ATTEMPTS) {
202
+ try {
203
+ // Esperar antes de cada intento excepto el primero
204
+ if (attempts > 0) {
205
+ await new Promise(resolve => setTimeout(resolve, pollInterval));
206
+ }
207
+
208
+ // CONSTRUIR URL CON EL TOKEN ID OBTENIDO DEL POST - NUNCA HARDCODEADO
209
+ // Asegurarse de que tokenId es el valor real de la respuesta
210
+ const currentTokenId = tokenId; // Variable local para asegurar que usamos el valor correcto
211
+ const verifyUrl = `${serverUrl}/api/tokens/${currentTokenId}`;
212
+
213
+ // SIEMPRE mostrar el ID que se está usando (no solo en debug)
214
+ if (attempts === 0) {
215
+ console.log(chalk.yellow(`\n[POLLING] Using Token ID: ${chalk.cyan(currentTokenId)}`));
216
+ console.log(chalk.yellow(`[POLLING] URL: ${chalk.cyan(verifyUrl)}\n`));
217
+ }
218
+
219
+ if (options.debug) {
220
+ console.log(chalk.gray(`[DEBUG] Attempt ${attempts + 1}`));
221
+ console.log(chalk.gray(`[DEBUG] Token ID from POST response: ${currentTokenId}`));
222
+ console.log(chalk.gray(`[DEBUG] Code from POST response: ${code}`));
223
+ console.log(chalk.gray(`[DEBUG] Full verification URL: ${verifyUrl}`));
224
+ }
225
+
226
+ const verifyResponse = await fetch(verifyUrl, {
227
+ method: 'GET',
228
+ headers: {
229
+ 'Content-Type': 'application/json',
230
+ },
231
+ });
232
+
233
+ if (verifyResponse.ok) {
234
+ const verifyData = await verifyResponse.json();
235
+
236
+ if (options.debug) {
237
+ console.log(chalk.gray(`\n[DEBUG] Attempt ${attempts + 1} - Response: ${JSON.stringify(verifyData, null, 2)}`));
238
+ }
239
+
240
+ // Intentar extraer el token
241
+ const extracted = extractToken(verifyData);
242
+ if (extracted.token) {
243
+ verifiedToken = extracted.token;
244
+ tokenEmail = extracted.email;
245
+ break;
246
+ }
247
+ } else {
248
+ // Si la respuesta no es OK, mostrar el status para debug
249
+ if (options.debug) {
250
+ const errorText = await verifyResponse.text();
251
+ console.log(chalk.yellow(`[DEBUG] HTTP Status: ${verifyResponse.status}, Response: ${errorText}`));
252
+ }
253
+ }
254
+
255
+ attempts++;
256
+ pollSpinner.text = `Waiting for token verification... (attempt ${attempts}/${MAX_POLL_ATTEMPTS})`;
257
+ } catch (error: any) {
258
+ // Continuar intentando en caso de error de red
259
+ if (options.debug) {
260
+ console.log(chalk.yellow(`[DEBUG] Error: ${error.message}`));
261
+ }
262
+ attempts++;
263
+ pollSpinner.text = `Waiting for token verification... (attempt ${attempts}/${MAX_POLL_ATTEMPTS})`;
264
+ }
265
+ }
266
+
267
+ if (!verifiedToken) {
268
+ pollSpinner.fail('Token verification timeout');
269
+ console.error(chalk.red('\n❌ Authentication timeout. Please try again.'));
270
+ console.error(chalk.yellow('\n💡 Tip: Use --debug flag to see detailed response information'));
271
+ console.error(chalk.yellow(` Example: codecrypto auth --debug\n`));
272
+ process.exit(1);
273
+ }
274
+
275
+ pollSpinner.succeed('Token verified successfully');
276
+
277
+ // Paso 3: Guardar token en ~/.codecrypto
278
+ const homeDir = os.homedir();
279
+ const codecryptoDir = path.join(homeDir, '.codecrypto');
280
+ const tokenFile = path.join(codecryptoDir, 'token.json');
281
+
282
+ const saveSpinner = ora('Saving authentication token...').start();
283
+
284
+ try {
285
+ // Crear directorio si no existe
286
+ if (!fs.existsSync(codecryptoDir)) {
287
+ fs.mkdirSync(codecryptoDir, { recursive: true });
288
+ }
289
+
290
+ // Guardar token
291
+ const tokenContent = {
292
+ token: verifiedToken,
293
+ email: tokenEmail,
294
+ serverUrl: serverUrl,
295
+ createdAt: new Date().toISOString(),
296
+ };
297
+
298
+ fs.writeFileSync(tokenFile, JSON.stringify(tokenContent, null, 2), 'utf-8');
299
+ saveSpinner.succeed('Token saved successfully');
300
+ } catch (error: any) {
301
+ saveSpinner.fail('Failed to save token');
302
+ console.error(chalk.red(`❌ Error: ${error.message}`));
303
+ process.exit(1);
304
+ }
305
+
306
+ console.log(chalk.green('\n✅ Authentication completed successfully!'));
307
+ console.log(chalk.gray(` Token saved to: ${chalk.cyan(tokenFile)}`));
308
+ if (tokenEmail) {
309
+ console.log(chalk.gray(` Email: ${chalk.cyan(tokenEmail)}`));
310
+ }
311
+ console.log('');
312
+
313
+ } catch (error: any) {
314
+ console.error(chalk.red(`\n❌ Error: ${error.message}`));
315
+ process.exit(1);
316
+ }
317
+ });
318
+
package/src/index.ts CHANGED
@@ -3,6 +3,7 @@
3
3
  import { Command } from 'commander';
4
4
  import { deployCommand } from './commands/deploy';
5
5
  import { deployScCommand } from './commands/deploy-sc';
6
+ import { authCommand } from './commands/auth';
6
7
 
7
8
  const program = new Command();
8
9
 
@@ -14,5 +15,6 @@ program
14
15
  // Registrar comandos
15
16
  program.addCommand(deployCommand);
16
17
  program.addCommand(deployScCommand);
18
+ program.addCommand(authCommand);
17
19
 
18
20
  program.parse(process.argv);