UNPKG

@nestbox-ai/cli

Version:

The cli tools that helps developers to build agents

163 lines 8.03 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.handle401Error = handle401Error; exports.withTokenRefresh = withTokenRefresh; // utils/error.ts const admin_1 = require("@nestbox-ai/admin"); const auth_1 = require("./auth"); const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const os_1 = __importDefault(require("os")); const chalk_1 = __importDefault(require("chalk")); /** * Attempts to refresh the authentication token using stored credentials */ function refreshAuthToken(serverUrl, accessToken) { return __awaiter(this, void 0, void 0, function* () { try { // Get the stored credentials to extract user info const configDir = path_1.default.join(os_1.default.homedir(), '.config', '.nestbox'); const files = fs_1.default.readdirSync(configDir); // Find the credential file that matches this server URL let userCredentials = null; for (const file of files) { try { const data = JSON.parse(fs_1.default.readFileSync(path_1.default.join(configDir, file), 'utf8')); if (data.apiServerUrl === serverUrl && data.accessToken === accessToken) { userCredentials = data; break; } } catch (e) { // Skip invalid files } } if (!userCredentials) { return { success: false, error: 'Could not find stored credentials' }; } // Create new configuration with the access token const configuration = new admin_1.Configuration({ basePath: serverUrl, accessToken: accessToken, }); const authApi = new admin_1.AuthApi(configuration); // Try to re-authenticate using the stored Google OAuth token const response = yield authApi.authControllerOAuthLogin({ providerId: accessToken, type: admin_1.OAuthLoginRequestDTOTypeEnum.Google, email: userCredentials.email, profilePictureUrl: userCredentials.picture || '', }); const newToken = response.data.token; // Update the stored credentials with the new token const fileName = `${userCredentials.email.replace('@', '_at_')}_${userCredentials.domain}.json`; const filePath = path_1.default.join(configDir, fileName); userCredentials.token = newToken; userCredentials.timestamp = new Date().toISOString(); fs_1.default.writeFileSync(filePath, JSON.stringify(userCredentials, null, 2)); return { success: true, newToken }; } catch (error) { console.error(chalk_1.default.yellow('Token refresh failed:'), error.message); return { success: false, error: error.message }; } }); } /** * Enhanced 401 error handler with automatic token refresh */ function handle401Error(error, retryCallback) { return __awaiter(this, void 0, void 0, function* () { if (error.response && error.response.status === 401) { // Get current auth token info const authInfo = (0, auth_1.getAuthToken)(); if (!authInfo || !authInfo.accessToken) { throw new Error('Authentication token has expired. Please login again using "nestbox login <domain>".'); } console.log(chalk_1.default.yellow('Authentication token expired. Attempting to refresh...')); // Try to refresh the token const refreshResult = yield refreshAuthToken(authInfo.serverUrl, authInfo.accessToken); if (refreshResult.success && retryCallback) { console.log(chalk_1.default.green('Token refreshed successfully. Retrying request...')); try { // Retry the original request with the new token const result = yield retryCallback(); return { success: true, data: result }; } catch (retryError) { // If retry also fails with 401, the refresh didn't work properly if (retryError.response && retryError.response.status === 401) { throw new Error('Authentication failed after token refresh. Please login again using "nestbox login <domain>".'); } // Re-throw other errors throw retryError; } } else { // Refresh failed throw new Error('Authentication token has expired and automatic refresh failed. Please login again using "nestbox login <domain>".'); } } return null; }); } /** * Wrapper function to make API calls with automatic retry on 401 */ function withTokenRefresh(apiCall, onRetry) { return __awaiter(this, void 0, void 0, function* () { try { return yield apiCall(); } catch (error) { if (error.response && error.response.status === 401) { // Get current auth token info const authInfo = (0, auth_1.getAuthToken)(); if (!authInfo || !authInfo.accessToken) { throw new Error('Authentication token has expired. Please login again using "nestbox login <domain>".'); } console.log(chalk_1.default.yellow('Authentication token expired. Attempting to refresh...')); // Try to refresh the token const refreshResult = yield refreshAuthToken(authInfo.serverUrl, authInfo.accessToken); if (refreshResult.success) { console.log(chalk_1.default.green('Token refreshed successfully. Retrying request...')); // If onRetry callback is provided, call it to reinitialize API clients if (onRetry) { onRetry(); } try { // Retry the original API call return yield apiCall(); } catch (retryError) { // If retry also fails with 401, the refresh didn't work properly if (retryError.response && retryError.response.status === 401) { throw new Error('Authentication failed after token refresh. Please login again using "nestbox login <domain>".'); } // Re-throw other errors throw retryError; } } else { // Refresh failed throw new Error('Authentication token has expired and automatic refresh failed. Please login again using "nestbox login <domain>".'); } } // If not a 401 error, re-throw throw error; } }); } //# sourceMappingURL=error.js.map