@taruvi/sdk 1.3.2 → 1.3.4-beta.0

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.
Files changed (63) hide show
  1. package/.kiro/settings/lsp.json +198 -0
  2. package/MODULE_NAMING_CHANGES.md +81 -0
  3. package/PARAMETER_NAMING_CHANGES.md +106 -0
  4. package/README.md +4 -4
  5. package/package.json +10 -4
  6. package/src/client.ts +4 -4
  7. package/src/index.ts +48 -35
  8. package/src/lib/analytics/types.ts +8 -0
  9. package/src/lib/{App → app}/types.ts +14 -6
  10. package/src/lib/auth/AuthClient.ts +8 -7
  11. package/src/lib/auth/types.ts +108 -6
  12. package/src/lib/{Database → database}/DatabaseClient.ts +15 -10
  13. package/src/lib/{Database → database}/types.ts +4 -7
  14. package/src/lib/functions/types.ts +25 -0
  15. package/src/lib/{Graphs → graphs}/GraphClient.ts +9 -8
  16. package/src/lib/{Graphs → graphs}/types.ts +12 -5
  17. package/src/lib/policy/PolicyClient.ts +79 -0
  18. package/src/lib/policy/types.ts +40 -0
  19. package/src/lib/secrets/SecretsClient.ts +75 -0
  20. package/src/lib/secrets/types.ts +59 -0
  21. package/src/lib/settings/types.ts +9 -0
  22. package/src/lib/{Storage → storage}/StorageClient.ts +27 -9
  23. package/src/lib/storage/types.ts +86 -0
  24. package/src/lib/users/UserClient.ts +55 -0
  25. package/src/lib/users/types.ts +104 -0
  26. package/src/lib-internal/errors/ErrorClient.ts +98 -8
  27. package/src/lib-internal/errors/index.ts +3 -25
  28. package/src/lib-internal/errors/types.ts +18 -95
  29. package/src/lib-internal/http/HttpClient.ts +83 -45
  30. package/src/lib-internal/routes/UserRoutes.ts +3 -1
  31. package/src/lib-internal/token/TokenClient.ts +1 -1
  32. package/src/types.ts +20 -1
  33. package/src/utils/utils.ts +5 -1
  34. package/tests/fixtures/mockClient.ts +19 -0
  35. package/tests/unit/analytics/AnalyticsClient.test.ts +84 -0
  36. package/tests/unit/app/AppClient.test.ts +114 -0
  37. package/tests/unit/auth/AuthClient.test.ts +131 -0
  38. package/tests/unit/client/Client.test.ts +70 -0
  39. package/tests/unit/database/DatabaseClient.test.ts +304 -0
  40. package/tests/unit/edge-cases/robustness.test.ts +259 -0
  41. package/tests/unit/errors/errors.test.ts +209 -0
  42. package/tests/unit/functions/FunctionsClient.test.ts +99 -0
  43. package/tests/unit/graphs/GraphClient.test.ts +329 -0
  44. package/tests/unit/policy/PolicyClient.test.ts +184 -0
  45. package/tests/unit/secrets/SecretsClient.test.ts +146 -0
  46. package/tests/unit/settings/SettingsClient.test.ts +50 -0
  47. package/tests/unit/storage/StorageClient.test.ts +251 -0
  48. package/tests/unit/users/UserClient.test.ts +150 -0
  49. package/vitest.config.ts +7 -0
  50. package/src/lib/Analytics/types.ts +0 -7
  51. package/src/lib/Function/types.ts +0 -17
  52. package/src/lib/Policy/PolicyClient.ts +0 -29
  53. package/src/lib/Policy/types.ts +0 -24
  54. package/src/lib/Secrets/SecretsClient.ts +0 -39
  55. package/src/lib/Secrets/types.ts +0 -17
  56. package/src/lib/Settings/types.ts +0 -4
  57. package/src/lib/Storage/types.ts +0 -41
  58. package/src/lib/user/UserClient.ts +0 -52
  59. package/src/lib/user/types.ts +0 -111
  60. /package/src/lib/{Analytics → analytics}/AnalyticsClient.ts +0 -0
  61. /package/src/lib/{App → app}/AppClient.ts +0 -0
  62. /package/src/lib/{Function → functions}/FunctionsClient.ts +0 -0
  63. /package/src/lib/{Settings → settings}/SettingsClient.ts +0 -0
@@ -0,0 +1,86 @@
1
+ import type { TaruviResponse } from "../../types.js"
2
+
3
+ // Internal types - all optional since they're built incrementally via builder pattern
4
+ export interface BucketUrlParams {
5
+ appSlug?: string
6
+ bucket?: string
7
+ path?: string
8
+ upload?: string
9
+ delete?: string
10
+ }
11
+
12
+ export interface BucketFileUpload {
13
+ files: []
14
+ path: string
15
+ metadata?: Record<string, unknown>
16
+ }
17
+
18
+ // Request types
19
+ export interface StorageRequest {
20
+ files: File[]
21
+ paths: string[]
22
+ metadatas: object[]
23
+ }
24
+
25
+ export interface StorageUpdateRequest {
26
+ metadata?: Record<string, unknown>
27
+ visibility?: 'public' | 'private'
28
+ }
29
+
30
+ // Storage object - matches StorageObjectSerializer from API
31
+ export interface StorageObject {
32
+ id: number
33
+ uuid: string
34
+ bucket?: number
35
+ bucket_slug?: string
36
+ bucket_name?: string
37
+ filename: string
38
+ file_path: string
39
+ file_url: string
40
+ size: number
41
+ mimetype: string
42
+ metadata?: Record<string, unknown>
43
+ visibility?: string
44
+ created_at: string
45
+ updated_at: string
46
+ created_by?: number
47
+ modified_by?: number
48
+ }
49
+
50
+ // Response types - uses standard wrapper
51
+ export type StorageResponse = TaruviResponse<StorageObject>
52
+ export type StorageListResponse = TaruviResponse<StorageObject[]>
53
+
54
+ // Batch upload response
55
+ export interface StorageUploadBatchResponse {
56
+ status: "success" | "error"
57
+ message: string
58
+ data: {
59
+ uploaded_count: number
60
+ failed_count: number
61
+ total: number
62
+ successful: Array<{
63
+ index: number
64
+ path: string
65
+ object: StorageObject
66
+ }>
67
+ failed: Array<{
68
+ index: number
69
+ path: string
70
+ error: string
71
+ }>
72
+ }
73
+ }
74
+
75
+ // Batch delete response
76
+ export interface StorageDeleteBatchResponse {
77
+ status: "success" | "error"
78
+ message: string
79
+ data: {
80
+ deleted_count: number
81
+ failed: Array<{
82
+ path: string
83
+ error: string
84
+ }>
85
+ }
86
+ }
@@ -0,0 +1,55 @@
1
+ import type { Client } from "../../client.js";
2
+ import type { UserCreateRequest, UserResponse, UserListResponse, UserListFilters, UserUpdateRequest, UserAppsResponse, AssignRolesRequest, RevokeRolesRequest, RolesResponse } from "./types.js";
3
+ import { UserRoutes } from "../../lib-internal/routes/UserRoutes.js";
4
+ import { buildQueryString } from "../../utils/utils.js";
5
+
6
+
7
+ export class User {
8
+ private client: Client
9
+
10
+ constructor(client: Client) {
11
+ this.client = client
12
+ }
13
+
14
+ async updateUser(username: string, body: UserUpdateRequest): Promise<UserResponse> {
15
+ return await this.client.httpClient.put(UserRoutes.updateUser(username), body)
16
+ }
17
+
18
+ async getUser(username: string): Promise<UserResponse> {
19
+ return await this.client.httpClient.get<UserResponse>(UserRoutes.getUser(username))
20
+ }
21
+
22
+ async list(filters?: UserListFilters): Promise<UserListResponse> {
23
+ const queryString = buildQueryString(filters as unknown as Record<string, unknown>)
24
+ return await this.client.httpClient.get<UserListResponse>(UserRoutes.listUser(queryString))
25
+ }
26
+
27
+ async getUserApps(username: string): Promise<UserAppsResponse> {
28
+ return await this.client.httpClient.get<UserAppsResponse>(UserRoutes.getUserApps(username))
29
+ }
30
+
31
+ async createUser(userData: UserCreateRequest): Promise<UserResponse> {
32
+ return await this.client.httpClient.post<UserResponse, UserCreateRequest>(
33
+ UserRoutes.baseUrl,
34
+ userData
35
+ )
36
+ }
37
+
38
+ async deleteUser(username: string): Promise<void> {
39
+ return await this.client.httpClient.delete(UserRoutes.deleteUser(username))
40
+ }
41
+
42
+ async assignRoles(request: AssignRolesRequest): Promise<RolesResponse> {
43
+ return await this.client.httpClient.post<RolesResponse, AssignRolesRequest>(
44
+ UserRoutes.assignRoles(),
45
+ request
46
+ )
47
+ }
48
+
49
+ async revokeRoles(request: RevokeRolesRequest): Promise<RolesResponse> {
50
+ return await this.client.httpClient.delete<RolesResponse>(
51
+ UserRoutes.revokeRoles(),
52
+ request
53
+ )
54
+ }
55
+ }
@@ -0,0 +1,104 @@
1
+ import type { TaruviResponse } from "../../types.js"
2
+
3
+ export interface UserCreateRequest {
4
+ username: string
5
+ email: string
6
+ password: string
7
+ confirm_password: string
8
+ first_name: string
9
+ last_name: string
10
+ is_active?: boolean
11
+ is_staff?: boolean
12
+ is_cloud_user?: boolean
13
+ attributes?: Record<string, unknown>
14
+ role_slugs?: string[]
15
+ }
16
+
17
+ export interface UserData {
18
+ id: number
19
+ uuid?: string
20
+ username: string
21
+ email: string
22
+ first_name: string
23
+ last_name: string
24
+ full_name?: string
25
+ is_active: boolean
26
+ is_staff: boolean
27
+ is_superuser?: boolean
28
+ is_deleted: boolean
29
+ date_joined: string
30
+ last_login?: string
31
+ groups?: UserGroup[]
32
+ user_permissions?: UserPermission[]
33
+ attributes?: Record<string, unknown>
34
+ missing_attributes?: string[]
35
+ roles?: UserRole[]
36
+ }
37
+
38
+ export interface UserGroup {
39
+ id: number
40
+ name: string
41
+ }
42
+
43
+ export interface UserPermission {
44
+ id: number
45
+ name: string
46
+ codename: string
47
+ content_type: string
48
+ }
49
+
50
+ export interface UserRole {
51
+ name: string
52
+ slug: string
53
+ type: string
54
+ app_slug: string
55
+ source: "direct" | "site_role" | "inherited"
56
+ }
57
+
58
+ export interface UserUpdateRequest {
59
+ username?: string
60
+ email?: string
61
+ first_name?: string
62
+ last_name?: string
63
+ is_active?: boolean
64
+ is_staff?: boolean
65
+ }
66
+
67
+ export interface UserListFilters {
68
+ search?: string
69
+ is_active?: boolean
70
+ is_staff?: boolean
71
+ is_superuser?: boolean
72
+ is_deleted?: boolean
73
+ ordering?: string
74
+ page?: number
75
+ page_size?: number
76
+ }
77
+
78
+ export interface UserApp {
79
+ name: string
80
+ slug: string
81
+ icon: string
82
+ url: string
83
+ display_name: string
84
+ }
85
+
86
+ // Response types - uses standard wrapper
87
+ export type UserResponse = TaruviResponse<UserData>
88
+ export type UserListResponse = TaruviResponse<UserData[]>
89
+ export type UserAppsResponse = TaruviResponse<UserApp[]>
90
+
91
+ export interface AssignRolesRequest {
92
+ roles: string[]
93
+ usernames: string[]
94
+ expires_at?: string
95
+ }
96
+
97
+ export interface RevokeRolesRequest {
98
+ roles: string[]
99
+ usernames: string[]
100
+ }
101
+
102
+ export type RolesResponse = TaruviResponse<{
103
+ count: number
104
+ }>
@@ -1,12 +1,102 @@
1
- export class ErrorClient {
1
+ import { ErrorCode, type ErrorResponseBody } from './types.js'
2
2
 
3
- constructor() {
4
- // No dependencies needed for now
3
+ /**
4
+ * Base SDK error. All typed errors extend this.
5
+ */
6
+ export class TaruviError extends Error {
7
+ public readonly code: string
8
+ public readonly statusCode: number
9
+ public readonly detail: string | undefined
10
+ public readonly errors: Record<string, unknown> | undefined
11
+ public readonly data: unknown
12
+
13
+ constructor(message: string, statusCode: number, code: string = ErrorCode.INTERNAL_ERROR, detail?: string, errors?: Record<string, unknown>, data?: unknown) {
14
+ super(message)
15
+ this.name = 'TaruviError'
16
+ this.statusCode = statusCode
17
+ this.code = code
18
+ this.detail = detail
19
+ this.errors = errors
20
+ this.data = data
5
21
  }
22
+ }
6
23
 
7
- // TODO: Implement error handling
8
- // - handleError
9
- // - logError
10
- // - formatError
11
- // - Custom error classes (AuthError, NetworkError, etc.)
24
+ export class ValidationError extends TaruviError {
25
+ constructor(message = 'Validation failed', detail?: string, errors?: Record<string, unknown>) {
26
+ super(message, 400, ErrorCode.VALIDATION_ERROR, detail, errors)
27
+ this.name = 'ValidationError'
28
+ }
29
+ }
30
+
31
+ export class AuthError extends TaruviError {
32
+ constructor(message = 'Authentication required') {
33
+ super(message, 401, ErrorCode.UNAUTHORIZED)
34
+ this.name = 'AuthError'
35
+ }
36
+ }
37
+
38
+ export class ForbiddenError extends TaruviError {
39
+ constructor(message = 'Permission denied') {
40
+ super(message, 403, ErrorCode.FORBIDDEN)
41
+ this.name = 'ForbiddenError'
42
+ }
43
+ }
44
+
45
+ export class NotFoundError extends TaruviError {
46
+ constructor(message = 'Resource not found') {
47
+ super(message, 404, ErrorCode.NOT_FOUND)
48
+ this.name = 'NotFoundError'
49
+ }
50
+ }
51
+
52
+ export class ConflictError extends TaruviError {
53
+ constructor(message = 'Resource conflict', detail?: string) {
54
+ super(message, 409, ErrorCode.CONFLICT, detail)
55
+ this.name = 'ConflictError'
56
+ }
57
+ }
58
+
59
+ export class TimeoutError extends TaruviError {
60
+ constructor(message = 'Request timeout') {
61
+ super(message, 504, ErrorCode.GATEWAY_TIMEOUT)
62
+ this.name = 'TimeoutError'
63
+ }
64
+ }
65
+
66
+ export class NetworkError extends TaruviError {
67
+ constructor(message = 'Network error') {
68
+ super(message, 0, ErrorCode.NETWORK_ERROR)
69
+ this.name = 'NetworkError'
70
+ }
71
+ }
72
+
73
+ /**
74
+ * Maps HTTP status + response body to the appropriate typed error.
75
+ */
76
+ export function createErrorFromResponse(statusCode: number, body?: ErrorResponseBody): TaruviError {
77
+ const message = body?.message || 'Request failed'
78
+ const code = body?.code || ErrorCode.INTERNAL_ERROR
79
+ const detail = body?.detail
80
+ const errors = body?.errors
81
+ const data = body?.data
82
+
83
+ switch (statusCode) {
84
+ case 400:
85
+ if (code === ErrorCode.VALIDATION_ERROR) {
86
+ return new ValidationError(message, detail, errors)
87
+ }
88
+ return new TaruviError(message, 400, code, detail, errors, data)
89
+ case 401:
90
+ return new AuthError(message)
91
+ case 403:
92
+ return new ForbiddenError(message)
93
+ case 404:
94
+ return new NotFoundError(message)
95
+ case 409:
96
+ return new ConflictError(message, detail)
97
+ case 504:
98
+ return new TimeoutError(message)
99
+ default:
100
+ return new TaruviError(message, statusCode, code, detail, errors, data)
101
+ }
12
102
  }
@@ -1,25 +1,3 @@
1
- /**
2
- * Error handling module exports
3
- *
4
- * This module provides comprehensive error handling for the Taruvi SDK
5
- * including typed error classes, error codes, and utility functions.
6
- */
7
-
8
- // Export error client
9
- export { ErrorClient } from './ErrorClient.js';
10
-
11
- // TODO: Export all error classes when implemented
12
- // - TaruviError
13
- // - AuthError
14
- // - DatabaseError
15
- // - StorageError
16
- // - NetworkError
17
- // - ValidationError
18
- // - FunctionError
19
-
20
- // TODO: Export types when implemented
21
- // - ErrorCode
22
- // - ErrorSeverity
23
- // - ErrorResponse
24
- // - HttpErrorResponse
25
- // - ValidationErrorDetail
1
+ export { TaruviError, ValidationError, AuthError, ForbiddenError, NotFoundError, ConflictError, TimeoutError, NetworkError, createErrorFromResponse } from './ErrorClient.js'
2
+ export { ErrorCode } from './types.js'
3
+ export type { ErrorResponseBody } from './types.js'
@@ -1,105 +1,28 @@
1
1
  /**
2
- * Error severity levels for categorizing errors
3
- */
4
- export enum ErrorSeverity {
5
- LOW = 'low',
6
- MEDIUM = 'medium',
7
- HIGH = 'high',
8
- CRITICAL = 'critical'
9
- }
10
-
11
- /**
12
- * Standard error codes used across the SDK
2
+ * Error codes matching the backend's ErrorCode enum.
3
+ * Maps 1:1 with base.responses.error_codes.ErrorCode in Python.
13
4
  */
14
5
  export enum ErrorCode {
15
- // General errors (1000-1099)
16
- UNKNOWN_ERROR = 'UNKNOWN_ERROR',
17
- INTERNAL_ERROR = 'INTERNAL_ERROR',
18
- TIMEOUT_ERROR = 'TIMEOUT_ERROR',
19
-
20
- // Network errors (1100-1199)
21
- NETWORK_ERROR = 'NETWORK_ERROR',
22
- CONNECTION_ERROR = 'CONNECTION_ERROR',
23
- REQUEST_FAILED = 'REQUEST_FAILED',
24
-
25
- // Authentication errors (1200-1299)
26
- AUTH_ERROR = 'AUTH_ERROR',
6
+ BAD_REQUEST = 'BAD_REQUEST',
7
+ VALIDATION_ERROR = 'VALIDATION_ERROR',
27
8
  UNAUTHORIZED = 'UNAUTHORIZED',
28
- TOKEN_EXPIRED = 'TOKEN_EXPIRED',
29
- TOKEN_INVALID = 'TOKEN_INVALID',
30
- SESSION_EXPIRED = 'SESSION_EXPIRED',
31
- INVALID_CREDENTIALS = 'INVALID_CREDENTIALS',
32
-
33
- // Authorization errors (1300-1399)
34
9
  FORBIDDEN = 'FORBIDDEN',
35
- INSUFFICIENT_PERMISSIONS = 'INSUFFICIENT_PERMISSIONS',
36
-
37
- // Validation errors (1400-1499)
38
- VALIDATION_ERROR = 'VALIDATION_ERROR',
39
- INVALID_INPUT = 'INVALID_INPUT',
40
- MISSING_REQUIRED_FIELD = 'MISSING_REQUIRED_FIELD',
41
- INVALID_FORMAT = 'INVALID_FORMAT',
42
-
43
- // Database errors (1500-1599)
44
- DATABASE_ERROR = 'DATABASE_ERROR',
45
- QUERY_FAILED = 'QUERY_FAILED',
46
- RECORD_NOT_FOUND = 'RECORD_NOT_FOUND',
47
- DUPLICATE_ENTRY = 'DUPLICATE_ENTRY',
48
- CONSTRAINT_VIOLATION = 'CONSTRAINT_VIOLATION',
49
-
50
- // Storage errors (1600-1699)
51
- STORAGE_ERROR = 'STORAGE_ERROR',
52
- FILE_NOT_FOUND = 'FILE_NOT_FOUND',
53
- FILE_TOO_LARGE = 'FILE_TOO_LARGE',
54
- INVALID_FILE_TYPE = 'INVALID_FILE_TYPE',
55
- UPLOAD_FAILED = 'UPLOAD_FAILED',
56
- DOWNLOAD_FAILED = 'DOWNLOAD_FAILED',
57
-
58
- // Function errors (1700-1799)
59
- FUNCTION_ERROR = 'FUNCTION_ERROR',
60
- FUNCTION_NOT_FOUND = 'FUNCTION_NOT_FOUND',
61
- FUNCTION_EXECUTION_FAILED = 'FUNCTION_EXECUTION_FAILED',
62
- FUNCTION_TIMEOUT = 'FUNCTION_TIMEOUT',
63
-
64
- // Rate limiting errors (1800-1899)
65
- RATE_LIMIT_EXCEEDED = 'RATE_LIMIT_EXCEEDED',
66
- QUOTA_EXCEEDED = 'QUOTA_EXCEEDED',
67
-
68
- // Client errors (1900-1999)
69
- CONFIGURATION_ERROR = 'CONFIGURATION_ERROR',
70
- INVALID_API_KEY = 'INVALID_API_KEY',
71
- INVALID_CONFIG = 'INVALID_CONFIG'
72
- }
73
-
74
- /**
75
- * Base error response structure
76
- */
77
- export interface ErrorResponse {
78
- code: ErrorCode;
79
- message: string;
80
- severity: ErrorSeverity;
81
- timestamp: string;
82
- requestId?: string | undefined;
83
- metadata?: Record<string, any> | undefined;
84
- cause?: Error | undefined;
85
- }
86
-
87
- /**
88
- * HTTP error response from the server
89
- */
90
- export interface HttpErrorResponse {
91
- status: number;
92
- statusText: string;
93
- message?: string;
94
- code?: string;
95
- details?: any;
10
+ NOT_FOUND = 'NOT_FOUND',
11
+ CONFLICT = 'CONFLICT',
12
+ INTERNAL_ERROR = 'INTERNAL_ERROR',
13
+ GATEWAY_TIMEOUT = 'GATEWAY_TIMEOUT',
14
+ NETWORK_ERROR = 'NETWORK_ERROR'
96
15
  }
97
16
 
98
17
  /**
99
- * Validation error details
18
+ * Backend error response shape.
19
+ * Matches AppException.to_dict() output.
100
20
  */
101
- export interface ValidationErrorDetail {
102
- field: string;
103
- message: string;
104
- value?: any;
21
+ export interface ErrorResponseBody {
22
+ status: 'error'
23
+ code: string
24
+ message: string
25
+ detail?: string
26
+ errors?: Record<string, unknown>
27
+ data?: unknown
105
28
  }
@@ -1,12 +1,13 @@
1
1
  import type { TaruviConfig } from "../../types.js";
2
2
  import type { TokenClient } from "../token/TokenClient.js";
3
- import axios from "axios";
3
+ import axios, { AxiosError } from "axios";
4
+ import { createErrorFromResponse, NetworkError, TaruviError } from "../errors/index.js";
5
+ import type { ErrorResponseBody } from "../errors/index.js";
4
6
 
5
7
  /**
6
8
  * HttpClient handles all HTTP requests to the Taruvi API.
7
- * Automatically adds authentication headers:
8
- * - Authorization: API key for site/app identification
9
- * - X-Session-Token: User session token for authenticated requests
9
+ * Automatically adds authentication headers and converts
10
+ * error responses to typed SDK errors.
10
11
  *
11
12
  * @internal
12
13
  */
@@ -36,56 +37,93 @@ export class HttpClient {
36
37
  return headers
37
38
  }
38
39
 
39
- async get<T>(endpoint: string): Promise<T> {
40
- const { data } = await axios.get<T>(`${this.config.baseUrl}/${endpoint}`, {
41
- headers: this.getAuthHeaders()
42
- })
43
- return data
44
- }
40
+ private handleError(error: unknown): never {
41
+ if (error instanceof TaruviError) {
42
+ throw error
43
+ }
45
44
 
46
- async post<T, D = any>(endpoint: string, body: D): Promise<T> {
47
- const isFormData = body instanceof FormData
48
- const { data } = await axios.post<T>(
49
- `${this.config.baseUrl}/${endpoint}`,
50
- body,
51
- {
52
- headers: this.getAuthHeaders(isFormData)
45
+ if (error instanceof AxiosError) {
46
+ if (error.response) {
47
+ const body = error.response.data as ErrorResponseBody | undefined
48
+ throw createErrorFromResponse(error.response.status, body)
53
49
  }
54
- )
55
- return data
50
+ // No response — network error
51
+ throw new NetworkError(error.message)
52
+ }
53
+
54
+ // Unknown error
55
+ throw error
56
56
  }
57
57
 
58
- async put<T, D = any>(endpoint: string, body: D) {
59
- const isFormData = body instanceof FormData
60
- const { data } = await axios.put<T>(`${this.config.baseUrl}/${endpoint}`,
61
- body,
62
- {
63
- headers: this.getAuthHeaders(isFormData)
58
+ async get<T>(endpoint: string): Promise<T> {
59
+ try {
60
+ const { data } = await axios.get<T>(`${this.config.apiUrl}/${endpoint}`, {
61
+ headers: this.getAuthHeaders()
64
62
  })
63
+ return data
64
+ } catch (error) {
65
+ this.handleError(error)
66
+ }
67
+ }
65
68
 
66
- return data
69
+ async post<T, D = unknown>(endpoint: string, body: D): Promise<T> {
70
+ try {
71
+ const isFormData = body instanceof FormData
72
+ const { data } = await axios.post<T>(
73
+ `${this.config.apiUrl}/${endpoint}`,
74
+ body,
75
+ {
76
+ headers: this.getAuthHeaders(isFormData)
77
+ }
78
+ )
79
+ return data
80
+ } catch (error) {
81
+ this.handleError(error)
82
+ }
67
83
  }
68
84
 
69
- async delete<T, D = any>(endpoint: string, body?: D): Promise<T> {
70
- const { data } = await axios.delete<T>(
71
- `${this.config.baseUrl}/${endpoint}`,
72
- {
73
- headers: this.getAuthHeaders(),
74
- data: body
75
- }
76
- )
77
- return data
85
+ async put<T, D = unknown>(endpoint: string, body: D): Promise<T> {
86
+ try {
87
+ const isFormData = body instanceof FormData
88
+ const { data } = await axios.put<T>(`${this.config.apiUrl}/${endpoint}`,
89
+ body,
90
+ {
91
+ headers: this.getAuthHeaders(isFormData)
92
+ })
93
+ return data
94
+ } catch (error) {
95
+ this.handleError(error)
96
+ }
78
97
  }
79
98
 
80
- async patch<T, D = any>(endpoint: string, body: D): Promise<T> {
81
- const isFormData = body instanceof FormData
82
- const { data } = await axios.patch<T>(
83
- `${this.config.baseUrl}/${endpoint}`,
84
- body,
85
- {
86
- headers: this.getAuthHeaders(isFormData)
87
- }
88
- )
89
- return data
99
+ async delete<T, D = unknown>(endpoint: string, body?: D): Promise<T> {
100
+ try {
101
+ const { data } = await axios.delete<T>(
102
+ `${this.config.apiUrl}/${endpoint}`,
103
+ {
104
+ headers: this.getAuthHeaders(),
105
+ data: body
106
+ }
107
+ )
108
+ return data
109
+ } catch (error) {
110
+ this.handleError(error)
111
+ }
112
+ }
113
+
114
+ async patch<T, D = unknown>(endpoint: string, body: D): Promise<T> {
115
+ try {
116
+ const isFormData = body instanceof FormData
117
+ const { data } = await axios.patch<T>(
118
+ `${this.config.apiUrl}/${endpoint}`,
119
+ body,
120
+ {
121
+ headers: this.getAuthHeaders(isFormData)
122
+ }
123
+ )
124
+ return data
125
+ } catch (error) {
126
+ this.handleError(error)
127
+ }
90
128
  }
91
129
  }
@@ -5,5 +5,7 @@ export const UserRoutes = {
5
5
  updateUser: (username: string) => `${UserRoutes.baseUrl}${username}/`,
6
6
  deleteUser: (username: string) => `${UserRoutes.baseUrl}${username}/`,
7
7
  listUser: (filter: string) => `${UserRoutes.baseUrl}${filter}`,
8
- getUserApps: (username: string) => `${UserRoutes.baseUrl}${username}/apps/`
8
+ getUserApps: (username: string) => `${UserRoutes.baseUrl}${username}/apps/`,
9
+ assignRoles: () => `api/assign/roles/`,
10
+ revokeRoles: () => `api/revoke/roles/`
9
11
  } as const
@@ -115,7 +115,7 @@ export class TokenClient {
115
115
  return null
116
116
  }
117
117
 
118
- const tokens: any = {
118
+ const tokens: AuthTokens = {
119
119
  accessToken,
120
120
  refreshToken,
121
121
  tokenType: tokenType || 'Bearer',