@hapico/cli 0.0.9 → 0.0.11
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/bin/index.js +62 -28
- package/dist/index.js +62 -28
- package/index.ts +78 -32
- package/package.json +1 -1
package/bin/index.js
CHANGED
|
@@ -47,6 +47,7 @@ const ora_1 = __importDefault(require("ora"));
|
|
|
47
47
|
const ws_1 = require("ws");
|
|
48
48
|
const Babel = __importStar(require("@babel/standalone"));
|
|
49
49
|
const qrcode_terminal_1 = __importDefault(require("qrcode-terminal"));
|
|
50
|
+
const open_1 = __importDefault(require("open"));
|
|
50
51
|
// Directory to store the token and project config
|
|
51
52
|
const CONFIG_DIR = path.join(process.env.HOME || process.env.USERPROFILE || ".", ".hapico");
|
|
52
53
|
const TOKEN_FILE = path.join(CONFIG_DIR, "auth_token.json");
|
|
@@ -55,8 +56,11 @@ if (!fs.existsSync(CONFIG_DIR)) {
|
|
|
55
56
|
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
56
57
|
}
|
|
57
58
|
// Function to save token
|
|
58
|
-
const saveToken = (
|
|
59
|
-
|
|
59
|
+
const saveToken = (tokens) => {
|
|
60
|
+
if (!tokens || !tokens.accessToken) {
|
|
61
|
+
throw new Error("Invalid token data");
|
|
62
|
+
}
|
|
63
|
+
fs.writeFileSync(TOKEN_FILE, JSON.stringify(tokens, null, 2), {
|
|
60
64
|
encoding: "utf8",
|
|
61
65
|
});
|
|
62
66
|
};
|
|
@@ -65,9 +69,15 @@ const getStoredToken = () => {
|
|
|
65
69
|
if (fs.existsSync(TOKEN_FILE)) {
|
|
66
70
|
const data = fs.readFileSync(TOKEN_FILE, { encoding: "utf8" });
|
|
67
71
|
const json = JSON.parse(data);
|
|
68
|
-
return json
|
|
72
|
+
return json !== null && json !== void 0 ? json : {
|
|
73
|
+
accessToken: null,
|
|
74
|
+
refreshToken: null,
|
|
75
|
+
};
|
|
69
76
|
}
|
|
70
|
-
return
|
|
77
|
+
return {
|
|
78
|
+
accessToken: null,
|
|
79
|
+
refreshToken: null,
|
|
80
|
+
};
|
|
71
81
|
};
|
|
72
82
|
// Function to save project ID
|
|
73
83
|
const saveProjectId = (projectDir, id) => {
|
|
@@ -288,13 +298,13 @@ class RoomState {
|
|
|
288
298
|
return this.isConnected;
|
|
289
299
|
}
|
|
290
300
|
}
|
|
291
|
-
commander_1.program.version("0.0.
|
|
301
|
+
commander_1.program.version("0.0.10").description("Hapico CLI for project management");
|
|
292
302
|
commander_1.program
|
|
293
303
|
.command("clone <id>")
|
|
294
304
|
.description("Clone a project by ID")
|
|
295
305
|
.action(async (id) => {
|
|
296
|
-
const
|
|
297
|
-
if (!
|
|
306
|
+
const { accessToken } = getStoredToken();
|
|
307
|
+
if (!accessToken) {
|
|
298
308
|
console.error("You need to login first. Use 'hapico login' command.");
|
|
299
309
|
return;
|
|
300
310
|
}
|
|
@@ -349,8 +359,8 @@ commander_1.program
|
|
|
349
359
|
.command("dev")
|
|
350
360
|
.description("Start the project in development mode")
|
|
351
361
|
.action(() => {
|
|
352
|
-
const
|
|
353
|
-
if (!
|
|
362
|
+
const { accessToken } = getStoredToken();
|
|
363
|
+
if (!accessToken) {
|
|
354
364
|
console.error("You need to login first. Use 'hapico login' command.");
|
|
355
365
|
return;
|
|
356
366
|
}
|
|
@@ -394,8 +404,9 @@ commander_1.program
|
|
|
394
404
|
.command("push")
|
|
395
405
|
.description("Push the project source code to the server")
|
|
396
406
|
.action(() => {
|
|
397
|
-
const
|
|
398
|
-
|
|
407
|
+
const data = getStoredToken();
|
|
408
|
+
const { accessToken } = data || {};
|
|
409
|
+
if (!accessToken) {
|
|
399
410
|
console.error("You need to login first. Use 'hapico login' command.");
|
|
400
411
|
return;
|
|
401
412
|
}
|
|
@@ -421,7 +432,7 @@ commander_1.program
|
|
|
421
432
|
}),
|
|
422
433
|
}, {
|
|
423
434
|
headers: {
|
|
424
|
-
Authorization: `Bearer ${
|
|
435
|
+
Authorization: `Bearer ${accessToken}`,
|
|
425
436
|
"Content-Type": "application/json",
|
|
426
437
|
},
|
|
427
438
|
})
|
|
@@ -435,28 +446,51 @@ commander_1.program
|
|
|
435
446
|
commander_1.program
|
|
436
447
|
.command("login")
|
|
437
448
|
.description("Login to the system")
|
|
438
|
-
.action(() => {
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
449
|
+
.action(async () => {
|
|
450
|
+
console.log("Logging in to the system...");
|
|
451
|
+
const loginSpinner = (0, ora_1.default)("Initiating login...").start();
|
|
452
|
+
try {
|
|
453
|
+
const response = await axios_1.default.post("https://auth.myworkbeast.com/auth/device");
|
|
454
|
+
const { device_code, user_code, verification_url, expires_in, interval } = response.data;
|
|
455
|
+
loginSpinner.succeed("Login initiated!");
|
|
456
|
+
console.log(`Please open this URL in your browser: ${verification_url}`);
|
|
457
|
+
console.log(`And enter this code: ${user_code}`);
|
|
458
|
+
console.log("Waiting for authentication...");
|
|
459
|
+
await (0, open_1.default)(verification_url);
|
|
460
|
+
const pollSpinner = (0, ora_1.default)("Waiting for authentication...").start();
|
|
461
|
+
let tokens = null;
|
|
462
|
+
const startTime = Date.now();
|
|
463
|
+
while (Date.now() - startTime < expires_in * 1000) {
|
|
464
|
+
try {
|
|
465
|
+
const pollResponse = await axios_1.default.post("https://auth.myworkbeast.com/auth/device/poll", { device_code });
|
|
466
|
+
if (pollResponse.data.accessToken) {
|
|
467
|
+
tokens = pollResponse.data;
|
|
468
|
+
break;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
catch (error) {
|
|
472
|
+
// Ignore temporary errors and continue polling
|
|
473
|
+
}
|
|
474
|
+
await new Promise((resolve) => setTimeout(resolve, interval * 1000));
|
|
475
|
+
}
|
|
476
|
+
if (tokens) {
|
|
477
|
+
pollSpinner.succeed("Login successful!");
|
|
478
|
+
saveToken(tokens);
|
|
479
|
+
}
|
|
480
|
+
else {
|
|
481
|
+
pollSpinner.fail("Login failed: Timeout or user did not complete authentication.");
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
catch (error) {
|
|
485
|
+
loginSpinner.fail(`Login error: ${error.message}`);
|
|
443
486
|
}
|
|
444
|
-
const readline = require("readline").createInterface({
|
|
445
|
-
input: process.stdin,
|
|
446
|
-
output: process.stdout,
|
|
447
|
-
});
|
|
448
|
-
readline.question("Please enter your token: ", (inputToken) => {
|
|
449
|
-
saveToken(inputToken);
|
|
450
|
-
console.log("Login successful!");
|
|
451
|
-
readline.close();
|
|
452
|
-
});
|
|
453
487
|
});
|
|
454
488
|
commander_1.program
|
|
455
489
|
.command("logout")
|
|
456
490
|
.description("Logout from the system")
|
|
457
491
|
.action(() => {
|
|
458
|
-
const
|
|
459
|
-
if (!
|
|
492
|
+
const accessToken = getStoredToken();
|
|
493
|
+
if (!accessToken) {
|
|
460
494
|
console.log("You are not logged in.");
|
|
461
495
|
return;
|
|
462
496
|
}
|
package/dist/index.js
CHANGED
|
@@ -47,6 +47,7 @@ const ora_1 = __importDefault(require("ora"));
|
|
|
47
47
|
const ws_1 = require("ws");
|
|
48
48
|
const Babel = __importStar(require("@babel/standalone"));
|
|
49
49
|
const qrcode_terminal_1 = __importDefault(require("qrcode-terminal"));
|
|
50
|
+
const open_1 = __importDefault(require("open"));
|
|
50
51
|
// Directory to store the token and project config
|
|
51
52
|
const CONFIG_DIR = path.join(process.env.HOME || process.env.USERPROFILE || ".", ".hapico");
|
|
52
53
|
const TOKEN_FILE = path.join(CONFIG_DIR, "auth_token.json");
|
|
@@ -55,8 +56,11 @@ if (!fs.existsSync(CONFIG_DIR)) {
|
|
|
55
56
|
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
56
57
|
}
|
|
57
58
|
// Function to save token
|
|
58
|
-
const saveToken = (
|
|
59
|
-
|
|
59
|
+
const saveToken = (tokens) => {
|
|
60
|
+
if (!tokens || !tokens.accessToken) {
|
|
61
|
+
throw new Error("Invalid token data");
|
|
62
|
+
}
|
|
63
|
+
fs.writeFileSync(TOKEN_FILE, JSON.stringify(tokens, null, 2), {
|
|
60
64
|
encoding: "utf8",
|
|
61
65
|
});
|
|
62
66
|
};
|
|
@@ -65,9 +69,15 @@ const getStoredToken = () => {
|
|
|
65
69
|
if (fs.existsSync(TOKEN_FILE)) {
|
|
66
70
|
const data = fs.readFileSync(TOKEN_FILE, { encoding: "utf8" });
|
|
67
71
|
const json = JSON.parse(data);
|
|
68
|
-
return json
|
|
72
|
+
return json !== null && json !== void 0 ? json : {
|
|
73
|
+
accessToken: null,
|
|
74
|
+
refreshToken: null,
|
|
75
|
+
};
|
|
69
76
|
}
|
|
70
|
-
return
|
|
77
|
+
return {
|
|
78
|
+
accessToken: null,
|
|
79
|
+
refreshToken: null,
|
|
80
|
+
};
|
|
71
81
|
};
|
|
72
82
|
// Function to save project ID
|
|
73
83
|
const saveProjectId = (projectDir, id) => {
|
|
@@ -288,13 +298,13 @@ class RoomState {
|
|
|
288
298
|
return this.isConnected;
|
|
289
299
|
}
|
|
290
300
|
}
|
|
291
|
-
commander_1.program.version("0.0.
|
|
301
|
+
commander_1.program.version("0.0.10").description("Hapico CLI for project management");
|
|
292
302
|
commander_1.program
|
|
293
303
|
.command("clone <id>")
|
|
294
304
|
.description("Clone a project by ID")
|
|
295
305
|
.action(async (id) => {
|
|
296
|
-
const
|
|
297
|
-
if (!
|
|
306
|
+
const { accessToken } = getStoredToken();
|
|
307
|
+
if (!accessToken) {
|
|
298
308
|
console.error("You need to login first. Use 'hapico login' command.");
|
|
299
309
|
return;
|
|
300
310
|
}
|
|
@@ -349,8 +359,8 @@ commander_1.program
|
|
|
349
359
|
.command("dev")
|
|
350
360
|
.description("Start the project in development mode")
|
|
351
361
|
.action(() => {
|
|
352
|
-
const
|
|
353
|
-
if (!
|
|
362
|
+
const { accessToken } = getStoredToken();
|
|
363
|
+
if (!accessToken) {
|
|
354
364
|
console.error("You need to login first. Use 'hapico login' command.");
|
|
355
365
|
return;
|
|
356
366
|
}
|
|
@@ -394,8 +404,9 @@ commander_1.program
|
|
|
394
404
|
.command("push")
|
|
395
405
|
.description("Push the project source code to the server")
|
|
396
406
|
.action(() => {
|
|
397
|
-
const
|
|
398
|
-
|
|
407
|
+
const data = getStoredToken();
|
|
408
|
+
const { accessToken } = data || {};
|
|
409
|
+
if (!accessToken) {
|
|
399
410
|
console.error("You need to login first. Use 'hapico login' command.");
|
|
400
411
|
return;
|
|
401
412
|
}
|
|
@@ -421,7 +432,7 @@ commander_1.program
|
|
|
421
432
|
}),
|
|
422
433
|
}, {
|
|
423
434
|
headers: {
|
|
424
|
-
Authorization: `Bearer ${
|
|
435
|
+
Authorization: `Bearer ${accessToken}`,
|
|
425
436
|
"Content-Type": "application/json",
|
|
426
437
|
},
|
|
427
438
|
})
|
|
@@ -435,28 +446,51 @@ commander_1.program
|
|
|
435
446
|
commander_1.program
|
|
436
447
|
.command("login")
|
|
437
448
|
.description("Login to the system")
|
|
438
|
-
.action(() => {
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
449
|
+
.action(async () => {
|
|
450
|
+
console.log("Logging in to the system...");
|
|
451
|
+
const loginSpinner = (0, ora_1.default)("Initiating login...").start();
|
|
452
|
+
try {
|
|
453
|
+
const response = await axios_1.default.post("https://auth.myworkbeast.com/auth/device");
|
|
454
|
+
const { device_code, user_code, verification_url, expires_in, interval } = response.data;
|
|
455
|
+
loginSpinner.succeed("Login initiated!");
|
|
456
|
+
console.log(`Please open this URL in your browser: ${verification_url}`);
|
|
457
|
+
console.log(`And enter this code: ${user_code}`);
|
|
458
|
+
console.log("Waiting for authentication...");
|
|
459
|
+
await (0, open_1.default)(verification_url);
|
|
460
|
+
const pollSpinner = (0, ora_1.default)("Waiting for authentication...").start();
|
|
461
|
+
let tokens = null;
|
|
462
|
+
const startTime = Date.now();
|
|
463
|
+
while (Date.now() - startTime < expires_in * 1000) {
|
|
464
|
+
try {
|
|
465
|
+
const pollResponse = await axios_1.default.post("https://auth.myworkbeast.com/auth/device/poll", { device_code });
|
|
466
|
+
if (pollResponse.data.accessToken) {
|
|
467
|
+
tokens = pollResponse.data;
|
|
468
|
+
break;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
catch (error) {
|
|
472
|
+
// Ignore temporary errors and continue polling
|
|
473
|
+
}
|
|
474
|
+
await new Promise((resolve) => setTimeout(resolve, interval * 1000));
|
|
475
|
+
}
|
|
476
|
+
if (tokens) {
|
|
477
|
+
pollSpinner.succeed("Login successful!");
|
|
478
|
+
saveToken(tokens);
|
|
479
|
+
}
|
|
480
|
+
else {
|
|
481
|
+
pollSpinner.fail("Login failed: Timeout or user did not complete authentication.");
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
catch (error) {
|
|
485
|
+
loginSpinner.fail(`Login error: ${error.message}`);
|
|
443
486
|
}
|
|
444
|
-
const readline = require("readline").createInterface({
|
|
445
|
-
input: process.stdin,
|
|
446
|
-
output: process.stdout,
|
|
447
|
-
});
|
|
448
|
-
readline.question("Please enter your token: ", (inputToken) => {
|
|
449
|
-
saveToken(inputToken);
|
|
450
|
-
console.log("Login successful!");
|
|
451
|
-
readline.close();
|
|
452
|
-
});
|
|
453
487
|
});
|
|
454
488
|
commander_1.program
|
|
455
489
|
.command("logout")
|
|
456
490
|
.description("Logout from the system")
|
|
457
491
|
.action(() => {
|
|
458
|
-
const
|
|
459
|
-
if (!
|
|
492
|
+
const accessToken = getStoredToken();
|
|
493
|
+
if (!accessToken) {
|
|
460
494
|
console.log("You are not logged in.");
|
|
461
495
|
return;
|
|
462
496
|
}
|
package/index.ts
CHANGED
|
@@ -24,10 +24,13 @@ if (!fs.existsSync(CONFIG_DIR)) {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
// Function to save token
|
|
27
|
-
const saveToken = (
|
|
27
|
+
const saveToken = (tokens: { accessToken: string; refreshToken?: string }) => {
|
|
28
|
+
if (!tokens || !tokens.accessToken) {
|
|
29
|
+
throw new Error("Invalid token data");
|
|
30
|
+
}
|
|
28
31
|
fs.writeFileSync(
|
|
29
32
|
TOKEN_FILE,
|
|
30
|
-
JSON.stringify(
|
|
33
|
+
JSON.stringify(tokens, null, 2),
|
|
31
34
|
{
|
|
32
35
|
encoding: "utf8",
|
|
33
36
|
}
|
|
@@ -35,13 +38,22 @@ const saveToken = (token: string) => {
|
|
|
35
38
|
};
|
|
36
39
|
|
|
37
40
|
// Function to get stored token
|
|
38
|
-
const getStoredToken = ():
|
|
41
|
+
const getStoredToken = (): {
|
|
42
|
+
accessToken: string | null;
|
|
43
|
+
refreshToken: string | null;
|
|
44
|
+
} => {
|
|
39
45
|
if (fs.existsSync(TOKEN_FILE)) {
|
|
40
46
|
const data = fs.readFileSync(TOKEN_FILE, { encoding: "utf8" });
|
|
41
47
|
const json = JSON.parse(data);
|
|
42
|
-
return json
|
|
48
|
+
return json ?? {
|
|
49
|
+
accessToken: null,
|
|
50
|
+
refreshToken: null,
|
|
51
|
+
};
|
|
43
52
|
}
|
|
44
|
-
return
|
|
53
|
+
return {
|
|
54
|
+
accessToken: null,
|
|
55
|
+
refreshToken: null,
|
|
56
|
+
};
|
|
45
57
|
};
|
|
46
58
|
|
|
47
59
|
// Function to save project ID
|
|
@@ -146,7 +158,9 @@ class FileManager {
|
|
|
146
158
|
} else if (entry.isFile()) {
|
|
147
159
|
const content = fs.readFileSync(fullPath, { encoding: "utf8" });
|
|
148
160
|
files.push({
|
|
149
|
-
path: this.replaceSplashWithSeparator(
|
|
161
|
+
path: this.replaceSplashWithSeparator(
|
|
162
|
+
fullPath.replace(this.basePath + path.sep, "./")
|
|
163
|
+
),
|
|
150
164
|
content,
|
|
151
165
|
es5: compileES5(content, fullPath) ?? "",
|
|
152
166
|
});
|
|
@@ -331,14 +345,14 @@ class RoomState {
|
|
|
331
345
|
}
|
|
332
346
|
}
|
|
333
347
|
|
|
334
|
-
program.version("0.0.
|
|
348
|
+
program.version("0.0.10").description("Hapico CLI for project management");
|
|
335
349
|
|
|
336
350
|
program
|
|
337
351
|
.command("clone <id>")
|
|
338
352
|
.description("Clone a project by ID")
|
|
339
353
|
.action(async (id: string) => {
|
|
340
|
-
const
|
|
341
|
-
if (!
|
|
354
|
+
const { accessToken } = getStoredToken();
|
|
355
|
+
if (!accessToken) {
|
|
342
356
|
console.error("You need to login first. Use 'hapico login' command.");
|
|
343
357
|
return;
|
|
344
358
|
}
|
|
@@ -411,8 +425,8 @@ program
|
|
|
411
425
|
.command("dev")
|
|
412
426
|
.description("Start the project in development mode")
|
|
413
427
|
.action(() => {
|
|
414
|
-
const
|
|
415
|
-
if (!
|
|
428
|
+
const { accessToken } = getStoredToken();
|
|
429
|
+
if (!accessToken) {
|
|
416
430
|
console.error("You need to login first. Use 'hapico login' command.");
|
|
417
431
|
return;
|
|
418
432
|
}
|
|
@@ -472,8 +486,9 @@ program
|
|
|
472
486
|
.command("push")
|
|
473
487
|
.description("Push the project source code to the server")
|
|
474
488
|
.action(() => {
|
|
475
|
-
const
|
|
476
|
-
|
|
489
|
+
const data = getStoredToken();
|
|
490
|
+
const { accessToken } = data || {};
|
|
491
|
+
if (!accessToken) {
|
|
477
492
|
console.error("You need to login first. Use 'hapico login' command.");
|
|
478
493
|
return;
|
|
479
494
|
}
|
|
@@ -506,7 +521,7 @@ program
|
|
|
506
521
|
},
|
|
507
522
|
{
|
|
508
523
|
headers: {
|
|
509
|
-
Authorization: `Bearer ${
|
|
524
|
+
Authorization: `Bearer ${accessToken}`,
|
|
510
525
|
"Content-Type": "application/json",
|
|
511
526
|
},
|
|
512
527
|
}
|
|
@@ -522,37 +537,68 @@ program
|
|
|
522
537
|
program
|
|
523
538
|
.command("login")
|
|
524
539
|
.description("Login to the system")
|
|
525
|
-
.action(() => {
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
console.log("You are already logged in.");
|
|
529
|
-
return;
|
|
530
|
-
}
|
|
531
|
-
const readline = require("readline").createInterface({
|
|
532
|
-
input: process.stdin,
|
|
533
|
-
output: process.stdout,
|
|
534
|
-
});
|
|
540
|
+
.action(async () => {
|
|
541
|
+
console.log("Logging in to the system...");
|
|
542
|
+
const loginSpinner: Ora = ora("Initiating login...").start();
|
|
535
543
|
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
544
|
+
try {
|
|
545
|
+
const response = await axios.post(
|
|
546
|
+
"https://auth.myworkbeast.com/auth/device"
|
|
547
|
+
);
|
|
548
|
+
const { device_code, user_code, verification_url, expires_in, interval } =
|
|
549
|
+
response.data;
|
|
550
|
+
|
|
551
|
+
loginSpinner.succeed("Login initiated!");
|
|
552
|
+
console.log(`Please open this URL in your browser: ${verification_url}`);
|
|
553
|
+
console.log(`And enter this code: ${user_code}`);
|
|
554
|
+
console.log("Waiting for authentication...");
|
|
555
|
+
|
|
556
|
+
await open(verification_url);
|
|
557
|
+
|
|
558
|
+
const pollSpinner: Ora = ora("Waiting for authentication...").start();
|
|
559
|
+
let tokens = null;
|
|
560
|
+
const startTime = Date.now();
|
|
561
|
+
while (Date.now() - startTime < expires_in * 1000) {
|
|
562
|
+
try {
|
|
563
|
+
const pollResponse = await axios.post(
|
|
564
|
+
"https://auth.myworkbeast.com/auth/device/poll",
|
|
565
|
+
{ device_code }
|
|
566
|
+
);
|
|
567
|
+
if (pollResponse.data.accessToken) {
|
|
568
|
+
tokens = pollResponse.data;
|
|
569
|
+
break;
|
|
570
|
+
}
|
|
571
|
+
} catch (error) {
|
|
572
|
+
// Ignore temporary errors and continue polling
|
|
573
|
+
}
|
|
574
|
+
await new Promise((resolve) => setTimeout(resolve, interval * 1000));
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
if (tokens) {
|
|
578
|
+
pollSpinner.succeed("Login successful!");
|
|
579
|
+
saveToken(tokens);
|
|
580
|
+
} else {
|
|
581
|
+
pollSpinner.fail(
|
|
582
|
+
"Login failed: Timeout or user did not complete authentication."
|
|
583
|
+
);
|
|
584
|
+
}
|
|
585
|
+
} catch (error) {
|
|
586
|
+
loginSpinner.fail(`Login error: ${(error as Error).message}`);
|
|
587
|
+
}
|
|
541
588
|
});
|
|
542
589
|
|
|
543
590
|
program
|
|
544
591
|
.command("logout")
|
|
545
592
|
.description("Logout from the system")
|
|
546
593
|
.action(() => {
|
|
547
|
-
const
|
|
548
|
-
if (!
|
|
594
|
+
const accessToken = getStoredToken();
|
|
595
|
+
if (!accessToken) {
|
|
549
596
|
console.log("You are not logged in.");
|
|
550
597
|
return;
|
|
551
598
|
}
|
|
552
599
|
fs.unlinkSync(TOKEN_FILE);
|
|
553
600
|
console.log("Logout successful!");
|
|
554
601
|
});
|
|
555
|
-
|
|
556
602
|
// Pull command to fetch the latest project files from the server
|
|
557
603
|
program
|
|
558
604
|
.command("pull")
|