incize
Version:
AI Commit Copilot for Power Developers
240 lines (239 loc) • 8.37 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CLIAuthService = void 0;
const ConfigManager_1 = require("../config/ConfigManager");
const CLIOutputRenderer_1 = require("../output/CLIOutputRenderer");
const chalk_1 = __importDefault(require("chalk"));
const ora_1 = __importDefault(require("ora"));
const readline_1 = __importDefault(require("readline"));
class CLIAuthService {
configManager;
outputRenderer;
API_BASE_URL = 'https://incize.dev/api';
constructor() {
this.configManager = new ConfigManager_1.ConfigManager();
this.outputRenderer = new CLIOutputRenderer_1.CLIOutputRenderer();
}
/**
* Authenticate user with email/password or magic link
*/
async login(email) {
const spinner = (0, ora_1.default)('Authenticating with Incize...').start();
try {
// Get email if not provided
if (!email) {
email = await this.promptForEmail();
}
// Validate email format
if (!this.isValidEmail(email)) {
spinner.fail('Invalid email format');
return false;
}
// Check if already authenticated
const currentAuth = await this.getAuthStatus();
if (currentAuth.authenticated) {
spinner.info('Already authenticated');
this.outputRenderer.renderAuthStatus(currentAuth);
return true;
}
// Send authentication request
const response = await this.sendAuthRequest(email);
if (response.success && response.apiKey && response.user) {
// Store authentication data
await this.configManager.setAuthConfig({
apiKey: response.apiKey,
userId: response.user.userId,
subscriptionTier: response.user.subscriptionTier,
preferences: response.user.preferences,
lastLogin: new Date().toISOString()
});
spinner.succeed('Authentication successful!');
this.outputRenderer.renderSuccess('Welcome to Incize! You are now authenticated.');
// Show user info
this.outputRenderer.renderUserInfo(response.user);
return true;
}
else {
spinner.fail(response.error || 'Authentication failed');
return false;
}
}
catch (error) {
spinner.fail('Authentication failed');
console.error(chalk_1.default.red('Error:'), error instanceof Error ? error.message : 'Unknown error');
return false;
}
}
/**
* Logout user and clear local authentication
*/
async logout() {
const spinner = (0, ora_1.default)('Logging out...').start();
try {
const authConfig = await this.configManager.getAuthConfig();
if (!authConfig) {
spinner.info('Not currently authenticated');
return true;
}
// Send logout request to server
await this.sendLogoutRequest(authConfig.apiKey);
// Clear local authentication
await this.configManager.clearAuthConfig();
spinner.succeed('Logged out successfully');
this.outputRenderer.renderSuccess('You have been logged out of Incize.');
return true;
}
catch (error) {
spinner.fail('Logout failed');
console.error(chalk_1.default.red('Error:'), error instanceof Error ? error.message : 'Unknown error');
return false;
}
}
/**
* Get current authentication status
*/
async getAuthStatus() {
try {
const authConfig = await this.configManager.getAuthConfig();
if (!authConfig || !authConfig.apiKey) {
return { authenticated: false, user: null };
}
// Validate token with server
const user = await this.validateToken(authConfig.apiKey);
if (user) {
return { authenticated: true, user };
}
else {
// Clear invalid auth
await this.configManager.clearAuthConfig();
return { authenticated: false, user: null };
}
}
catch (error) {
return { authenticated: false, user: null };
}
}
/**
* Get API key for authenticated requests
*/
async getApiKey() {
const authConfig = await this.configManager.getAuthConfig();
return authConfig?.apiKey || null;
}
/**
* Send authenticated request to API
*/
async sendAuthenticatedRequest(endpoint, options = {}) {
const apiKey = await this.getApiKey();
if (!apiKey) {
throw new Error('Not authenticated. Run `incize auth login` first.');
}
const response = await fetch(`${this.API_BASE_URL}${endpoint}`, {
...options,
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json',
...options.headers
}
});
if (!response.ok) {
if (response.status === 401) {
// Clear invalid auth
await this.configManager.clearAuthConfig();
throw new Error('Authentication expired. Please login again.');
}
throw new Error(`API request failed: ${response.statusText}`);
}
return response.json();
}
/**
* Send commit analysis to web dashboard
*/
async sendCommitAnalysis(analysis) {
try {
await this.sendAuthenticatedRequest('/commits', {
method: 'POST',
body: JSON.stringify(analysis)
});
return true;
}
catch (error) {
console.error(chalk_1.default.yellow('Warning: Could not sync to dashboard:'), error instanceof Error ? error.message : 'Unknown error');
return false;
}
}
/**
* Prompt user for email
*/
async promptForEmail() {
const rl = readline_1.default.createInterface({
input: process.stdin,
output: process.stdout
});
return new Promise((resolve) => {
rl.question(chalk_1.default.blue('Enter your email: '), (email) => {
rl.close();
resolve(email.trim());
});
});
}
/**
* Validate email format
*/
isValidEmail(email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
/**
* Send authentication request to server
*/
async sendAuthRequest(email) {
const response = await fetch(`${this.API_BASE_URL}/auth/cli`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ email })
});
if (!response.ok) {
throw new Error(`Authentication request failed: ${response.statusText}`);
}
return response.json();
}
/**
* Send logout request to server
*/
async sendLogoutRequest(apiKey) {
await fetch(`${this.API_BASE_URL}/auth/logout`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
}
});
}
/**
* Validate token with server
*/
async validateToken(apiKey) {
try {
const response = await fetch(`${this.API_BASE_URL}/auth/validate`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${apiKey}`
}
});
if (response.ok) {
return response.json();
}
return null;
}
catch (error) {
return null;
}
}
}
exports.CLIAuthService = CLIAuthService;