@nestbox-ai/cli 1.0.25 → 1.0.26

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,2 @@
1
+ export { registerLoginCommand } from "./login";
2
+ export { registerLogoutCommand } from "./logout";
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerLogoutCommand = exports.registerLoginCommand = void 0;
4
+ // Auth command exports
5
+ var login_1 = require("./login");
6
+ Object.defineProperty(exports, "registerLoginCommand", { enumerable: true, get: function () { return login_1.registerLoginCommand; } });
7
+ var logout_1 = require("./logout");
8
+ Object.defineProperty(exports, "registerLogoutCommand", { enumerable: true, get: function () { return logout_1.registerLogoutCommand; } });
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/auth/index.ts"],"names":[],"mappings":";;;AAAA,uBAAuB;AACvB,iCAA+C;AAAtC,6GAAA,oBAAoB,OAAA;AAC7B,mCAAiD;AAAxC,+GAAA,qBAAqB,OAAA"}
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerLoginCommand(program: Command): void;
@@ -0,0 +1,186 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.registerLoginCommand = registerLoginCommand;
16
+ const chalk_1 = __importDefault(require("chalk"));
17
+ const inquirer_1 = __importDefault(require("inquirer"));
18
+ const open_1 = __importDefault(require("open"));
19
+ const ora_1 = __importDefault(require("ora"));
20
+ const fs_1 = __importDefault(require("fs"));
21
+ const os_1 = __importDefault(require("os"));
22
+ const path_1 = __importDefault(require("path"));
23
+ const admin_1 = require("@nestbox-ai/admin");
24
+ const axios_1 = __importDefault(require("axios"));
25
+ function registerLoginCommand(program) {
26
+ program
27
+ .command('login <nestbox-domain>')
28
+ .description('Login using Google SSO')
29
+ .action((domain) => __awaiter(this, void 0, void 0, function* () {
30
+ console.log('Login command triggered for domain:', domain);
31
+ const spinner = (0, ora_1.default)('Initiating Google login...').start();
32
+ try {
33
+ // Determine the protocol and construct the auth URL based on the provided domain
34
+ let authUrl;
35
+ if (domain.includes('localhost')) {
36
+ // Use HTTP for localhost and specific port
37
+ authUrl = `http://${domain}/cli/auth`;
38
+ }
39
+ else {
40
+ // Use HTTPS for all other domains
41
+ authUrl = `https://${domain}/cli/auth`;
42
+ }
43
+ spinner.text = 'Opening browser for Google authentication...';
44
+ // Open the browser for authentication
45
+ yield (0, open_1.default)(authUrl);
46
+ spinner.succeed('Browser opened for authentication');
47
+ // Prompt user to paste the combined token and API URL
48
+ const { combinedInput } = yield inquirer_1.default.prompt([
49
+ {
50
+ type: 'input',
51
+ name: 'combinedInput',
52
+ message: 'After authenticating, please paste the data here:',
53
+ validate: (input) => input.trim().length > 0 || 'Input is required'
54
+ }
55
+ ]);
56
+ // Split the input by comma
57
+ const [accessToken, apiServerUrl] = combinedInput.split(',').map(item => item.trim());
58
+ if (!accessToken || !apiServerUrl) {
59
+ spinner.fail('Invalid input format. Expected: token,apiServerUrl');
60
+ return;
61
+ }
62
+ console.log(chalk_1.default.green('Credentials received. Extracting user information...'));
63
+ // Fetch user data from the token
64
+ let email = '';
65
+ let name = '';
66
+ let picture = '';
67
+ try {
68
+ // Try to decode JWT to get user data (email, name, picture, etc.)
69
+ const tokenParts = accessToken.split('.');
70
+ if (tokenParts.length === 3) {
71
+ // Base64 decode the payload part of JWT
72
+ const base64Payload = tokenParts[1].replace(/-/g, '+').replace(/_/g, '/');
73
+ const decodedPayload = Buffer.from(base64Payload, 'base64').toString('utf-8');
74
+ const tokenPayload = JSON.parse(decodedPayload);
75
+ // Extract user information
76
+ email = tokenPayload.email || '';
77
+ name = tokenPayload.name || '';
78
+ picture = tokenPayload.picture || '';
79
+ }
80
+ }
81
+ catch (e) {
82
+ console.log(chalk_1.default.yellow('Could not decode token payload. Will prompt for email.'));
83
+ }
84
+ // If email couldn't be extracted from token, prompt user
85
+ if (!email) {
86
+ const response = yield inquirer_1.default.prompt([
87
+ {
88
+ type: 'input',
89
+ name: 'email',
90
+ message: 'Enter your email address:',
91
+ validate: (input) => /\S+@\S+\.\S+/.test(input) || 'Please enter a valid email'
92
+ }
93
+ ]);
94
+ email = response.email;
95
+ }
96
+ spinner.start('Verifying access token...');
97
+ if (apiServerUrl && email && accessToken) {
98
+ // Verify the access token
99
+ const configuration = new admin_1.Configuration({
100
+ basePath: apiServerUrl,
101
+ accessToken: accessToken,
102
+ });
103
+ const authApi = new admin_1.AuthApi(configuration);
104
+ try {
105
+ const response = yield authApi.authControllerOAuthLogin({
106
+ providerId: accessToken,
107
+ type: admin_1.OAuthLoginRequestDTOTypeEnum.Google,
108
+ email,
109
+ profilePictureUrl: picture || '',
110
+ });
111
+ const authResponse = response.data;
112
+ // Save credentials to file
113
+ try {
114
+ // Create directory structure
115
+ const configDir = path_1.default.join(os_1.default.homedir(), '.config', '.nestbox');
116
+ if (!fs_1.default.existsSync(configDir)) {
117
+ fs_1.default.mkdirSync(configDir, { recursive: true });
118
+ }
119
+ // Create the file path
120
+ const fileName = `${email.replace('@', '_at_')}_${domain}.json`;
121
+ const filePath = path_1.default.join(configDir, fileName);
122
+ // Create credentials object
123
+ const credentials = {
124
+ domain,
125
+ email,
126
+ token: authResponse.token,
127
+ accessToken, // Save the original accessToken
128
+ apiServerUrl,
129
+ name,
130
+ picture,
131
+ timestamp: new Date().toISOString()
132
+ };
133
+ // Write to file
134
+ fs_1.default.writeFileSync(filePath, JSON.stringify(credentials, null, 2));
135
+ spinner.succeed('Authentication successful');
136
+ console.log(chalk_1.default.green(`Successfully logged in as ${email}`));
137
+ console.log(chalk_1.default.blue(`Credentials saved to: ${filePath}`));
138
+ }
139
+ catch (fileError) {
140
+ spinner.warn('Authentication successful, but failed to save credentials file');
141
+ console.error(chalk_1.default.yellow('File error:'), fileError instanceof Error ? fileError.message : 'Unknown error');
142
+ }
143
+ }
144
+ catch (authError) {
145
+ spinner.fail('Failed to verify access token');
146
+ if (axios_1.default.isAxiosError(authError) && authError.response) {
147
+ if (authError.response.data.message === "user.not_found") {
148
+ console.error(chalk_1.default.red('Authentication Error:'), "You need to register your email with the Nestbox platform");
149
+ const { openSignup } = yield inquirer_1.default.prompt([
150
+ {
151
+ type: 'confirm',
152
+ name: 'openSignup',
153
+ message: 'Would you like to open the signup page to register?',
154
+ default: true
155
+ }
156
+ ]);
157
+ if (openSignup) {
158
+ // Construct signup URL with the same protocol logic as login
159
+ let signupUrl;
160
+ if (domain.includes('localhost')) {
161
+ signupUrl = `http://${domain}`;
162
+ }
163
+ else {
164
+ signupUrl = `https://${domain}`;
165
+ }
166
+ console.log(chalk_1.default.blue(`Opening signup page: ${signupUrl}`));
167
+ yield (0, open_1.default)(signupUrl);
168
+ }
169
+ }
170
+ }
171
+ else {
172
+ console.error(chalk_1.default.red('Authentication Error:'), authError instanceof Error ? authError.message : 'Unknown error');
173
+ }
174
+ }
175
+ }
176
+ else {
177
+ spinner.fail('Missing required information for authentication');
178
+ }
179
+ }
180
+ catch (error) {
181
+ spinner.fail('Authentication failed');
182
+ console.error(chalk_1.default.red('Error:'), error instanceof Error ? error.message : 'Unknown error');
183
+ }
184
+ }));
185
+ }
186
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../../src/commands/auth/login.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerLogoutCommand(program: Command): void;
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.registerLogoutCommand = registerLogoutCommand;
16
+ const chalk_1 = __importDefault(require("chalk"));
17
+ const inquirer_1 = __importDefault(require("inquirer"));
18
+ const fs_1 = __importDefault(require("fs"));
19
+ const os_1 = __importDefault(require("os"));
20
+ const path_1 = __importDefault(require("path"));
21
+ const auth_1 = require("../../utils/auth");
22
+ function registerLogoutCommand(program) {
23
+ program
24
+ .command('logout [nestbox-domain]')
25
+ .description('Logout from Nestbox platform')
26
+ .action((domain) => __awaiter(this, void 0, void 0, function* () {
27
+ try {
28
+ const authToken = (0, auth_1.getAuthToken)(domain);
29
+ if (!authToken) {
30
+ console.log(chalk_1.default.yellow('No authentication token found. Please log in first.'));
31
+ return;
32
+ }
33
+ // Function to remove all credential files for a domain
34
+ const removeCredentialFiles = (domain) => {
35
+ try {
36
+ const configDir = path_1.default.join(os_1.default.homedir(), '.config', '.nestbox');
37
+ if (!fs_1.default.existsSync(configDir)) {
38
+ return false;
39
+ }
40
+ // Sanitize domain for file matching
41
+ // Replace characters that are problematic in filenames
42
+ const sanitizedDomain = domain.replace(/:/g, '_');
43
+ // Get all files in the directory
44
+ const files = fs_1.default.readdirSync(configDir);
45
+ // Find and remove all files that match the domain
46
+ let removedCount = 0;
47
+ for (const file of files) {
48
+ // Check if the file matches any of the possible domain formats
49
+ if (file.endsWith(`_${domain}.json`) ||
50
+ file.endsWith(`_${sanitizedDomain}.json`)) {
51
+ fs_1.default.unlinkSync(path_1.default.join(configDir, file));
52
+ removedCount++;
53
+ }
54
+ }
55
+ return removedCount > 0;
56
+ }
57
+ catch (error) {
58
+ console.warn(chalk_1.default.yellow(`Warning: Could not remove credential files. ${error instanceof Error ? error.message : ''}`));
59
+ return false;
60
+ }
61
+ };
62
+ if (domain) {
63
+ // Logout from specific domain
64
+ // Remove credentials using utility function
65
+ const removed = (0, auth_1.removeCredentials)(domain);
66
+ // Also remove all credential files for this domain
67
+ const filesRemoved = removeCredentialFiles(domain);
68
+ if (removed || filesRemoved) {
69
+ console.log(chalk_1.default.green(`Successfully logged out from ${domain}`));
70
+ }
71
+ else {
72
+ console.log(chalk_1.default.yellow(`No credentials found for ${domain}`));
73
+ }
74
+ }
75
+ else {
76
+ // Ask which domain to logout from
77
+ const credentials = (0, auth_1.listCredentials)();
78
+ if (credentials.length === 0) {
79
+ console.log(chalk_1.default.yellow('No credentials found'));
80
+ return;
81
+ }
82
+ // Group credentials by domain
83
+ const domains = Array.from(new Set(credentials.map(cred => cred.domain)));
84
+ const domainChoices = domains.map(domain => {
85
+ const accounts = credentials.filter(cred => cred.domain === domain);
86
+ return `${domain} (${accounts.length} account${accounts.length > 1 ? 's' : ''})`;
87
+ });
88
+ const { selected } = yield inquirer_1.default.prompt([
89
+ {
90
+ type: 'list',
91
+ name: 'selected',
92
+ message: 'Select domain to logout from:',
93
+ choices: domainChoices,
94
+ }
95
+ ]);
96
+ // Extract domain from the selected choice
97
+ const selectedDomain = selected.split(' ')[0];
98
+ // Remove credentials using utility function
99
+ (0, auth_1.removeCredentials)(selectedDomain);
100
+ // Also remove all credential files for this domain
101
+ removeCredentialFiles(selectedDomain);
102
+ console.log(chalk_1.default.green(`Successfully logged out from ${selectedDomain}`));
103
+ }
104
+ }
105
+ catch (error) {
106
+ const err = error;
107
+ console.error(chalk_1.default.red('Error:'), err.message);
108
+ }
109
+ }));
110
+ }
111
+ //# sourceMappingURL=logout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.js","sourceRoot":"","sources":["../../../src/commands/auth/logout.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,5 @@
1
- import { Command } from 'commander';
1
+ import { Command } from "commander";
2
+ /**
3
+ * Register all auth-related commands
4
+ */
2
5
  export declare function registerAuthCommands(program: Command): void;
@@ -1,276 +1,14 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- var __importDefault = (this && this.__importDefault) || function (mod) {
12
- return (mod && mod.__esModule) ? mod : { "default": mod };
13
- };
14
2
  Object.defineProperty(exports, "__esModule", { value: true });
15
3
  exports.registerAuthCommands = registerAuthCommands;
16
- const chalk_1 = __importDefault(require("chalk"));
17
- const inquirer_1 = __importDefault(require("inquirer"));
18
- const open_1 = __importDefault(require("open"));
19
- const ora_1 = __importDefault(require("ora"));
20
- const fs_1 = __importDefault(require("fs"));
21
- const os_1 = __importDefault(require("os"));
22
- const path_1 = __importDefault(require("path"));
23
- const auth_1 = require("../utils/auth");
24
- const admin_1 = require("@nestbox-ai/admin");
25
- const axios_1 = __importDefault(require("axios"));
4
+ const login_1 = require("./auth/login");
5
+ const logout_1 = require("./auth/logout");
6
+ /**
7
+ * Register all auth-related commands
8
+ */
26
9
  function registerAuthCommands(program) {
27
- // Login command
28
- program
29
- .command('login <nestbox-domain>')
30
- .description('Login using Google SSO')
31
- .action((domain) => __awaiter(this, void 0, void 0, function* () {
32
- console.log('Login command triggered for domain:', domain);
33
- const spinner = (0, ora_1.default)('Initiating Google login...').start();
34
- try {
35
- // Determine the protocol and construct the auth URL based on the provided domain
36
- let authUrl;
37
- if (domain.includes('localhost')) {
38
- // Use HTTP for localhost and specific port
39
- authUrl = `http://${domain}/cli/auth`;
40
- }
41
- else {
42
- // Use HTTPS for all other domains
43
- authUrl = `https://${domain}/cli/auth`;
44
- }
45
- spinner.text = 'Opening browser for Google authentication...';
46
- // Open the browser for authentication
47
- yield (0, open_1.default)(authUrl);
48
- spinner.succeed('Browser opened for authentication');
49
- // Prompt user to paste the combined token and API URL
50
- const { combinedInput } = yield inquirer_1.default.prompt([
51
- {
52
- type: 'input',
53
- name: 'combinedInput',
54
- message: 'After authenticating, please paste the data here:',
55
- validate: (input) => input.trim().length > 0 || 'Input is required'
56
- }
57
- ]);
58
- // Split the input by comma
59
- const [accessToken, apiServerUrl] = combinedInput.split(',').map(item => item.trim());
60
- if (!accessToken || !apiServerUrl) {
61
- spinner.fail('Invalid input format. Expected: token,apiServerUrl');
62
- return;
63
- }
64
- console.log(chalk_1.default.green('Credentials received. Extracting user information...'));
65
- // Fetch user data from the token
66
- let email = '';
67
- let name = '';
68
- let picture = '';
69
- try {
70
- // Try to decode JWT to get user data (email, name, picture, etc.)
71
- const tokenParts = accessToken.split('.');
72
- if (tokenParts.length === 3) {
73
- // Base64 decode the payload part of JWT
74
- const base64Payload = tokenParts[1].replace(/-/g, '+').replace(/_/g, '/');
75
- const decodedPayload = Buffer.from(base64Payload, 'base64').toString('utf-8');
76
- const tokenPayload = JSON.parse(decodedPayload);
77
- // Extract user information
78
- email = tokenPayload.email || '';
79
- name = tokenPayload.name || '';
80
- picture = tokenPayload.picture || '';
81
- }
82
- }
83
- catch (e) {
84
- console.log(chalk_1.default.yellow('Could not decode token payload. Will prompt for email.'));
85
- }
86
- // If email couldn't be extracted from token, prompt user
87
- if (!email) {
88
- const response = yield inquirer_1.default.prompt([
89
- {
90
- type: 'input',
91
- name: 'email',
92
- message: 'Enter your email address:',
93
- validate: (input) => /\S+@\S+\.\S+/.test(input) || 'Please enter a valid email'
94
- }
95
- ]);
96
- email = response.email;
97
- }
98
- spinner.start('Verifying access token...');
99
- if (apiServerUrl && email && accessToken) {
100
- // Verify the access token
101
- const configuration = new admin_1.Configuration({
102
- basePath: apiServerUrl,
103
- accessToken: accessToken,
104
- });
105
- const authApi = new admin_1.AuthApi(configuration);
106
- try {
107
- const response = yield authApi.authControllerOAuthLogin({
108
- providerId: accessToken,
109
- type: admin_1.OAuthLoginRequestDTOTypeEnum.Google,
110
- email,
111
- profilePictureUrl: picture || '',
112
- });
113
- const authResponse = response.data;
114
- // Save credentials to file
115
- try {
116
- // Create directory structure
117
- const configDir = path_1.default.join(os_1.default.homedir(), '.config', '.nestbox');
118
- if (!fs_1.default.existsSync(configDir)) {
119
- fs_1.default.mkdirSync(configDir, { recursive: true });
120
- }
121
- // Create the file path
122
- const fileName = `${email.replace('@', '_at_')}_${domain}.json`;
123
- const filePath = path_1.default.join(configDir, fileName);
124
- // Create credentials object
125
- const credentials = {
126
- domain,
127
- email,
128
- token: authResponse.token,
129
- accessToken, // Save the original accessToken
130
- apiServerUrl,
131
- name,
132
- picture,
133
- timestamp: new Date().toISOString()
134
- };
135
- // Write to file
136
- fs_1.default.writeFileSync(filePath, JSON.stringify(credentials, null, 2));
137
- spinner.succeed('Authentication successful');
138
- console.log(chalk_1.default.green(`Successfully logged in as ${email}`));
139
- console.log(chalk_1.default.blue(`Credentials saved to: ${filePath}`));
140
- }
141
- catch (fileError) {
142
- spinner.warn('Authentication successful, but failed to save credentials file');
143
- console.error(chalk_1.default.yellow('File error:'), fileError instanceof Error ? fileError.message : 'Unknown error');
144
- }
145
- }
146
- catch (authError) {
147
- spinner.fail('Failed to verify access token');
148
- if (axios_1.default.isAxiosError(authError) && authError.response) {
149
- if (authError.response.data.message === "user.not_found") {
150
- console.error(chalk_1.default.red('Authentication Error:'), "You need to register your email with the Nestbox platform");
151
- const { openSignup } = yield inquirer_1.default.prompt([
152
- {
153
- type: 'confirm',
154
- name: 'openSignup',
155
- message: 'Would you like to open the signup page to register?',
156
- default: true
157
- }
158
- ]);
159
- if (openSignup) {
160
- // Construct signup URL with the same protocol logic as login
161
- let signupUrl;
162
- if (domain.includes('localhost')) {
163
- signupUrl = `http://${domain}`;
164
- }
165
- else {
166
- signupUrl = `https://${domain}`;
167
- }
168
- console.log(chalk_1.default.blue(`Opening signup page: ${signupUrl}`));
169
- yield (0, open_1.default)(signupUrl);
170
- }
171
- }
172
- }
173
- else {
174
- console.error(chalk_1.default.red('Authentication Error:'), authError instanceof Error ? authError.message : 'Unknown error');
175
- }
176
- }
177
- }
178
- else {
179
- spinner.fail('Missing required information for authentication');
180
- }
181
- }
182
- catch (error) {
183
- spinner.fail('Authentication failed');
184
- console.error(chalk_1.default.red('Error:'), error instanceof Error ? error.message : 'Unknown error');
185
- }
186
- }));
187
- // Logout command
188
- program
189
- .command('logout [nestbox-domain]')
190
- .description('Logout from Nestbox platform')
191
- .action((domain) => __awaiter(this, void 0, void 0, function* () {
192
- try {
193
- const authToken = (0, auth_1.getAuthToken)(domain);
194
- if (!authToken) {
195
- console.log(chalk_1.default.yellow('No authentication token found. Please log in first.'));
196
- return;
197
- }
198
- // Function to remove all credential files for a domain
199
- const removeCredentialFiles = (domain) => {
200
- try {
201
- const configDir = path_1.default.join(os_1.default.homedir(), '.config', '.nestbox');
202
- if (!fs_1.default.existsSync(configDir)) {
203
- return false;
204
- }
205
- // Sanitize domain for file matching
206
- // Replace characters that are problematic in filenames
207
- const sanitizedDomain = domain.replace(/:/g, '_');
208
- // Get all files in the directory
209
- const files = fs_1.default.readdirSync(configDir);
210
- // Find and remove all files that match the domain
211
- let removedCount = 0;
212
- for (const file of files) {
213
- // Check if the file matches any of the possible domain formats
214
- if (file.endsWith(`_${domain}.json`) ||
215
- file.endsWith(`_${sanitizedDomain}.json`)) {
216
- fs_1.default.unlinkSync(path_1.default.join(configDir, file));
217
- removedCount++;
218
- }
219
- }
220
- return removedCount > 0;
221
- }
222
- catch (error) {
223
- console.warn(chalk_1.default.yellow(`Warning: Could not remove credential files. ${error instanceof Error ? error.message : ''}`));
224
- return false;
225
- }
226
- };
227
- if (domain) {
228
- // Logout from specific domain
229
- // Remove credentials using utility function
230
- const removed = (0, auth_1.removeCredentials)(domain);
231
- // Also remove all credential files for this domain
232
- const filesRemoved = removeCredentialFiles(domain);
233
- if (removed || filesRemoved) {
234
- console.log(chalk_1.default.green(`Successfully logged out from ${domain}`));
235
- }
236
- else {
237
- console.log(chalk_1.default.yellow(`No credentials found for ${domain}`));
238
- }
239
- }
240
- else {
241
- // Ask which domain to logout from
242
- const credentials = (0, auth_1.listCredentials)();
243
- if (credentials.length === 0) {
244
- console.log(chalk_1.default.yellow('No credentials found'));
245
- return;
246
- }
247
- // Group credentials by domain
248
- const domains = Array.from(new Set(credentials.map(cred => cred.domain)));
249
- const domainChoices = domains.map(domain => {
250
- const accounts = credentials.filter(cred => cred.domain === domain);
251
- return `${domain} (${accounts.length} account${accounts.length > 1 ? 's' : ''})`;
252
- });
253
- const { selected } = yield inquirer_1.default.prompt([
254
- {
255
- type: 'list',
256
- name: 'selected',
257
- message: 'Select domain to logout from:',
258
- choices: domainChoices,
259
- }
260
- ]);
261
- // Extract domain from the selected choice
262
- const selectedDomain = selected.split(' ')[0];
263
- // Remove credentials using utility function
264
- (0, auth_1.removeCredentials)(selectedDomain);
265
- // Also remove all credential files for this domain
266
- removeCredentialFiles(selectedDomain);
267
- console.log(chalk_1.default.green(`Successfully logged out from ${selectedDomain}`));
268
- }
269
- }
270
- catch (error) {
271
- const err = error;
272
- console.error(chalk_1.default.red('Error:'), err.message);
273
- }
274
- }));
10
+ // Register auth commands directly on the program (not as subcommands)
11
+ (0, login_1.registerLoginCommand)(program);
12
+ (0, logout_1.registerLogoutCommand)(program);
275
13
  }
276
14
  //# sourceMappingURL=auth.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":";;AAOA,oDAIC;AAVD,wCAAoD;AACpD,0CAAsD;AAEtD;;GAEG;AACH,SAAgB,oBAAoB,CAAC,OAAgB;IACnD,sEAAsE;IACtE,IAAA,4BAAoB,EAAC,OAAO,CAAC,CAAC;IAC9B,IAAA,8BAAqB,EAAC,OAAO,CAAC,CAAC;AACjC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nestbox-ai/cli",
3
- "version": "1.0.25",
3
+ "version": "1.0.26",
4
4
  "description": "The cli tools that helps developers to build agents",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -0,0 +1,3 @@
1
+ // Auth command exports
2
+ export { registerLoginCommand } from "./login";
3
+ export { registerLogoutCommand } from "./logout";
@@ -0,0 +1,184 @@
1
+ import { Command } from 'commander';
2
+ import chalk from 'chalk';
3
+ import inquirer from 'inquirer';
4
+ import open from 'open';
5
+ import ora from 'ora';
6
+ import fs from 'fs';
7
+ import os from 'os';
8
+ import path from 'path';
9
+ import { AuthApi, Configuration, OAuthLoginRequestDTOTypeEnum } from '@nestbox-ai/admin';
10
+ import axios from 'axios';
11
+
12
+ export function registerLoginCommand(program: Command): void {
13
+ program
14
+ .command('login <nestbox-domain>')
15
+ .description('Login using Google SSO')
16
+ .action(async (domain: string) => {
17
+ console.log('Login command triggered for domain:', domain);
18
+ const spinner = ora('Initiating Google login...').start();
19
+
20
+ try {
21
+ // Determine the protocol and construct the auth URL based on the provided domain
22
+ let authUrl;
23
+ if (domain.includes('localhost')) {
24
+ // Use HTTP for localhost and specific port
25
+ authUrl = `http://${domain}/cli/auth`;
26
+ } else {
27
+ // Use HTTPS for all other domains
28
+ authUrl = `https://${domain}/cli/auth`;
29
+ }
30
+
31
+ spinner.text = 'Opening browser for Google authentication...';
32
+
33
+ // Open the browser for authentication
34
+ await open(authUrl);
35
+ spinner.succeed('Browser opened for authentication');
36
+
37
+ // Prompt user to paste the combined token and API URL
38
+ const { combinedInput } = await inquirer.prompt<{ combinedInput: string }>([
39
+ {
40
+ type: 'input',
41
+ name: 'combinedInput',
42
+ message: 'After authenticating, please paste the data here:',
43
+ validate: (input) => input.trim().length > 0 || 'Input is required'
44
+ }
45
+ ]);
46
+
47
+ // Split the input by comma
48
+ const [accessToken, apiServerUrl] = combinedInput.split(',').map(item => item.trim());
49
+
50
+ if (!accessToken || !apiServerUrl) {
51
+ spinner.fail('Invalid input format. Expected: token,apiServerUrl');
52
+ return;
53
+ }
54
+
55
+ console.log(chalk.green('Credentials received. Extracting user information...'));
56
+
57
+ // Fetch user data from the token
58
+ let email = '';
59
+ let name = '';
60
+ let picture = '';
61
+ try {
62
+ // Try to decode JWT to get user data (email, name, picture, etc.)
63
+ const tokenParts = accessToken.split('.');
64
+ if (tokenParts.length === 3) {
65
+ // Base64 decode the payload part of JWT
66
+ const base64Payload = tokenParts[1].replace(/-/g, '+').replace(/_/g, '/');
67
+ const decodedPayload = Buffer.from(base64Payload, 'base64').toString('utf-8');
68
+ const tokenPayload = JSON.parse(decodedPayload);
69
+
70
+ // Extract user information
71
+ email = tokenPayload.email || '';
72
+ name = tokenPayload.name || '';
73
+ picture = tokenPayload.picture || '';
74
+ }
75
+ } catch (e) {
76
+ console.log(chalk.yellow('Could not decode token payload. Will prompt for email.'));
77
+ }
78
+
79
+ // If email couldn't be extracted from token, prompt user
80
+ if (!email) {
81
+ const response = await inquirer.prompt<{ email: string }>([
82
+ {
83
+ type: 'input',
84
+ name: 'email',
85
+ message: 'Enter your email address:',
86
+ validate: (input) => /\S+@\S+\.\S+/.test(input) || 'Please enter a valid email'
87
+ }
88
+ ]);
89
+ email = response.email;
90
+ }
91
+
92
+ spinner.start('Verifying access token...');
93
+
94
+ if (apiServerUrl && email && accessToken) {
95
+ // Verify the access token
96
+ const configuration = new Configuration({
97
+ basePath: apiServerUrl,
98
+ accessToken: accessToken,
99
+ });
100
+ const authApi = new AuthApi(configuration);
101
+ try {
102
+ const response = await authApi.authControllerOAuthLogin({
103
+ providerId: accessToken,
104
+ type: OAuthLoginRequestDTOTypeEnum.Google,
105
+ email,
106
+ profilePictureUrl: picture || '',
107
+ });
108
+ const authResponse = response.data;
109
+
110
+ // Save credentials to file
111
+ try {
112
+ // Create directory structure
113
+ const configDir = path.join(os.homedir(), '.config', '.nestbox');
114
+ if (!fs.existsSync(configDir)) {
115
+ fs.mkdirSync(configDir, { recursive: true });
116
+ }
117
+
118
+ // Create the file path
119
+ const fileName = `${email.replace('@', '_at_')}_${domain}.json`;
120
+ const filePath = path.join(configDir, fileName);
121
+
122
+ // Create credentials object
123
+ const credentials = {
124
+ domain,
125
+ email,
126
+ token: authResponse.token,
127
+ accessToken, // Save the original accessToken
128
+ apiServerUrl,
129
+ name,
130
+ picture,
131
+ timestamp: new Date().toISOString()
132
+ };
133
+
134
+ // Write to file
135
+ fs.writeFileSync(filePath, JSON.stringify(credentials, null, 2));
136
+
137
+ spinner.succeed('Authentication successful');
138
+ console.log(chalk.green(`Successfully logged in as ${email}`));
139
+ console.log(chalk.blue(`Credentials saved to: ${filePath}`));
140
+ } catch (fileError) {
141
+ spinner.warn('Authentication successful, but failed to save credentials file');
142
+ console.error(chalk.yellow('File error:'), fileError instanceof Error ? fileError.message : 'Unknown error');
143
+
144
+ }
145
+ } catch (authError) {
146
+ spinner.fail('Failed to verify access token');
147
+ if (axios.isAxiosError(authError) && authError.response) {
148
+ if (authError.response.data.message === "user.not_found") {
149
+ console.error(chalk.red('Authentication Error:'), "You need to register your email with the Nestbox platform");
150
+ const { openSignup } = await inquirer.prompt<{ openSignup: boolean }>([
151
+ {
152
+ type: 'confirm',
153
+ name: 'openSignup',
154
+ message: 'Would you like to open the signup page to register?',
155
+ default: true
156
+ }
157
+ ]);
158
+
159
+ if (openSignup) {
160
+ // Construct signup URL with the same protocol logic as login
161
+ let signupUrl;
162
+ if (domain.includes('localhost')) {
163
+ signupUrl = `http://${domain}`;
164
+ } else {
165
+ signupUrl = `https://${domain}`;
166
+ }
167
+
168
+ console.log(chalk.blue(`Opening signup page: ${signupUrl}`));
169
+ await open(signupUrl);
170
+ }
171
+ }
172
+ } else {
173
+ console.error(chalk.red('Authentication Error:'), authError instanceof Error ? authError.message : 'Unknown error');
174
+ }
175
+ }
176
+ } else {
177
+ spinner.fail('Missing required information for authentication');
178
+ }
179
+ } catch (error) {
180
+ spinner.fail('Authentication failed');
181
+ console.error(chalk.red('Error:'), error instanceof Error ? error.message : 'Unknown error');
182
+ }
183
+ });
184
+ }
@@ -0,0 +1,110 @@
1
+ import { Command } from 'commander';
2
+ import chalk from 'chalk';
3
+ import inquirer from 'inquirer';
4
+ import fs from 'fs';
5
+ import os from 'os';
6
+ import path from 'path';
7
+ import { getAuthToken, listCredentials, removeCredentials } from '../../utils/auth';
8
+
9
+ export function registerLogoutCommand(program: Command): void {
10
+ program
11
+ .command('logout [nestbox-domain]')
12
+ .description('Logout from Nestbox platform')
13
+ .action(async (domain?: string) => {
14
+ try {
15
+ const authToken = getAuthToken(domain);
16
+ if (!authToken) {
17
+ console.log(chalk.yellow('No authentication token found. Please log in first.'));
18
+ return;
19
+ }
20
+
21
+ // Function to remove all credential files for a domain
22
+ const removeCredentialFiles = (domain: string) => {
23
+ try {
24
+ const configDir = path.join(os.homedir(), '.config', '.nestbox');
25
+ if (!fs.existsSync(configDir)) {
26
+ return false;
27
+ }
28
+
29
+ // Sanitize domain for file matching
30
+ // Replace characters that are problematic in filenames
31
+ const sanitizedDomain = domain.replace(/:/g, '_');
32
+
33
+ // Get all files in the directory
34
+ const files = fs.readdirSync(configDir);
35
+
36
+ // Find and remove all files that match the domain
37
+ let removedCount = 0;
38
+ for (const file of files) {
39
+ // Check if the file matches any of the possible domain formats
40
+ if (
41
+ file.endsWith(`_${domain}.json`) ||
42
+ file.endsWith(`_${sanitizedDomain}.json`)
43
+ ) {
44
+ fs.unlinkSync(path.join(configDir, file));
45
+ removedCount++;
46
+ }
47
+ }
48
+
49
+ return removedCount > 0;
50
+ } catch (error) {
51
+ console.warn(chalk.yellow(`Warning: Could not remove credential files. ${error instanceof Error ? error.message : ''}`));
52
+ return false;
53
+ }
54
+ };
55
+
56
+ if (domain) {
57
+ // Logout from specific domain
58
+ // Remove credentials using utility function
59
+ const removed = removeCredentials(domain);
60
+
61
+ // Also remove all credential files for this domain
62
+ const filesRemoved = removeCredentialFiles(domain);
63
+
64
+ if (removed || filesRemoved) {
65
+ console.log(chalk.green(`Successfully logged out from ${domain}`));
66
+ } else {
67
+ console.log(chalk.yellow(`No credentials found for ${domain}`));
68
+ }
69
+ } else {
70
+ // Ask which domain to logout from
71
+ const credentials = listCredentials();
72
+
73
+ if (credentials.length === 0) {
74
+ console.log(chalk.yellow('No credentials found'));
75
+ return;
76
+ }
77
+
78
+ // Group credentials by domain
79
+ const domains = Array.from(new Set(credentials.map(cred => cred.domain)));
80
+ const domainChoices = domains.map(domain => {
81
+ const accounts = credentials.filter(cred => cred.domain === domain);
82
+ return `${domain} (${accounts.length} account${accounts.length > 1 ? 's' : ''})`;
83
+ });
84
+
85
+ const { selected } = await inquirer.prompt<{ selected: string }>([
86
+ {
87
+ type: 'list',
88
+ name: 'selected',
89
+ message: 'Select domain to logout from:',
90
+ choices: domainChoices,
91
+ }
92
+ ]);
93
+
94
+ // Extract domain from the selected choice
95
+ const selectedDomain = selected.split(' ')[0];
96
+
97
+ // Remove credentials using utility function
98
+ removeCredentials(selectedDomain);
99
+
100
+ // Also remove all credential files for this domain
101
+ removeCredentialFiles(selectedDomain);
102
+
103
+ console.log(chalk.green(`Successfully logged out from ${selectedDomain}`));
104
+ }
105
+ } catch (error) {
106
+ const err = error as Error;
107
+ console.error(chalk.red('Error:'), err.message);
108
+ }
109
+ });
110
+ }
@@ -1,291 +1,12 @@
1
- import { Command } from 'commander';
2
- import chalk from 'chalk';
3
- import inquirer from 'inquirer';
4
- import open from 'open';
5
- import ora from 'ora';
6
- import fs from 'fs';
7
- import os from 'os';
8
- import path from 'path';
9
- import { getAuthToken, listCredentials, removeCredentials } from '../utils/auth';
10
- import { AuthApi, Configuration, OAuthLoginRequestDTOTypeEnum } from '@nestbox-ai/admin';
11
- import axios from 'axios';
12
-
1
+ import { Command } from "commander";
2
+ import { registerLoginCommand } from "./auth/login";
3
+ import { registerLogoutCommand } from "./auth/logout";
13
4
 
5
+ /**
6
+ * Register all auth-related commands
7
+ */
14
8
  export function registerAuthCommands(program: Command): void {
15
- // Login command
16
- program
17
- .command('login <nestbox-domain>')
18
- .description('Login using Google SSO')
19
- .action(async (domain: string) => {
20
- console.log('Login command triggered for domain:', domain);
21
- const spinner = ora('Initiating Google login...').start();
22
-
23
- try {
24
- // Determine the protocol and construct the auth URL based on the provided domain
25
- let authUrl;
26
- if (domain.includes('localhost')) {
27
- // Use HTTP for localhost and specific port
28
- authUrl = `http://${domain}/cli/auth`;
29
- } else {
30
- // Use HTTPS for all other domains
31
- authUrl = `https://${domain}/cli/auth`;
32
- }
33
-
34
- spinner.text = 'Opening browser for Google authentication...';
35
-
36
- // Open the browser for authentication
37
- await open(authUrl);
38
- spinner.succeed('Browser opened for authentication');
39
-
40
- // Prompt user to paste the combined token and API URL
41
- const { combinedInput } = await inquirer.prompt<{ combinedInput: string }>([
42
- {
43
- type: 'input',
44
- name: 'combinedInput',
45
- message: 'After authenticating, please paste the data here:',
46
- validate: (input) => input.trim().length > 0 || 'Input is required'
47
- }
48
- ]);
49
-
50
- // Split the input by comma
51
- const [accessToken, apiServerUrl] = combinedInput.split(',').map(item => item.trim());
52
-
53
- if (!accessToken || !apiServerUrl) {
54
- spinner.fail('Invalid input format. Expected: token,apiServerUrl');
55
- return;
56
- }
57
-
58
- console.log(chalk.green('Credentials received. Extracting user information...'));
59
-
60
- // Fetch user data from the token
61
- let email = '';
62
- let name = '';
63
- let picture = '';
64
- try {
65
- // Try to decode JWT to get user data (email, name, picture, etc.)
66
- const tokenParts = accessToken.split('.');
67
- if (tokenParts.length === 3) {
68
- // Base64 decode the payload part of JWT
69
- const base64Payload = tokenParts[1].replace(/-/g, '+').replace(/_/g, '/');
70
- const decodedPayload = Buffer.from(base64Payload, 'base64').toString('utf-8');
71
- const tokenPayload = JSON.parse(decodedPayload);
72
-
73
- // Extract user information
74
- email = tokenPayload.email || '';
75
- name = tokenPayload.name || '';
76
- picture = tokenPayload.picture || '';
77
- }
78
- } catch (e) {
79
- console.log(chalk.yellow('Could not decode token payload. Will prompt for email.'));
80
- }
81
-
82
- // If email couldn't be extracted from token, prompt user
83
- if (!email) {
84
- const response = await inquirer.prompt<{ email: string }>([
85
- {
86
- type: 'input',
87
- name: 'email',
88
- message: 'Enter your email address:',
89
- validate: (input) => /\S+@\S+\.\S+/.test(input) || 'Please enter a valid email'
90
- }
91
- ]);
92
- email = response.email;
93
- }
94
-
95
- spinner.start('Verifying access token...');
96
-
97
- if (apiServerUrl && email && accessToken) {
98
- // Verify the access token
99
- const configuration = new Configuration({
100
- basePath: apiServerUrl,
101
- accessToken: accessToken,
102
- });
103
- const authApi = new AuthApi(configuration);
104
- try {
105
- const response = await authApi.authControllerOAuthLogin({
106
- providerId: accessToken,
107
- type: OAuthLoginRequestDTOTypeEnum.Google,
108
- email,
109
- profilePictureUrl: picture || '',
110
- });
111
- const authResponse = response.data;
112
-
113
- // Save credentials to file
114
- try {
115
- // Create directory structure
116
- const configDir = path.join(os.homedir(), '.config', '.nestbox');
117
- if (!fs.existsSync(configDir)) {
118
- fs.mkdirSync(configDir, { recursive: true });
119
- }
120
-
121
- // Create the file path
122
- const fileName = `${email.replace('@', '_at_')}_${domain}.json`;
123
- const filePath = path.join(configDir, fileName);
124
-
125
- // Create credentials object
126
- const credentials = {
127
- domain,
128
- email,
129
- token: authResponse.token,
130
- accessToken, // Save the original accessToken
131
- apiServerUrl,
132
- name,
133
- picture,
134
- timestamp: new Date().toISOString()
135
- };
136
-
137
- // Write to file
138
- fs.writeFileSync(filePath, JSON.stringify(credentials, null, 2));
139
-
140
- spinner.succeed('Authentication successful');
141
- console.log(chalk.green(`Successfully logged in as ${email}`));
142
- console.log(chalk.blue(`Credentials saved to: ${filePath}`));
143
- } catch (fileError) {
144
- spinner.warn('Authentication successful, but failed to save credentials file');
145
- console.error(chalk.yellow('File error:'), fileError instanceof Error ? fileError.message : 'Unknown error');
146
-
147
- }
148
- } catch (authError) {
149
- spinner.fail('Failed to verify access token');
150
- if (axios.isAxiosError(authError) && authError.response) {
151
- if (authError.response.data.message === "user.not_found") {
152
- console.error(chalk.red('Authentication Error:'), "You need to register your email with the Nestbox platform");
153
- const { openSignup } = await inquirer.prompt<{ openSignup: boolean }>([
154
- {
155
- type: 'confirm',
156
- name: 'openSignup',
157
- message: 'Would you like to open the signup page to register?',
158
- default: true
159
- }
160
- ]);
161
-
162
- if (openSignup) {
163
- // Construct signup URL with the same protocol logic as login
164
- let signupUrl;
165
- if (domain.includes('localhost')) {
166
- signupUrl = `http://${domain}`;
167
- } else {
168
- signupUrl = `https://${domain}`;
169
- }
170
-
171
- console.log(chalk.blue(`Opening signup page: ${signupUrl}`));
172
- await open(signupUrl);
173
- }
174
- }
175
- } else {
176
- console.error(chalk.red('Authentication Error:'), authError instanceof Error ? authError.message : 'Unknown error');
177
- }
178
- }
179
- } else {
180
- spinner.fail('Missing required information for authentication');
181
- }
182
- } catch (error) {
183
- spinner.fail('Authentication failed');
184
- console.error(chalk.red('Error:'), error instanceof Error ? error.message : 'Unknown error');
185
- }
186
- });
187
-
188
-
189
-
190
- // Logout command
191
- program
192
- .command('logout [nestbox-domain]')
193
- .description('Logout from Nestbox platform')
194
- .action(async (domain?: string) => {
195
- try {
196
- const authToken = getAuthToken(domain);
197
- if (!authToken) {
198
- console.log(chalk.yellow('No authentication token found. Please log in first.'));
199
- return;
200
- }
201
-
202
- // Function to remove all credential files for a domain
203
- const removeCredentialFiles = (domain: string) => {
204
- try {
205
- const configDir = path.join(os.homedir(), '.config', '.nestbox');
206
- if (!fs.existsSync(configDir)) {
207
- return false;
208
- }
209
-
210
- // Sanitize domain for file matching
211
- // Replace characters that are problematic in filenames
212
- const sanitizedDomain = domain.replace(/:/g, '_');
213
-
214
- // Get all files in the directory
215
- const files = fs.readdirSync(configDir);
216
-
217
- // Find and remove all files that match the domain
218
- let removedCount = 0;
219
- for (const file of files) {
220
- // Check if the file matches any of the possible domain formats
221
- if (
222
- file.endsWith(`_${domain}.json`) ||
223
- file.endsWith(`_${sanitizedDomain}.json`)
224
- ) {
225
- fs.unlinkSync(path.join(configDir, file));
226
- removedCount++;
227
- }
228
- }
229
-
230
- return removedCount > 0;
231
- } catch (error) {
232
- console.warn(chalk.yellow(`Warning: Could not remove credential files. ${error instanceof Error ? error.message : ''}`));
233
- return false;
234
- }
235
- };
236
-
237
- if (domain) {
238
- // Logout from specific domain
239
- // Remove credentials using utility function
240
- const removed = removeCredentials(domain);
241
-
242
- // Also remove all credential files for this domain
243
- const filesRemoved = removeCredentialFiles(domain);
244
-
245
- if (removed || filesRemoved) {
246
- console.log(chalk.green(`Successfully logged out from ${domain}`));
247
- } else {
248
- console.log(chalk.yellow(`No credentials found for ${domain}`));
249
- }
250
- } else {
251
- // Ask which domain to logout from
252
- const credentials = listCredentials();
253
-
254
- if (credentials.length === 0) {
255
- console.log(chalk.yellow('No credentials found'));
256
- return;
257
- }
258
-
259
- // Group credentials by domain
260
- const domains = Array.from(new Set(credentials.map(cred => cred.domain)));
261
- const domainChoices = domains.map(domain => {
262
- const accounts = credentials.filter(cred => cred.domain === domain);
263
- return `${domain} (${accounts.length} account${accounts.length > 1 ? 's' : ''})`;
264
- });
265
-
266
- const { selected } = await inquirer.prompt<{ selected: string }>([
267
- {
268
- type: 'list',
269
- name: 'selected',
270
- message: 'Select domain to logout from:',
271
- choices: domainChoices,
272
- }
273
- ]);
274
-
275
- // Extract domain from the selected choice
276
- const selectedDomain = selected.split(' ')[0];
277
-
278
- // Remove credentials using utility function
279
- removeCredentials(selectedDomain);
280
-
281
- // Also remove all credential files for this domain
282
- removeCredentialFiles(selectedDomain);
283
-
284
- console.log(chalk.green(`Successfully logged out from ${selectedDomain}`));
285
- }
286
- } catch (error) {
287
- const err = error as Error;
288
- console.error(chalk.red('Error:'), err.message);
289
- }
290
- });
9
+ // Register auth commands directly on the program (not as subcommands)
10
+ registerLoginCommand(program);
11
+ registerLogoutCommand(program);
291
12
  }