@nestbox-ai/cli
Version:
The cli tools that helps developers to build agents
163 lines • 8.03 kB
JavaScript
;
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