qubitlink_cli 1.0.0-dev.1 → 1.0.0-dev.3

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/index.js CHANGED
@@ -5,11 +5,30 @@ import inquirer from 'inquirer';
5
5
  import { AuthService } from './services/auth.js';
6
6
  import { LinkService } from './services/link.js';
7
7
  import { OrgService } from './services/org.js';
8
+ import boxen from 'boxen';
9
+ import ora from 'ora';
10
+ import Table from 'cli-table3';
8
11
  const program = new Command();
12
+ const displayHeader = () => {
13
+ const banner = chalk.bold.magenta(`
14
+ ____ _ _ _ _ _ _
15
+ / __ \\ _ _| |__ (_) |_| | (_)_ __ | | __
16
+ | | | || | | | '_ \\ | | __| | | | '_ \\| |/ /
17
+ | |_| || |_| | |_) || | |_| |___| | | | | <
18
+ \\___\\_\\\\ \\__,_|_.__/ |_|\\__|_____|_|_| |_|_|\\_\\
19
+ `);
20
+ console.log(banner);
21
+ console.log(chalk.dim(' Manage your short links from the terminal\n'));
22
+ };
9
23
  program
10
24
  .name('qubit')
11
25
  .description('QubitLink CLI - Manage your short links from the terminal')
12
- .version('1.0.0');
26
+ .version('1.0.0-dev.1');
27
+ program.hook('preAction', (thisCommand, actionCommand) => {
28
+ if (actionCommand.name() !== 'logout') {
29
+ displayHeader();
30
+ }
31
+ });
13
32
  // --- Auth Commands ---
14
33
  program
15
34
  .command('login')
@@ -17,9 +36,8 @@ program
17
36
  .action(async () => {
18
37
  try {
19
38
  await AuthService.loginFlow();
20
- console.log(chalk.green('\nLogin successful!'));
21
39
  const user = AuthService.getUser();
22
- console.log(`Welcome back, ${chalk.bold(user.fullname)}.`);
40
+ console.log(`\nWelcome back, ${chalk.bold.magenta(user.fullname)}! ✨`);
23
41
  process.exit(0);
24
42
  }
25
43
  catch (error) {
@@ -42,8 +60,19 @@ program
42
60
  return;
43
61
  }
44
62
  const activeOrg = AuthService.getActiveOrgId();
45
- console.log(chalk.cyan('Logged in as:'), chalk.bold(user.email));
46
- console.log(chalk.cyan('Active Scope:'), activeOrg ? chalk.green(`Organization (${activeOrg})`) : chalk.yellow('Personal'));
63
+ const content = [
64
+ `${chalk.cyan('User :')} ${chalk.bold(user.fullname)}`,
65
+ `${chalk.cyan('Email :')} ${user.email}`,
66
+ `${chalk.cyan('Scope :')} ${activeOrg ? chalk.green(`Organization (${activeOrg})`) : chalk.yellow('Personal')}`
67
+ ].join('\n');
68
+ console.log(boxen(content, {
69
+ padding: 1,
70
+ margin: { top: 1, bottom: 1 },
71
+ borderStyle: 'round',
72
+ borderColor: 'magenta',
73
+ title: 'Active Session',
74
+ titleAlignment: 'center'
75
+ }));
47
76
  });
48
77
  // --- Link Commands ---
49
78
  const link = program.command('link').description('Manage short links');
@@ -56,34 +85,57 @@ link
56
85
  .option('--sensitive', 'Mark as sensitive content')
57
86
  .option('--org <orgId>', 'Create in specific organization')
58
87
  .action(async (url, options) => {
88
+ const spinner = ora('Creating link...').start();
59
89
  try {
60
- console.log(chalk.blue('Creating link...'));
61
90
  const result = await LinkService.create(url, options);
62
- console.log(chalk.green('\nLink created successfully!'));
63
- console.log(chalk.bold('Short URL:'), result.data.shortUrl);
91
+ spinner.succeed(chalk.green('Link created successfully!'));
92
+ const content = [
93
+ `${chalk.cyan('Short URL :')} ${chalk.bold.magenta(result.data.shortUrl)}`,
94
+ `${chalk.cyan('Original :')} ${url}`,
95
+ `${chalk.cyan('Short Code:')} ${result.data.urlKey}`
96
+ ].join('\n');
97
+ console.log(boxen(content, {
98
+ padding: 1,
99
+ borderStyle: 'round',
100
+ borderColor: 'cyan',
101
+ title: 'Link Details',
102
+ titleAlignment: 'center'
103
+ }));
64
104
  }
65
105
  catch (error) {
66
- console.error(chalk.red('Failed to create link:'), error.response?.data?.message || error.message);
106
+ spinner.fail(chalk.red('Failed to create link: ') + (error.response?.data?.message || error.message));
67
107
  }
68
108
  });
69
109
  link
70
110
  .command('list')
71
111
  .description('List your links')
72
112
  .action(async () => {
113
+ const spinner = ora('Fetching links...').start();
73
114
  try {
74
115
  const result = await LinkService.list();
75
116
  const links = result.data || [];
76
- console.log(chalk.cyan('\n--- Your Links ---'));
117
+ spinner.stop();
77
118
  if (links.length === 0) {
78
- console.log('No links found.');
119
+ console.log(chalk.yellow('\nNo links found in this scope.'));
79
120
  return;
80
121
  }
122
+ const table = new Table({
123
+ head: [chalk.magenta('Code'), chalk.magenta('Original URL'), chalk.magenta('Clicks')],
124
+ colWidths: [12, 40, 10],
125
+ wordWrap: true,
126
+ style: { head: [], border: [] }
127
+ });
81
128
  links.forEach((l) => {
82
- console.log(`${chalk.bold(l.urlKey)} -> ${l.originalURL || '[Page]'} (${l.clicks || 0} clicks)`);
129
+ table.push([
130
+ chalk.bold(l.urlKey),
131
+ l.originalURL || chalk.dim('[Page]'),
132
+ l.clicks || 0
133
+ ]);
83
134
  });
135
+ console.log('\n' + table.toString() + '\n');
84
136
  }
85
137
  catch (error) {
86
- console.error(chalk.red('Failed to list links:'), error.response?.data?.message || error.message);
138
+ spinner.fail(chalk.red('Failed to list links: ') + (error.response?.data?.message || error.message));
87
139
  }
88
140
  });
89
141
  // --- Scope Commands ---
@@ -91,10 +143,12 @@ const scope = program.command('scope').description('Manage organization or perso
91
143
  scope
92
144
  .action(async () => {
93
145
  try {
146
+ const spinner = ora('Fetching available scopes...').start();
94
147
  const orgs = await OrgService.list();
148
+ spinner.stop();
95
149
  const choices = [
96
- { name: 'Personal Mode', value: null },
97
- ...orgs.map((o) => ({ name: `${o.name} (Organization)`, value: o._id }))
150
+ { name: `${chalk.yellow('●')} Personal Mode`, value: null },
151
+ ...orgs.map((o) => ({ name: `${chalk.cyan('●')} ${o.name} (Organization)`, value: o._id }))
98
152
  ];
99
153
  const { scopeId } = await inquirer.prompt([
100
154
  {
@@ -106,7 +160,7 @@ scope
106
160
  }
107
161
  ]);
108
162
  AuthService.setActiveOrg(scopeId);
109
- console.log(chalk.green(`\nActive scope set to: ${chalk.bold(scopeId ? 'Organization' : 'Personal')}`));
163
+ console.log(chalk.green(`\nActive scope set to: ${chalk.bold(scopeId ? 'Organization' : 'Personal')}! ✨`));
110
164
  }
111
165
  catch (error) {
112
166
  console.error(chalk.red('Failed to manage scope:'), error.response?.data?.message || error.message);
@@ -4,6 +4,7 @@ import open from 'open';
4
4
  import http from 'http';
5
5
  import { URL } from 'url';
6
6
  import { getConfig } from '../config.js';
7
+ import ora from 'ora';
7
8
  import { generateAuthResponseHtml } from '../utils/html.js';
8
9
  const PORT = 4005;
9
10
  const REDIRECT_URI = `http://localhost:${PORT}/callback`;
@@ -54,17 +55,29 @@ export class AuthService {
54
55
  finish('An unexpected error occurred during the authentication process. Please try again later.', false, err, 'Unexpected Error');
55
56
  }
56
57
  });
58
+ const spinner = ora('Opening browser for authentication...').start();
57
59
  server.listen(PORT, async () => {
58
- console.log(chalk.blue('\nOpening browser for authentication...'));
60
+ spinner.text = chalk.blue('Opening browser for authentication...');
59
61
  console.log(chalk.gray(`URL: ${authUrl}\n`));
60
62
  try {
61
63
  await open(authUrl);
64
+ spinner.text = chalk.yellow('Waiting for authentication in browser...');
62
65
  }
63
66
  catch (e) {
64
- console.log(chalk.yellow('Could not open browser automatically. Please open the link above manually.'));
67
+ spinner.warn(chalk.yellow('Could not open browser automatically. Please open the link above manually.'));
68
+ spinner.start(chalk.yellow('Waiting for authentication in browser...'));
65
69
  }
66
- console.log(chalk.yellow('Waiting for authentication in browser...'));
67
70
  });
71
+ const originalResolve = resolve;
72
+ const originalReject = reject;
73
+ resolve = () => {
74
+ spinner.succeed(chalk.green('Authentication successful!'));
75
+ originalResolve();
76
+ };
77
+ reject = (err) => {
78
+ spinner.fail(chalk.red('Authentication failed: ') + err.message);
79
+ originalReject(err);
80
+ };
68
81
  });
69
82
  }
70
83
  static async exchangeCode(code) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qubitlink_cli",
3
- "version": "1.0.0-dev.1",
3
+ "version": "1.0.0-dev.3",
4
4
  "description": "CLI tool for QubitLink",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -32,11 +32,14 @@
32
32
  "dependencies": {
33
33
  "@types/open": "^6.1.0",
34
34
  "axios": "^1.7.9",
35
+ "boxen": "^8.0.1",
35
36
  "chalk": "^5.4.1",
37
+ "cli-table3": "^0.6.5",
36
38
  "commander": "^13.1.0",
37
39
  "conf": "^13.1.0",
38
40
  "inquirer": "^12.3.2",
39
- "open": "^11.0.0"
41
+ "open": "^11.0.0",
42
+ "ora": "^9.1.0"
40
43
  },
41
44
  "devDependencies": {
42
45
  "@types/chalk": "^2.2.4",