@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 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 = (token) => {
59
- fs.writeFileSync(TOKEN_FILE, JSON.stringify({ access_token: token }, null, 2), {
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.access_token || null;
72
+ return json !== null && json !== void 0 ? json : {
73
+ accessToken: null,
74
+ refreshToken: null,
75
+ };
69
76
  }
70
- return null;
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.9").description("Hapico CLI for project management");
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 token = getStoredToken();
297
- if (!token) {
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 token = getStoredToken();
353
- if (!token) {
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 token = getStoredToken();
398
- if (!token) {
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 ${token}`,
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
- const token = getStoredToken();
440
- if (token) {
441
- console.log("You are already logged in.");
442
- return;
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 token = getStoredToken();
459
- if (!token) {
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 = (token) => {
59
- fs.writeFileSync(TOKEN_FILE, JSON.stringify({ access_token: token }, null, 2), {
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.access_token || null;
72
+ return json !== null && json !== void 0 ? json : {
73
+ accessToken: null,
74
+ refreshToken: null,
75
+ };
69
76
  }
70
- return null;
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.9").description("Hapico CLI for project management");
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 token = getStoredToken();
297
- if (!token) {
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 token = getStoredToken();
353
- if (!token) {
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 token = getStoredToken();
398
- if (!token) {
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 ${token}`,
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
- const token = getStoredToken();
440
- if (token) {
441
- console.log("You are already logged in.");
442
- return;
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 token = getStoredToken();
459
- if (!token) {
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 = (token: string) => {
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({ access_token: token }, null, 2),
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 = (): string | null => {
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.access_token || null;
48
+ return json ?? {
49
+ accessToken: null,
50
+ refreshToken: null,
51
+ };
43
52
  }
44
- return null;
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(fullPath.replace(this.basePath + path.sep, "./")),
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.9").description("Hapico CLI for project management");
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 token = getStoredToken();
341
- if (!token) {
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 token = getStoredToken();
415
- if (!token) {
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 token = getStoredToken();
476
- if (!token) {
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 ${token}`,
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
- const token = getStoredToken();
527
- if (token) {
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
- readline.question("Please enter your token: ", (inputToken: string) => {
537
- saveToken(inputToken);
538
- console.log("Login successful!");
539
- readline.close();
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 token = getStoredToken();
548
- if (!token) {
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")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hapico/cli",
3
- "version": "0.0.9",
3
+ "version": "0.0.11",
4
4
  "description": "A simple CLI tool for project management",
5
5
  "main": "index.js",
6
6
  "bin": {