@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.
Files changed (81) hide show
  1. package/.docs/publicacion-npm.md +111 -0
  2. package/.env.example +14 -0
  3. package/.gitlab-ci.yml +23 -0
  4. package/README.md +202 -0
  5. package/dist/config/config.d.ts +3 -0
  6. package/dist/config/config.js +21 -0
  7. package/dist/core/api-client.d.ts +27 -0
  8. package/dist/core/api-client.js +183 -0
  9. package/dist/core/api-error.d.ts +15 -0
  10. package/dist/core/api-error.js +46 -0
  11. package/dist/core/event-emitter.d.ts +11 -0
  12. package/dist/core/event-emitter.js +32 -0
  13. package/dist/index.d.ts +41 -0
  14. package/dist/index.js +59 -0
  15. package/dist/modules/legacy/areas/areas-api.d.ts +34 -0
  16. package/dist/modules/legacy/areas/areas-api.js +44 -0
  17. package/dist/modules/legacy/areas/types.d.ts +37 -0
  18. package/dist/modules/legacy/areas/types.js +1 -0
  19. package/dist/modules/legacy/classificationtypes/classificationtypes-api.d.ts +34 -0
  20. package/dist/modules/legacy/classificationtypes/classificationtypes-api.js +46 -0
  21. package/dist/modules/legacy/classificationtypes/types.d.ts +41 -0
  22. package/dist/modules/legacy/classificationtypes/types.js +1 -0
  23. package/dist/modules/v1/auth/auth-api.d.ts +17 -0
  24. package/dist/modules/v1/auth/auth-api.js +63 -0
  25. package/dist/modules/v1/auth/types.d.ts +18 -0
  26. package/dist/modules/v1/auth/types.js +1 -0
  27. package/dist/modules/v1/main/main-api.d.ts +11 -0
  28. package/dist/modules/v1/main/main-api.js +14 -0
  29. package/dist/modules/v1/main/types.d.ts +3 -0
  30. package/dist/modules/v1/main/types.js +1 -0
  31. package/dist/modules/v1/notifications/notification-api.d.ts +16 -0
  32. package/dist/modules/v1/notifications/notification-api.js +26 -0
  33. package/dist/modules/v1/notifications/types.d.ts +53 -0
  34. package/dist/modules/v1/notifications/types.js +1 -0
  35. package/dist/modules/v1/users/types.d.ts +64 -0
  36. package/dist/modules/v1/users/types.js +1 -0
  37. package/dist/modules/v1/users/users-api.d.ts +81 -0
  38. package/dist/modules/v1/users/users-api.js +113 -0
  39. package/dist/types/common.d.ts +18 -0
  40. package/dist/types/common.js +1 -0
  41. package/dist/types/sdk.d.ts +42 -0
  42. package/dist/types/sdk.js +11 -0
  43. package/dist/utils/cache.d.ts +10 -0
  44. package/dist/utils/cache.js +43 -0
  45. package/dist/utils/http.d.ts +5 -0
  46. package/dist/utils/http.js +56 -0
  47. package/package.json +38 -0
  48. package/src/config/config.ts +24 -0
  49. package/src/core/api-client.ts +272 -0
  50. package/src/core/api-error.ts +54 -0
  51. package/src/core/event-emitter.ts +43 -0
  52. package/src/index.ts +89 -0
  53. package/src/modules/legacy/areas/areas-api.ts +73 -0
  54. package/src/modules/legacy/areas/types.ts +49 -0
  55. package/src/modules/legacy/classificationtypes/classificationtypes-api.ts +80 -0
  56. package/src/modules/legacy/classificationtypes/types.ts +52 -0
  57. package/src/modules/v1/auth/auth-api.ts +75 -0
  58. package/src/modules/v1/auth/types.ts +20 -0
  59. package/src/modules/v1/main/main-api.ts +20 -0
  60. package/src/modules/v1/main/types.ts +3 -0
  61. package/src/modules/v1/notifications/notification-api.ts +55 -0
  62. package/src/modules/v1/notifications/types.ts +58 -0
  63. package/src/modules/v1/users/types.ts +83 -0
  64. package/src/modules/v1/users/users-api.ts +148 -0
  65. package/src/types/common.ts +22 -0
  66. package/src/types/sdk.ts +38 -0
  67. package/src/utils/cache.ts +58 -0
  68. package/src/utils/http.ts +77 -0
  69. package/tests/integration/legacy/auth-areas.test.ts +115 -0
  70. package/tests/integration/legacy/auth-classification-types.test.ts +80 -0
  71. package/tests/integration/v1/auth-logs.test.ts +145 -0
  72. package/tests/integration/v1/auth-users.test.ts +189 -0
  73. package/tests/modules/legacy/areas/areas-api.test.ts +232 -0
  74. package/tests/modules/legacy/classification-types/classification-types-api.test.ts +100 -0
  75. package/tests/modules/v1/auth/auth-api.test.ts +134 -0
  76. package/tests/modules/v1/users/users-api.test.ts +176 -0
  77. package/tests/setup.ts +12 -0
  78. package/tests/utils/test-utils.ts +453 -0
  79. package/tsconfig.json +16 -0
  80. package/tsconfig.test.json +13 -0
  81. 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,3 @@
1
+ export interface StatusResponse {
2
+ message: String;
3
+ }
@@ -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
+ }
@@ -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
+ }