@zerosls/clm-sdk 1.0.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.
- package/.docs/publicacion-npm.md +111 -0
- package/.env.example +14 -0
- package/.gitlab-ci.yml +23 -0
- package/README.md +202 -0
- package/dist/config/config.d.ts +3 -0
- package/dist/config/config.js +21 -0
- package/dist/core/api-client.d.ts +27 -0
- package/dist/core/api-client.js +183 -0
- package/dist/core/api-error.d.ts +15 -0
- package/dist/core/api-error.js +46 -0
- package/dist/core/event-emitter.d.ts +11 -0
- package/dist/core/event-emitter.js +32 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.js +59 -0
- package/dist/modules/legacy/areas/areas-api.d.ts +34 -0
- package/dist/modules/legacy/areas/areas-api.js +44 -0
- package/dist/modules/legacy/areas/types.d.ts +37 -0
- package/dist/modules/legacy/areas/types.js +1 -0
- package/dist/modules/legacy/classificationtypes/classificationtypes-api.d.ts +34 -0
- package/dist/modules/legacy/classificationtypes/classificationtypes-api.js +46 -0
- package/dist/modules/legacy/classificationtypes/types.d.ts +41 -0
- package/dist/modules/legacy/classificationtypes/types.js +1 -0
- package/dist/modules/v1/auth/auth-api.d.ts +17 -0
- package/dist/modules/v1/auth/auth-api.js +63 -0
- package/dist/modules/v1/auth/types.d.ts +18 -0
- package/dist/modules/v1/auth/types.js +1 -0
- package/dist/modules/v1/main/main-api.d.ts +11 -0
- package/dist/modules/v1/main/main-api.js +14 -0
- package/dist/modules/v1/main/types.d.ts +3 -0
- package/dist/modules/v1/main/types.js +1 -0
- package/dist/modules/v1/notifications/notification-api.d.ts +16 -0
- package/dist/modules/v1/notifications/notification-api.js +26 -0
- package/dist/modules/v1/notifications/types.d.ts +53 -0
- package/dist/modules/v1/notifications/types.js +1 -0
- package/dist/modules/v1/users/types.d.ts +64 -0
- package/dist/modules/v1/users/types.js +1 -0
- package/dist/modules/v1/users/users-api.d.ts +81 -0
- package/dist/modules/v1/users/users-api.js +113 -0
- package/dist/types/common.d.ts +18 -0
- package/dist/types/common.js +1 -0
- package/dist/types/sdk.d.ts +42 -0
- package/dist/types/sdk.js +11 -0
- package/dist/utils/cache.d.ts +10 -0
- package/dist/utils/cache.js +43 -0
- package/dist/utils/http.d.ts +5 -0
- package/dist/utils/http.js +56 -0
- package/package.json +38 -0
- package/src/config/config.ts +24 -0
- package/src/core/api-client.ts +272 -0
- package/src/core/api-error.ts +54 -0
- package/src/core/event-emitter.ts +43 -0
- package/src/index.ts +89 -0
- package/src/modules/legacy/areas/areas-api.ts +73 -0
- package/src/modules/legacy/areas/types.ts +49 -0
- package/src/modules/legacy/classificationtypes/classificationtypes-api.ts +80 -0
- package/src/modules/legacy/classificationtypes/types.ts +52 -0
- package/src/modules/v1/auth/auth-api.ts +75 -0
- package/src/modules/v1/auth/types.ts +20 -0
- package/src/modules/v1/main/main-api.ts +20 -0
- package/src/modules/v1/main/types.ts +3 -0
- package/src/modules/v1/notifications/notification-api.ts +55 -0
- package/src/modules/v1/notifications/types.ts +58 -0
- package/src/modules/v1/users/types.ts +83 -0
- package/src/modules/v1/users/users-api.ts +148 -0
- package/src/types/common.ts +22 -0
- package/src/types/sdk.ts +38 -0
- package/src/utils/cache.ts +58 -0
- package/src/utils/http.ts +77 -0
- package/tests/integration/legacy/auth-areas.test.ts +115 -0
- package/tests/integration/legacy/auth-classification-types.test.ts +80 -0
- package/tests/integration/v1/auth-logs.test.ts +145 -0
- package/tests/integration/v1/auth-users.test.ts +189 -0
- package/tests/modules/legacy/areas/areas-api.test.ts +232 -0
- package/tests/modules/legacy/classification-types/classification-types-api.test.ts +100 -0
- package/tests/modules/v1/auth/auth-api.test.ts +134 -0
- package/tests/modules/v1/users/users-api.test.ts +176 -0
- package/tests/setup.ts +12 -0
- package/tests/utils/test-utils.ts +453 -0
- package/tsconfig.json +16 -0
- package/tsconfig.test.json +13 -0
- package/vitest.config.ts +16 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export interface ClassificationTypeBase {
|
|
2
|
+
createdBy: string;
|
|
3
|
+
createdByName: string;
|
|
4
|
+
createdOn: string;
|
|
5
|
+
lastModBy: string;
|
|
6
|
+
lastModByName: string;
|
|
7
|
+
lastModOn: string;
|
|
8
|
+
name: string;
|
|
9
|
+
description: string | null;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Entidad completa (con ID)
|
|
13
|
+
export interface ClassificationType {
|
|
14
|
+
id: number;
|
|
15
|
+
name: string;
|
|
16
|
+
description: string | null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Request para crear tipo de clasificación
|
|
20
|
+
export interface CreateClassificationTypeRequest extends ClassificationTypeBase {}
|
|
21
|
+
|
|
22
|
+
// Request para actualizar tipo de clasificación
|
|
23
|
+
export interface UpdateClassificationTypeRequest {
|
|
24
|
+
id: number;
|
|
25
|
+
name: string;
|
|
26
|
+
description: string | null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Request para eliminar tipo de clasificación
|
|
30
|
+
export interface DeleteClassificationTypeRequest {
|
|
31
|
+
id: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Respuesta del GET (lista)
|
|
35
|
+
export interface ClassificationTypesResponse {
|
|
36
|
+
dataResult: ClassificationType[];
|
|
37
|
+
statusResponse: {
|
|
38
|
+
code: number;
|
|
39
|
+
success: boolean;
|
|
40
|
+
message: string;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Respuesta genérica para POST/PUT/DELETE
|
|
45
|
+
export interface ClassificationTypeResponse {
|
|
46
|
+
dataResult?: ClassificationType;
|
|
47
|
+
statusResponse: {
|
|
48
|
+
code: number;
|
|
49
|
+
success: boolean;
|
|
50
|
+
message: string;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// auth-api.ts
|
|
2
|
+
import { ApiClient } from "../../../core/api-client";
|
|
3
|
+
import { LoginCredentials, LoginResponse, RefreshTokenRequest } from "./types";
|
|
4
|
+
|
|
5
|
+
export class AuthApi {
|
|
6
|
+
private apiClient: ApiClient;
|
|
7
|
+
|
|
8
|
+
constructor(apiClient: ApiClient) {
|
|
9
|
+
this.apiClient = apiClient;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Login con POST JSON (evita el modal del navegador).
|
|
14
|
+
* El servidor setea cookie HttpOnly (zero_token).
|
|
15
|
+
*/
|
|
16
|
+
async login(credentials: LoginCredentials): Promise<{ ok: boolean }> {
|
|
17
|
+
try {
|
|
18
|
+
const response = await fetch(`${this.apiClient['baseUrl']}/auth/login`, {
|
|
19
|
+
method: 'POST',
|
|
20
|
+
headers: {
|
|
21
|
+
'Content-Type': 'application/json',
|
|
22
|
+
'X-Organization': this.apiClient['organization'] || 'default-org'
|
|
23
|
+
},
|
|
24
|
+
credentials: 'include', // ← Importante para cookies
|
|
25
|
+
body: JSON.stringify({
|
|
26
|
+
email: credentials.email,
|
|
27
|
+
password: credentials.password
|
|
28
|
+
})
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
if (response.status === 401) {
|
|
33
|
+
throw new Error('Invalid credentials');
|
|
34
|
+
}
|
|
35
|
+
throw new Error(`Login failed: ${response.status}`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const data = await response.json();
|
|
39
|
+
|
|
40
|
+
// No guardar token en memoria, solo usar cookie
|
|
41
|
+
this.apiClient.setToken(null);
|
|
42
|
+
|
|
43
|
+
console.log('✅ Login exitoso, cookie establecida');
|
|
44
|
+
return { ok: true };
|
|
45
|
+
|
|
46
|
+
} catch (error) {
|
|
47
|
+
console.error('❌ SDK Login error:', error);
|
|
48
|
+
throw error;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async refreshToken(request?: RefreshTokenRequest): Promise<LoginResponse> {
|
|
53
|
+
const response = await this.apiClient.post<LoginResponse>("/auth/refresh", request);
|
|
54
|
+
if ((response as any)?.token) this.apiClient.setToken((response as any).token);
|
|
55
|
+
return response;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async logout(): Promise<void> {
|
|
59
|
+
try {
|
|
60
|
+
await this.apiClient.post<void>("/auth/logout");
|
|
61
|
+
} catch (error) {
|
|
62
|
+
console.error("Error during logout:", error);
|
|
63
|
+
} finally {
|
|
64
|
+
this.apiClient.setToken(null);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
isAuthenticated(): boolean {
|
|
69
|
+
return this.apiClient.getToken() !== null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
setToken(token: string | null): void {
|
|
73
|
+
this.apiClient.setToken(token);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface LoginCredentials {
|
|
2
|
+
email: string;
|
|
3
|
+
password: string;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export interface LoginResponse {
|
|
7
|
+
token: string;
|
|
8
|
+
refreshToken?: string;
|
|
9
|
+
expiresIn: number;
|
|
10
|
+
user: {
|
|
11
|
+
id: string;
|
|
12
|
+
name: string;
|
|
13
|
+
email: string;
|
|
14
|
+
role: string;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface RefreshTokenRequest {
|
|
19
|
+
refreshToken: string;
|
|
20
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ApiClient } from "../../../core/api-client";
|
|
2
|
+
import { StatusResponse } from "./types";
|
|
3
|
+
|
|
4
|
+
export class MainApi {
|
|
5
|
+
private apiClient: ApiClient;
|
|
6
|
+
|
|
7
|
+
constructor(apiClient: ApiClient) {
|
|
8
|
+
this.apiClient = apiClient;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Get api status
|
|
13
|
+
*
|
|
14
|
+
* @returns true or false
|
|
15
|
+
*/
|
|
16
|
+
async status(): Promise<Boolean> {
|
|
17
|
+
const response = await this.apiClient.get<StatusResponse>("/status");
|
|
18
|
+
return response.message === "Ok" || false;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { ApiClient } from "../../../core/api-client";
|
|
2
|
+
import { buildQueryParams } from "../../../utils/http";
|
|
3
|
+
import {
|
|
4
|
+
GetTasksQueryParams,
|
|
5
|
+
TasksResponse,
|
|
6
|
+
NotFoundTaskResponse,
|
|
7
|
+
StartTaskResponse,
|
|
8
|
+
RemoveTaskResponse,
|
|
9
|
+
} from "./types";
|
|
10
|
+
|
|
11
|
+
export class NotificationsApi {
|
|
12
|
+
private apiClient: ApiClient;
|
|
13
|
+
|
|
14
|
+
constructor(apiClient: ApiClient) {
|
|
15
|
+
this.apiClient = apiClient;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async getWithParams(query: GetTasksQueryParams): Promise<TasksResponse> {
|
|
19
|
+
const queryParams = buildQueryParams(query);
|
|
20
|
+
const tasks = await this.apiClient.get<TasksResponse>(
|
|
21
|
+
"/tasks" + queryParams,
|
|
22
|
+
undefined,
|
|
23
|
+
{ useCache: false }
|
|
24
|
+
);
|
|
25
|
+
return tasks;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Inicia un proceso de notificacion especificando su Id
|
|
30
|
+
*/
|
|
31
|
+
async startJob(
|
|
32
|
+
taskId: string
|
|
33
|
+
): Promise<NotFoundTaskResponse | StartTaskResponse> {
|
|
34
|
+
const processResponse = await this.apiClient.post<
|
|
35
|
+
NotFoundTaskResponse | StartTaskResponse
|
|
36
|
+
>(`/tasks/${taskId}/process`, undefined);
|
|
37
|
+
return processResponse;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Elimina tareas especificando un limite y
|
|
42
|
+
* una cantidad de tiempo
|
|
43
|
+
*/
|
|
44
|
+
async deletedJobsByHours(
|
|
45
|
+
limit: number,
|
|
46
|
+
hours: number,
|
|
47
|
+
status: string
|
|
48
|
+
): Promise<RemoveTaskResponse> {
|
|
49
|
+
const processResponse = await this.apiClient.delete<RemoveTaskResponse>(
|
|
50
|
+
`/tasks?hours=${hours}&limit=${limit}&status=${status}`,
|
|
51
|
+
undefined
|
|
52
|
+
);
|
|
53
|
+
return processResponse;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export interface Task {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
end_date: string;
|
|
6
|
+
number_period: string;
|
|
7
|
+
select_period: string;
|
|
8
|
+
actity_time: string;
|
|
9
|
+
notification_date: string;
|
|
10
|
+
userManager: string;
|
|
11
|
+
status: string;
|
|
12
|
+
created_by: string;
|
|
13
|
+
created_at: string;
|
|
14
|
+
updated_by: string;
|
|
15
|
+
updated_at: string;
|
|
16
|
+
start_date: string;
|
|
17
|
+
notification_type: string;
|
|
18
|
+
notification_type_id: string;
|
|
19
|
+
company_id: number;
|
|
20
|
+
metadata_request: {
|
|
21
|
+
id: string;
|
|
22
|
+
name: string;
|
|
23
|
+
};
|
|
24
|
+
request_id: number | null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface TasksResponse {
|
|
28
|
+
data: Task[];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface GetTasksQueryParams {
|
|
32
|
+
status?: string;
|
|
33
|
+
notification_type?: string;
|
|
34
|
+
from_date?: string;
|
|
35
|
+
to_date?: string;
|
|
36
|
+
upcoming?: string;
|
|
37
|
+
page?: string;
|
|
38
|
+
limit?: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface StartTaskResponse {
|
|
42
|
+
success: boolean;
|
|
43
|
+
message: string;
|
|
44
|
+
jobId: string;
|
|
45
|
+
taskId: string;
|
|
46
|
+
taskName: string;
|
|
47
|
+
status: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface NotFoundTaskResponse {
|
|
51
|
+
statusCode: number;
|
|
52
|
+
error: string;
|
|
53
|
+
message: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface RemoveTaskResponse {
|
|
57
|
+
count: number;
|
|
58
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// Base User interface
|
|
2
|
+
export interface User {
|
|
3
|
+
id: string;
|
|
4
|
+
email: string;
|
|
5
|
+
full_name: string;
|
|
6
|
+
role_id: number;
|
|
7
|
+
is_deleted: boolean;
|
|
8
|
+
deleted_at: string | null;
|
|
9
|
+
is_active: boolean;
|
|
10
|
+
created_at: string;
|
|
11
|
+
updated_at: string;
|
|
12
|
+
phone: string | null;
|
|
13
|
+
area: string | null;
|
|
14
|
+
area_id: number | null;
|
|
15
|
+
organization_id: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Response when getting users with pagination
|
|
19
|
+
export interface UsersResponse {
|
|
20
|
+
data: User[];
|
|
21
|
+
meta: {
|
|
22
|
+
total: number;
|
|
23
|
+
page: number;
|
|
24
|
+
limit: number;
|
|
25
|
+
pages: number;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Query parameters for listing users
|
|
30
|
+
export interface UsersQuery {
|
|
31
|
+
page?: number;
|
|
32
|
+
limit?: number;
|
|
33
|
+
email?: string;
|
|
34
|
+
full_name?: string;
|
|
35
|
+
phone?: string;
|
|
36
|
+
area?: string;
|
|
37
|
+
role_id?: number;
|
|
38
|
+
area_id?: number;
|
|
39
|
+
showDeleted?: boolean;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Data for creating a new user
|
|
43
|
+
export interface UserCreate {
|
|
44
|
+
id?: string;
|
|
45
|
+
email: string;
|
|
46
|
+
password?: string;
|
|
47
|
+
full_name: string;
|
|
48
|
+
phone?: string;
|
|
49
|
+
area?: string;
|
|
50
|
+
area_id?: number;
|
|
51
|
+
role_id?: number;
|
|
52
|
+
organization_id?: number;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Data for updating a user
|
|
56
|
+
export interface UserUpdate {
|
|
57
|
+
password?: string;
|
|
58
|
+
email?: string;
|
|
59
|
+
full_name?: string;
|
|
60
|
+
phone?: string;
|
|
61
|
+
area?: string;
|
|
62
|
+
area_id?: number;
|
|
63
|
+
role_id?: number;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Standard API response structure
|
|
67
|
+
export interface ApiResponse<T> {
|
|
68
|
+
statusCode: number;
|
|
69
|
+
message: string;
|
|
70
|
+
data?: T;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Type for created user response
|
|
74
|
+
export type UserCreatedResponse = ApiResponse<User>;
|
|
75
|
+
|
|
76
|
+
// Type for updated user response
|
|
77
|
+
export type UserUpdatedResponse = ApiResponse<User>;
|
|
78
|
+
|
|
79
|
+
// Type for deleted user response
|
|
80
|
+
export type UserDeletedResponse = ApiResponse<undefined>;
|
|
81
|
+
|
|
82
|
+
// Type for deactivated user response
|
|
83
|
+
export type UserDeactivatedResponse = ApiResponse<User>;
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { ApiClient } from '../../../core/api-client';
|
|
2
|
+
import { ApiError } from '../../../core/api-error';
|
|
3
|
+
import { RequestOptions } from '../../../types/common';
|
|
4
|
+
import {
|
|
5
|
+
User,
|
|
6
|
+
UsersResponse,
|
|
7
|
+
UsersQuery,
|
|
8
|
+
UserCreate,
|
|
9
|
+
UserUpdate,
|
|
10
|
+
UserCreatedResponse,
|
|
11
|
+
UserUpdatedResponse,
|
|
12
|
+
UserDeletedResponse,
|
|
13
|
+
UserDeactivatedResponse
|
|
14
|
+
} from './types';
|
|
15
|
+
|
|
16
|
+
export class UsersApi {
|
|
17
|
+
private apiClient: ApiClient;
|
|
18
|
+
private readonly CACHE_PREFIX = 'GET:/users';
|
|
19
|
+
|
|
20
|
+
constructor(apiClient: ApiClient) {
|
|
21
|
+
this.apiClient = apiClient;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Get all users with optional filters and pagination
|
|
26
|
+
*
|
|
27
|
+
* @param query - Query parameters for filtering and pagination
|
|
28
|
+
* @param options - Request options
|
|
29
|
+
* @returns Paginated list of users
|
|
30
|
+
*/
|
|
31
|
+
async getAll(query?: UsersQuery, options?: RequestOptions): Promise<UsersResponse> {
|
|
32
|
+
const allUsers = this.apiClient.get<UsersResponse>('/users', query, options);
|
|
33
|
+
console.log(allUsers);
|
|
34
|
+
return allUsers;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Get a specific user by ID
|
|
39
|
+
*
|
|
40
|
+
* @param id - User ID (UUID)
|
|
41
|
+
* @param showDeleted - Whether to include deleted users
|
|
42
|
+
* @param options - Request options
|
|
43
|
+
* @returns User data
|
|
44
|
+
*/
|
|
45
|
+
async getById(id: string, showDeleted: boolean = false, options?: RequestOptions): Promise<User> {
|
|
46
|
+
return this.apiClient.get<User>(
|
|
47
|
+
`/users/${id}`,
|
|
48
|
+
{ showDeleted },
|
|
49
|
+
options
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Create a new user
|
|
55
|
+
*
|
|
56
|
+
* @param userData - User data for creation
|
|
57
|
+
* @param options - Request options
|
|
58
|
+
* @returns Created user response
|
|
59
|
+
*/
|
|
60
|
+
async create(userData: UserCreate, options?: RequestOptions): Promise<UserCreatedResponse> {
|
|
61
|
+
return this.apiClient.post<UserCreatedResponse>('/users', userData, options);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Update an existing user
|
|
66
|
+
*
|
|
67
|
+
* @param id - User ID (UUID)
|
|
68
|
+
* @param userData - Data to update
|
|
69
|
+
* @param options - Request options
|
|
70
|
+
* @returns Updated user response
|
|
71
|
+
*/
|
|
72
|
+
async update(id: string, userData: UserUpdate, options?: RequestOptions): Promise<UserUpdatedResponse> {
|
|
73
|
+
return this.apiClient.patch<UserUpdatedResponse>(`/users/${id}`, userData, options);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Permanently delete a user
|
|
78
|
+
*
|
|
79
|
+
* @param id - User ID (UUID)
|
|
80
|
+
* @param options - Request options
|
|
81
|
+
* @returns Delete confirmation response
|
|
82
|
+
*/
|
|
83
|
+
async delete(id: string, options?: RequestOptions): Promise<UserDeletedResponse> {
|
|
84
|
+
return this.apiClient.delete<UserDeletedResponse>(`/users/${id}`, undefined, options);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Deactivate a user (soft delete)
|
|
89
|
+
*
|
|
90
|
+
* @param id - User ID (UUID)
|
|
91
|
+
* @param options - Request options
|
|
92
|
+
* @returns Deactivated user response
|
|
93
|
+
*/
|
|
94
|
+
async deactivate(id: string, options?: RequestOptions): Promise<UserDeactivatedResponse> {
|
|
95
|
+
return this.apiClient.patch<UserDeactivatedResponse>(
|
|
96
|
+
`/users/${id}/desactivate`,
|
|
97
|
+
undefined,
|
|
98
|
+
options
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Search users by email or name
|
|
104
|
+
* Helper method that uses getAll with specific filters
|
|
105
|
+
*
|
|
106
|
+
* @param searchTerm - Term to search for in email or name
|
|
107
|
+
* @param options - Request options
|
|
108
|
+
* @returns Matching users
|
|
109
|
+
*/
|
|
110
|
+
async search(searchTerm: string, options?: RequestOptions): Promise<UsersResponse> {
|
|
111
|
+
// Determine if searchTerm looks like an email
|
|
112
|
+
const isEmail = searchTerm.includes('@');
|
|
113
|
+
|
|
114
|
+
const query: UsersQuery = isEmail
|
|
115
|
+
? { email: searchTerm }
|
|
116
|
+
: { full_name: searchTerm };
|
|
117
|
+
|
|
118
|
+
return this.getAll(query, options);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Get users by role ID
|
|
123
|
+
* Helper method that uses getAll with role filter
|
|
124
|
+
*
|
|
125
|
+
* @param roleId - Role ID to filter by
|
|
126
|
+
* @param options - Request options
|
|
127
|
+
* @returns Users with the specified role
|
|
128
|
+
*/
|
|
129
|
+
async getByRole(roleId: number, options?: RequestOptions): Promise<UsersResponse> {
|
|
130
|
+
return this.getAll({ role_id: roleId }, options);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Clear cache for users
|
|
135
|
+
* Private method used internally after modifications
|
|
136
|
+
*/
|
|
137
|
+
private clearCache(): void {
|
|
138
|
+
try {
|
|
139
|
+
// @ts-ignore - This works because the SDK has a cache.clearByPrefix method
|
|
140
|
+
if (this.apiClient['cache'] && typeof this.apiClient['cache'].clearByPrefix === 'function') {
|
|
141
|
+
// @ts-ignore
|
|
142
|
+
this.apiClient['cache'].clearByPrefix(this.CACHE_PREFIX);
|
|
143
|
+
}
|
|
144
|
+
} catch (error) {
|
|
145
|
+
console.error('Error clearing cache:', error);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface PaginatedResponse<T> {
|
|
2
|
+
results: T[];
|
|
3
|
+
pagination: {
|
|
4
|
+
page: number;
|
|
5
|
+
limit: number;
|
|
6
|
+
totalPages: number;
|
|
7
|
+
totalItems: number;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Opciones para peticiones HTTP
|
|
12
|
+
export interface RequestOptions {
|
|
13
|
+
useCache?: boolean;
|
|
14
|
+
cacheTime?: number;
|
|
15
|
+
headers?: Record<string, string>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Parámetros de paginación
|
|
19
|
+
export interface PaginationParams {
|
|
20
|
+
page?: number;
|
|
21
|
+
limit?: number;
|
|
22
|
+
}
|
package/src/types/sdk.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export interface SdkConfig {
|
|
2
|
+
baseUrl: string;
|
|
3
|
+
organization: string;
|
|
4
|
+
token?: string | null;
|
|
5
|
+
cache?: {
|
|
6
|
+
enabled?: boolean;
|
|
7
|
+
ttl?: number;
|
|
8
|
+
};
|
|
9
|
+
debug?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Tipos de eventos que puede emitir el SDK
|
|
13
|
+
export type SdkEventType =
|
|
14
|
+
| "tokenChanged"
|
|
15
|
+
| "beforeRequest"
|
|
16
|
+
| "afterRequest"
|
|
17
|
+
| "requestError"
|
|
18
|
+
| "authError";
|
|
19
|
+
|
|
20
|
+
// Información de evento por tipo
|
|
21
|
+
export interface SdkEvents {
|
|
22
|
+
tokenChanged: string | null;
|
|
23
|
+
beforeRequest: { url: string; method: string; data?: any };
|
|
24
|
+
afterRequest: { url: string; method: string; response: any };
|
|
25
|
+
requestError: { url: string; method: string; error: any };
|
|
26
|
+
authError: { statusCode: number; message: string };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Tipos de errores HTTP
|
|
30
|
+
export enum ErrorType {
|
|
31
|
+
NETWORK = "NETWORK",
|
|
32
|
+
AUTHENTICATION = "AUTHENTICATION",
|
|
33
|
+
AUTHORIZATION = "AUTHORIZATION",
|
|
34
|
+
NOT_FOUND = "NOT_FOUND",
|
|
35
|
+
VALIDATION = "VALIDATION",
|
|
36
|
+
SERVER = "SERVER",
|
|
37
|
+
UNKNOWN = "UNKNOWN",
|
|
38
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
interface CacheItem<T> {
|
|
2
|
+
data: T;
|
|
3
|
+
timestamp: number;
|
|
4
|
+
expiry: number;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export class Cache {
|
|
8
|
+
private store: Map<string, CacheItem<any>> = new Map();
|
|
9
|
+
private defaultTtl: number;
|
|
10
|
+
|
|
11
|
+
constructor(defaultTtl: number = 60000) { // 1 minuto por defecto
|
|
12
|
+
this.defaultTtl = defaultTtl;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Guardar dato en caché
|
|
16
|
+
set<T>(key: string, data: T, ttl?: number): void {
|
|
17
|
+
const expiry = ttl || this.defaultTtl;
|
|
18
|
+
this.store.set(key, {
|
|
19
|
+
data,
|
|
20
|
+
timestamp: Date.now(),
|
|
21
|
+
expiry
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Obtener dato desde caché
|
|
26
|
+
get<T>(key: string): T | null {
|
|
27
|
+
const item = this.store.get(key);
|
|
28
|
+
|
|
29
|
+
// Si no existe o está expirado, devolver null
|
|
30
|
+
if (!item || Date.now() > item.timestamp + item.expiry) {
|
|
31
|
+
if (item) {
|
|
32
|
+
this.store.delete(key); // Limpiar item expirado
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return item.data as T;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Eliminar dato específico
|
|
41
|
+
delete(key: string): void {
|
|
42
|
+
this.store.delete(key);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Limpiar caché por prefijo
|
|
46
|
+
clearByPrefix(prefix: string): void {
|
|
47
|
+
for (const key of this.store.keys()) {
|
|
48
|
+
if (key.startsWith(prefix)) {
|
|
49
|
+
this.store.delete(key);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Limpiar toda la caché
|
|
55
|
+
clear(): void {
|
|
56
|
+
this.store.clear();
|
|
57
|
+
}
|
|
58
|
+
}
|