Spaces:
Running
Running
import { Injectable } from '@angular/core'; | |
import { HttpClient, HttpHeaders } from '@angular/common/http'; | |
import { Observable, throwError } from 'rxjs'; | |
import { catchError, tap } from 'rxjs/operators'; | |
import { Router } from '@angular/router'; | |
import { AuthService } from './auth.service'; | |
// Interfaces | |
export interface Environment { | |
work_mode: string; | |
cloud_token: string; | |
spark_endpoint: string; | |
} | |
export interface API { | |
name: string; | |
url: string; | |
method: string; | |
headers?: any; | |
body_template?: any; | |
timeout_seconds: number; | |
retry?: { | |
retry_count: number; | |
backoff_seconds: number; | |
strategy: string; | |
}; | |
auth?: { | |
enabled: boolean; | |
token_endpoint?: string; | |
response_token_path?: string; | |
token_request_body?: any; | |
token_refresh_endpoint?: string; | |
token_refresh_body?: any; | |
}; | |
response_prompt?: string; | |
deleted?: boolean; | |
last_update_date?: string; | |
last_update_user?: string; | |
} | |
export interface Version { | |
id: number; | |
version_number: number; | |
caption: string; | |
published: boolean; | |
general_prompt?: string; | |
llm?: any; | |
intents?: any[]; | |
created_date?: string; | |
published_by?: string; | |
publish_date?: string; | |
last_update_date?: string; | |
last_update_user?: string; | |
} | |
export interface Project { | |
id: number; | |
name: string; | |
caption: string; | |
enabled: boolean; | |
versions: Version[]; | |
last_update_date?: string; | |
deleted?: boolean; | |
created_date?: string; | |
created_by?: string; | |
last_update_user?: string; | |
} | |
({ | |
providedIn: 'root' | |
}) | |
export class ApiService { | |
private apiUrl = '/api'; | |
constructor( | |
private http: HttpClient, | |
private router: Router, | |
private authService: AuthService | |
) {} | |
// ===================== Auth ===================== | |
login(username: string, password: string): Observable<any> { | |
return this.http.post(`${this.apiUrl}/login`, { username, password }).pipe( | |
tap((response: any) => { | |
this.authService.setToken(response.token); | |
this.authService.setUsername(response.username); | |
}) | |
); | |
} | |
logout(): void { | |
this.authService.logout(); | |
} | |
private getAuthHeaders(): HttpHeaders { | |
const token = this.authService.getToken(); | |
return new HttpHeaders({ | |
'Authorization': `Bearer ${token}`, | |
'Content-Type': 'application/json' | |
}); | |
} | |
// ===================== User ===================== | |
changePassword(currentPassword: string, newPassword: string): Observable<any> { | |
return this.http.post( | |
`${this.apiUrl}/change-password`, | |
{ current_password: currentPassword, new_password: newPassword }, | |
{ headers: this.getAuthHeaders() } | |
).pipe( | |
catchError(this.handleError) | |
); | |
} | |
// ===================== Environment ===================== | |
getEnvironment(): Observable<Environment> { | |
return this.http.get<Environment>(`${this.apiUrl}/environment`, { | |
headers: this.getAuthHeaders() | |
}).pipe( | |
catchError(this.handleError) | |
); | |
} | |
updateEnvironment(data: Environment): Observable<any> { | |
return this.http.put(`${this.apiUrl}/environment`, data, { | |
headers: this.getAuthHeaders() | |
}).pipe( | |
catchError(this.handleError) | |
); | |
} | |
// ===================== Projects ===================== | |
getProjects(includeDeleted = false): Observable<Project[]> { | |
return this.http.get<Project[]>(`${this.apiUrl}/projects`, { | |
headers: this.getAuthHeaders(), | |
params: { include_deleted: includeDeleted.toString() } | |
}).pipe( | |
catchError(this.handleError) | |
); | |
} | |
createProject(data: any): Observable<any> { | |
return this.http.post(`${this.apiUrl}/projects`, data, { | |
headers: this.getAuthHeaders() | |
}).pipe( | |
catchError(this.handleError) | |
); | |
} | |
updateProject(id: number, data: any): Observable<any> { | |
return this.http.put(`${this.apiUrl}/projects/${id}`, data, { | |
headers: this.getAuthHeaders() | |
}).pipe( | |
catchError(this.handleError) | |
); | |
} | |
deleteProject(id: number): Observable<any> { | |
return this.http.delete(`${this.apiUrl}/projects/${id}`, { | |
headers: this.getAuthHeaders() | |
}).pipe( | |
catchError(this.handleError) | |
); | |
} | |
toggleProject(id: number): Observable<any> { | |
return this.http.patch(`${this.apiUrl}/projects/${id}/toggle`, {}, { | |
headers: this.getAuthHeaders() | |
}).pipe( | |
catchError(this.handleError) | |
); | |
} | |
exportProject(id: number): Observable<any> { | |
return this.http.get(`${this.apiUrl}/projects/${id}/export`, { | |
headers: this.getAuthHeaders() | |
}).pipe( | |
catchError(this.handleError) | |
); | |
} | |
importProject(data: any): Observable<any> { | |
return this.http.post(`${this.apiUrl}/projects/import`, data, { | |
headers: this.getAuthHeaders() | |
}).pipe( | |
catchError(this.handleError) | |
); | |
} | |
// ===================== Versions ===================== | |
createVersion(projectId: number, data: any): Observable<any> { | |
return this.http.post(`${this.apiUrl}/projects/${projectId}/versions`, data, { | |
headers: this.getAuthHeaders() | |
}).pipe( | |
catchError(this.handleError) | |
); | |
} | |
updateVersion(projectId: number, versionId: number, data: any, force: boolean = false): Observable<any> { | |
return this.http.put( | |
`${this.apiUrl}/projects/${projectId}/versions/${versionId}${force ? '?force=true' : ''}`, | |
data, | |
{ headers: this.getAuthHeaders() } | |
).pipe( | |
catchError(this.handleError) | |
); | |
} | |
deleteVersion(projectId: number, versionId: number): Observable<any> { | |
return this.http.delete(`${this.apiUrl}/projects/${projectId}/versions/${versionId}`, { | |
headers: this.getAuthHeaders() | |
}).pipe( | |
catchError(this.handleError) | |
); | |
} | |
publishVersion(projectId: number, versionId: number): Observable<any> { | |
return this.http.post(`${this.apiUrl}/projects/${projectId}/versions/${versionId}/publish`, {}, { | |
headers: this.getAuthHeaders() | |
}).pipe( | |
catchError(this.handleError) | |
); | |
} | |
// ===================== APIs ===================== | |
getAPIs(includeDeleted = false): Observable<API[]> { | |
return this.http.get<API[]>(`${this.apiUrl}/apis`, { | |
headers: this.getAuthHeaders(), | |
params: { include_deleted: includeDeleted.toString() } | |
}).pipe( | |
catchError(this.handleError) | |
); | |
} | |
createAPI(data: any): Observable<any> { | |
return this.http.post(`${this.apiUrl}/apis`, data, { | |
headers: this.getAuthHeaders() | |
}).pipe( | |
catchError(this.handleError) | |
); | |
} | |
updateAPI(name: string, data: any): Observable<any> { | |
return this.http.put(`${this.apiUrl}/apis/${name}`, data, { | |
headers: this.getAuthHeaders() | |
}).pipe( | |
catchError(this.handleError) | |
); | |
} | |
deleteAPI(name: string): Observable<any> { | |
return this.http.delete(`${this.apiUrl}/apis/${name}`, { | |
headers: this.getAuthHeaders() | |
}).pipe( | |
catchError(this.handleError) | |
); | |
} | |
testAPI(data: any): Observable<any> { | |
return this.http.post(`${this.apiUrl}/apis/test`, data, { | |
headers: this.getAuthHeaders() | |
}).pipe( | |
catchError(this.handleError) | |
); | |
} | |
// ===================== Tests ===================== | |
runTests(testType: string): Observable<any> { | |
return this.http.post(`${this.apiUrl}/test/run-all`, { test_type: testType }, { | |
headers: this.getAuthHeaders() | |
}).pipe( | |
catchError(this.handleError) | |
); | |
} | |
// ===================== Activity Log ===================== | |
getActivityLog(limit = 50): Observable<any[]> { | |
return this.http.get<any[]>(`${this.apiUrl}/activity-log`, { | |
headers: this.getAuthHeaders(), | |
params: { limit: limit.toString() } | |
}).pipe( | |
catchError(this.handleError) | |
); | |
} | |
// ===================== Validation ===================== | |
validateRegex(pattern: string, testValue: string): Observable<any> { | |
return this.http.post(`${this.apiUrl}/validate/regex`, | |
{ pattern, test_value: testValue }, | |
{ headers: this.getAuthHeaders() } | |
).pipe( | |
catchError(this.handleError) | |
); | |
} | |
// ===================== Error Handler ===================== | |
// ===================== Error Handler ===================== | |
private handleError(error: any) { | |
console.error('API Error:', error); | |
if (error.status === 401) { | |
// Token expired or invalid | |
this.authService.logout(); | |
} else if (error.status === 409) { | |
// Race condition error - add specific handling | |
const message = error.error?.detail || 'Resource was modified by another user'; | |
// Create a more user-friendly error object | |
return throwError(() => ({ | |
...error, | |
userMessage: message, | |
requiresReload: true | |
})); | |
} | |
return throwError(() => error.error || error); | |
} | |
} |