@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,272 @@
|
|
|
1
|
+
import { SdkConfig, SdkEventType, SdkEvents } from "../types/sdk";
|
|
2
|
+
import { PaginatedResponse, RequestOptions } from "../types/common";
|
|
3
|
+
import { EventEmitter } from "./event-emitter";
|
|
4
|
+
import { ApiError } from "./api-error";
|
|
5
|
+
import { Cache } from "../utils/cache";
|
|
6
|
+
import {
|
|
7
|
+
buildUrl,
|
|
8
|
+
buildHeaders,
|
|
9
|
+
generateCacheKey,
|
|
10
|
+
parseResponse,
|
|
11
|
+
} from "../utils/http";
|
|
12
|
+
|
|
13
|
+
export class ApiClient {
|
|
14
|
+
private baseUrl: string;
|
|
15
|
+
private organization: string;
|
|
16
|
+
private token: string | null = null;
|
|
17
|
+
private eventEmitter: EventEmitter;
|
|
18
|
+
private cache: Cache;
|
|
19
|
+
private debug: boolean;
|
|
20
|
+
private cacheEnabled: boolean;
|
|
21
|
+
|
|
22
|
+
constructor(config: SdkConfig, eventEmitter: EventEmitter) {
|
|
23
|
+
this.baseUrl = config.baseUrl;
|
|
24
|
+
this.organization = config.organization;
|
|
25
|
+
this.token = config.token || null;
|
|
26
|
+
this.eventEmitter = eventEmitter;
|
|
27
|
+
this.cacheEnabled = config.cache?.enabled !== false;
|
|
28
|
+
this.cache = new Cache(config.cache?.ttl);
|
|
29
|
+
this.debug = config.debug || false;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Métodos para gestión del token
|
|
33
|
+
public setToken(token: string | null): void {
|
|
34
|
+
this.token = token;
|
|
35
|
+
this.eventEmitter.emit("tokenChanged", token);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public getToken(): string | null {
|
|
39
|
+
return this.token;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public setOrganization(organization: string): void {
|
|
43
|
+
this.organization = organization;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Método GET
|
|
47
|
+
public async get<T>(
|
|
48
|
+
endpoint: string,
|
|
49
|
+
params?: Record<string, any>,
|
|
50
|
+
options?: RequestOptions
|
|
51
|
+
): Promise<T> {
|
|
52
|
+
return this.request<T>("GET", endpoint, undefined, params, options);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Método POST
|
|
56
|
+
public async post<T>(
|
|
57
|
+
endpoint: string,
|
|
58
|
+
data?: any,
|
|
59
|
+
options?: RequestOptions
|
|
60
|
+
): Promise<T> {
|
|
61
|
+
return this.request<T>("POST", endpoint, data, undefined, options);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Método PATCH
|
|
65
|
+
public async patch<T>(
|
|
66
|
+
endpoint: string,
|
|
67
|
+
data?: any,
|
|
68
|
+
options?: RequestOptions
|
|
69
|
+
): Promise<T> {
|
|
70
|
+
const result = await this.request<T>(
|
|
71
|
+
"PATCH",
|
|
72
|
+
endpoint,
|
|
73
|
+
data,
|
|
74
|
+
undefined,
|
|
75
|
+
options
|
|
76
|
+
);
|
|
77
|
+
this.invalidateCache(endpoint);
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Método PUT
|
|
82
|
+
public async put<T>(
|
|
83
|
+
endpoint: string,
|
|
84
|
+
data?: any,
|
|
85
|
+
options?: RequestOptions
|
|
86
|
+
): Promise<T> {
|
|
87
|
+
const result = await this.request<T>(
|
|
88
|
+
"PUT",
|
|
89
|
+
endpoint,
|
|
90
|
+
data,
|
|
91
|
+
undefined,
|
|
92
|
+
options
|
|
93
|
+
);
|
|
94
|
+
this.invalidateCache(endpoint);
|
|
95
|
+
return result;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ✅ Método DELETE - CORREGIDO
|
|
99
|
+
public async delete<T>(
|
|
100
|
+
endpoint: string,
|
|
101
|
+
data?: any, // ✅ Cambiar params por data para enviarlo en el body
|
|
102
|
+
options?: RequestOptions
|
|
103
|
+
): Promise<T> {
|
|
104
|
+
console.log("🗑️ DELETE request:", { endpoint, data });
|
|
105
|
+
|
|
106
|
+
const result = await this.request<T>(
|
|
107
|
+
"DELETE",
|
|
108
|
+
endpoint,
|
|
109
|
+
data, // ✅ Enviar como body (data)
|
|
110
|
+
undefined, // ✅ params es undefined
|
|
111
|
+
options
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
this.invalidateCache(endpoint);
|
|
115
|
+
console.log("✅ DELETE response:", result);
|
|
116
|
+
return result;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Invalida la caché relacionada con un endpoint específico
|
|
121
|
+
*/
|
|
122
|
+
private invalidateCache(endpoint: string): void {
|
|
123
|
+
if (this.cacheEnabled) {
|
|
124
|
+
const basePath = endpoint.split("/").slice(0, 2).join("/");
|
|
125
|
+
this.cache.clearByPrefix(`GET:${this.baseUrl}${basePath}`);
|
|
126
|
+
|
|
127
|
+
if (this.debug) {
|
|
128
|
+
console.log(`[SDK-Cache] Invalidated cache for: ${basePath}`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Método central para todas las peticiones HTTP
|
|
134
|
+
private async request<T>(
|
|
135
|
+
method: string,
|
|
136
|
+
endpoint: string,
|
|
137
|
+
data?: any,
|
|
138
|
+
params?: Record<string, any>,
|
|
139
|
+
options: RequestOptions = {}
|
|
140
|
+
): Promise<T> {
|
|
141
|
+
const url = buildUrl(this.baseUrl, endpoint, params);
|
|
142
|
+
|
|
143
|
+
// =====================================================
|
|
144
|
+
// 1. Construir headers base
|
|
145
|
+
// =====================================================
|
|
146
|
+
const base: HeadersInit = buildHeaders(this.token, {
|
|
147
|
+
"X-Organization": this.organization,
|
|
148
|
+
...(options.headers || {}),
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
const headers = new Headers(base);
|
|
152
|
+
|
|
153
|
+
if (!this.token) {
|
|
154
|
+
headers.delete("Authorization");
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// =====================================================
|
|
158
|
+
// 2. Si el endpoint es /legacy/** → agregar Bearer legacy
|
|
159
|
+
// =====================================================
|
|
160
|
+
if (endpoint.startsWith("/legacy/")) {
|
|
161
|
+
const legacyToken =
|
|
162
|
+
(window as any).__LEGACY_TOKEN__ ||
|
|
163
|
+
sessionStorage.getItem("legacy_token") ||
|
|
164
|
+
null;
|
|
165
|
+
|
|
166
|
+
if (legacyToken) {
|
|
167
|
+
headers.set("Authorization", `Bearer ${legacyToken}`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// =====================================================
|
|
172
|
+
// 3. Cache
|
|
173
|
+
// =====================================================
|
|
174
|
+
const useCache = this.cacheEnabled && options.useCache !== false;
|
|
175
|
+
if (useCache && method === "GET") {
|
|
176
|
+
const cacheKey = generateCacheKey(method, url, data);
|
|
177
|
+
const cachedData = this.cache.get<T>(cacheKey);
|
|
178
|
+
if (cachedData) {
|
|
179
|
+
if (this.debug) {
|
|
180
|
+
console.log(`[SDK-Cache] Hit: ${cacheKey}`);
|
|
181
|
+
}
|
|
182
|
+
return cachedData;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
this.eventEmitter.emit("beforeRequest", {
|
|
187
|
+
url,
|
|
188
|
+
method,
|
|
189
|
+
data,
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
try {
|
|
193
|
+
// =====================================================
|
|
194
|
+
// 4. Preparar options de fetch
|
|
195
|
+
// =====================================================
|
|
196
|
+
const fetchOptions: RequestInit = {
|
|
197
|
+
method,
|
|
198
|
+
headers,
|
|
199
|
+
credentials: "include",
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
// ✅ CRÍTICO: Agregar body para POST, PUT, PATCH y DELETE
|
|
203
|
+
if (data && method !== "GET") {
|
|
204
|
+
fetchOptions.body = JSON.stringify(data);
|
|
205
|
+
console.log(`📤 ${method} Body:`, data);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// =====================================================
|
|
209
|
+
// 5. Hacer la llamada real
|
|
210
|
+
// =====================================================
|
|
211
|
+
console.log(`🌐 ${method} ${url}`, fetchOptions);
|
|
212
|
+
const response = await fetch(url, fetchOptions);
|
|
213
|
+
|
|
214
|
+
// Manejo de errores HTTP
|
|
215
|
+
if (!response.ok) {
|
|
216
|
+
let errorData;
|
|
217
|
+
try {
|
|
218
|
+
errorData = await response.json();
|
|
219
|
+
} catch {
|
|
220
|
+
errorData = { message: response.statusText };
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
console.error(`❌ ${method} ${response.status}:`, errorData);
|
|
224
|
+
|
|
225
|
+
if (response.status === 401) {
|
|
226
|
+
this.eventEmitter.emit("authError", {
|
|
227
|
+
statusCode: 401,
|
|
228
|
+
message: errorData.message || "Authentication required",
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return errorData as T;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Parsear respuesta exitosa
|
|
236
|
+
const responseData = await parseResponse<T>(response);
|
|
237
|
+
|
|
238
|
+
// Guardar en caché si aplica
|
|
239
|
+
if (useCache && method === "GET") {
|
|
240
|
+
const cacheKey = generateCacheKey(method, url, data);
|
|
241
|
+
const cacheTime = options.cacheTime || undefined;
|
|
242
|
+
this.cache.set(cacheKey, responseData, cacheTime);
|
|
243
|
+
|
|
244
|
+
if (this.debug) {
|
|
245
|
+
console.log(`[SDK-Cache] Set: ${cacheKey}`);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
this.eventEmitter.emit("afterRequest", {
|
|
250
|
+
url,
|
|
251
|
+
method,
|
|
252
|
+
response: responseData,
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
return responseData;
|
|
256
|
+
} catch (error) {
|
|
257
|
+
this.eventEmitter.emit("requestError", {
|
|
258
|
+
url,
|
|
259
|
+
method,
|
|
260
|
+
error,
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
if (error instanceof ApiError) {
|
|
264
|
+
throw error;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
throw new ApiError((error as Error).message || "Network error", 0, {
|
|
268
|
+
originalError: error,
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { ErrorType } from '../types/sdk';
|
|
2
|
+
|
|
3
|
+
export class ApiError extends Error {
|
|
4
|
+
public readonly isApiError = true;
|
|
5
|
+
public readonly statusCode: number;
|
|
6
|
+
public readonly type: ErrorType;
|
|
7
|
+
public readonly details?: any;
|
|
8
|
+
|
|
9
|
+
constructor(message: string, statusCode: number, details?: any) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.name = 'ApiError';
|
|
12
|
+
this.statusCode = statusCode;
|
|
13
|
+
this.details = details;
|
|
14
|
+
this.type = this.determineErrorType(statusCode);
|
|
15
|
+
|
|
16
|
+
// Para que instanceof funcione correctamente con clases extendidas
|
|
17
|
+
Object.setPrototypeOf(this, ApiError.prototype);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Determina el tipo de error según el código HTTP
|
|
21
|
+
private determineErrorType(statusCode: number): ErrorType {
|
|
22
|
+
if (statusCode === 401) return ErrorType.AUTHENTICATION;
|
|
23
|
+
if (statusCode === 403) return ErrorType.AUTHORIZATION;
|
|
24
|
+
if (statusCode === 404) return ErrorType.NOT_FOUND;
|
|
25
|
+
if (statusCode >= 400 && statusCode < 500) return ErrorType.VALIDATION;
|
|
26
|
+
if (statusCode >= 500) return ErrorType.SERVER;
|
|
27
|
+
return ErrorType.UNKNOWN;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Propiedades útiles para verificación de tipo de error
|
|
31
|
+
get isNetworkError(): boolean {
|
|
32
|
+
return this.type === ErrorType.NETWORK;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
get isAuthenticationError(): boolean {
|
|
36
|
+
return this.type === ErrorType.AUTHENTICATION;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
get isAuthorizationError(): boolean {
|
|
40
|
+
return this.type === ErrorType.AUTHORIZATION;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
get isNotFoundError(): boolean {
|
|
44
|
+
return this.type === ErrorType.NOT_FOUND;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
get isValidationError(): boolean {
|
|
48
|
+
return this.type === ErrorType.VALIDATION;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
get isServerError(): boolean {
|
|
52
|
+
return this.type === ErrorType.SERVER;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { SdkEventType, SdkEvents } from '../types/sdk';
|
|
2
|
+
|
|
3
|
+
type Listener<T> = (data: T) => void;
|
|
4
|
+
|
|
5
|
+
interface Subscription {
|
|
6
|
+
unsubscribe: () => void;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export class EventEmitter {
|
|
10
|
+
private listeners: Map<string, Array<Listener<any>>> = new Map();
|
|
11
|
+
|
|
12
|
+
// Suscribirse a un evento
|
|
13
|
+
public on<K extends SdkEventType>(event: K, listener: Listener<SdkEvents[K]>): Subscription {
|
|
14
|
+
if (!this.listeners.has(event)) {
|
|
15
|
+
this.listeners.set(event, []);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const eventListeners = this.listeners.get(event)!;
|
|
19
|
+
eventListeners.push(listener);
|
|
20
|
+
|
|
21
|
+
// Devolver objeto para cancelar suscripción
|
|
22
|
+
return {
|
|
23
|
+
unsubscribe: () => {
|
|
24
|
+
const index = eventListeners.indexOf(listener);
|
|
25
|
+
if (index !== -1) {
|
|
26
|
+
eventListeners.splice(index, 1);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Emitir un evento con datos
|
|
33
|
+
public emit<K extends SdkEventType>(event: K, data: SdkEvents[K]): void {
|
|
34
|
+
if (!this.listeners.has(event)) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const eventListeners = this.listeners.get(event)!;
|
|
39
|
+
for (const listener of eventListeners) {
|
|
40
|
+
listener(data);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { SdkConfig } from "./types/sdk";
|
|
2
|
+
import { mergeWithDefaultConfig } from "./config/config";
|
|
3
|
+
import { ApiClient } from "./core/api-client";
|
|
4
|
+
import { EventEmitter } from "./core/event-emitter";
|
|
5
|
+
import { Cache } from "./utils/cache";
|
|
6
|
+
import { SdkEventType } from "./types/sdk";
|
|
7
|
+
|
|
8
|
+
// v1
|
|
9
|
+
import { AuthApi } from "./modules/v1/auth/auth-api";
|
|
10
|
+
import { UsersApi } from "./modules/v1/users/users-api";
|
|
11
|
+
import { MainApi } from "./modules/v1/main/main-api";
|
|
12
|
+
import { NotificationsApi } from "./modules/v1/notifications/notification-api";
|
|
13
|
+
//import { LogsApi } from "./modules/v1/logs/logs-api";
|
|
14
|
+
|
|
15
|
+
// Legacy
|
|
16
|
+
import { AreasApi } from "./modules/legacy/areas/areas-api";
|
|
17
|
+
import { ClassificationTypesApi } from "./modules/legacy/classificationtypes/classificationtypes-api";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Main SDK for consuming CLM API
|
|
21
|
+
*/
|
|
22
|
+
export class ClmSdk {
|
|
23
|
+
private apiClient: ApiClient;
|
|
24
|
+
private eventEmitter: EventEmitter;
|
|
25
|
+
private cacheInstance: Cache;
|
|
26
|
+
|
|
27
|
+
// Public modules v1
|
|
28
|
+
public auth: AuthApi;
|
|
29
|
+
public users: UsersApi;
|
|
30
|
+
public main: MainApi;
|
|
31
|
+
public notifications: NotificationsApi;
|
|
32
|
+
//public logs: LogsApi;
|
|
33
|
+
|
|
34
|
+
// Public modules legacy
|
|
35
|
+
public areas: AreasApi;
|
|
36
|
+
public classificationTypes: ClassificationTypesApi;
|
|
37
|
+
|
|
38
|
+
constructor(config: Partial<SdkConfig>) {
|
|
39
|
+
this.eventEmitter = new EventEmitter();
|
|
40
|
+
|
|
41
|
+
// Apply default configuration
|
|
42
|
+
const fullConfig = mergeWithDefaultConfig(config);
|
|
43
|
+
|
|
44
|
+
// Initialize core utilities
|
|
45
|
+
this.cacheInstance = new Cache(fullConfig.cache?.ttl);
|
|
46
|
+
this.apiClient = new ApiClient(fullConfig, this.eventEmitter);
|
|
47
|
+
|
|
48
|
+
// Initialize modules v1
|
|
49
|
+
this.auth = new AuthApi(this.apiClient);
|
|
50
|
+
this.users = new UsersApi(this.apiClient);
|
|
51
|
+
this.main = new MainApi(this.apiClient);
|
|
52
|
+
this.notifications = new NotificationsApi(this.apiClient);
|
|
53
|
+
//this.logs = new LogsApi(this.apiClient);
|
|
54
|
+
|
|
55
|
+
// Initialize legacy modules
|
|
56
|
+
this.areas = new AreasApi(this.apiClient);
|
|
57
|
+
this.classificationTypes = new ClassificationTypesApi(this.apiClient);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Access to events system
|
|
62
|
+
*/
|
|
63
|
+
public on(
|
|
64
|
+
event: SdkEventType,
|
|
65
|
+
listener: any
|
|
66
|
+
): ReturnType<typeof this.eventEmitter.on> {
|
|
67
|
+
return this.eventEmitter.on(event, listener);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Access to cache functions
|
|
72
|
+
*/
|
|
73
|
+
public cache = {
|
|
74
|
+
clear: () => this.cacheInstance.clear(),
|
|
75
|
+
clearByPrefix: (prefix: string) => this.cacheInstance.clearByPrefix(prefix),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export * from "./types/common";
|
|
80
|
+
export * from "./types/sdk";
|
|
81
|
+
|
|
82
|
+
// Export v1 types
|
|
83
|
+
export * from "./modules/v1/auth/types";
|
|
84
|
+
export * from "./modules/v1/users/types";
|
|
85
|
+
export * from "./modules/v1/notifications/types";
|
|
86
|
+
//export * from "./modules/v1/logs/types";
|
|
87
|
+
// Export legacy types
|
|
88
|
+
export * from "./modules/legacy/areas/types";
|
|
89
|
+
export * from "./modules/legacy/classificationtypes/types";
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { ApiClient } from "../../../core/api-client";
|
|
2
|
+
import {
|
|
3
|
+
CreateAreaRequest,
|
|
4
|
+
UpdateAreaRequest,
|
|
5
|
+
DeleteAreaRequest,
|
|
6
|
+
AreaResponse,
|
|
7
|
+
AreasResponse
|
|
8
|
+
} from "./types";
|
|
9
|
+
|
|
10
|
+
export class AreasApi {
|
|
11
|
+
private apiClient: ApiClient;
|
|
12
|
+
private readonly basePath = "/legacy/catalog/areas"; //Siempre debe empezar con /legacy/ por que lo usa en el Gateway del API para que todas las request de API LEGACY y API V1 salgan de http://localhost:3001 URL del API que fusiona el API LEGACY y el API V1 y que el puerto lo toma por defecto del manifest
|
|
13
|
+
|
|
14
|
+
constructor(apiClient: ApiClient) {
|
|
15
|
+
this.apiClient = apiClient;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* GET - Obtener todas las áreas
|
|
20
|
+
*/
|
|
21
|
+
async getAreas(): Promise<AreasResponse> {
|
|
22
|
+
return await this.apiClient.get<AreasResponse>(
|
|
23
|
+
this.basePath,
|
|
24
|
+
undefined,
|
|
25
|
+
{ useCache: false }
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* POST - Crear una nueva área
|
|
31
|
+
*/
|
|
32
|
+
async createArea(data: CreateAreaRequest): Promise<AreaResponse> {
|
|
33
|
+
return await this.apiClient.post<AreaResponse>(
|
|
34
|
+
this.basePath,
|
|
35
|
+
data
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* PATCH - Actualizar datos de un área existente
|
|
41
|
+
*/
|
|
42
|
+
async updateArea(data: UpdateAreaRequest): Promise<AreaResponse> {
|
|
43
|
+
return await this.apiClient.patch<AreaResponse>(
|
|
44
|
+
this.basePath,
|
|
45
|
+
data
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* DELETE - Eliminar un área existente
|
|
51
|
+
*/
|
|
52
|
+
async deleteArea(data: DeleteAreaRequest): Promise<AreaResponse> {
|
|
53
|
+
return await this.apiClient.delete<AreaResponse>(
|
|
54
|
+
this.basePath,
|
|
55
|
+
data
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Helper: Generar datos de auditoría actuales
|
|
61
|
+
*/
|
|
62
|
+
generateAuditData(userId: string, userName: string) {
|
|
63
|
+
const now = new Date().toISOString();
|
|
64
|
+
return {
|
|
65
|
+
createdBy: userId,
|
|
66
|
+
createdByName: userName,
|
|
67
|
+
createdOn: now,
|
|
68
|
+
lastModBy: userId,
|
|
69
|
+
lastModByName: userName,
|
|
70
|
+
lastModOn: now
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// Entidad base con metadatos de auditoría
|
|
2
|
+
export interface AreaBase {
|
|
3
|
+
createdBy: string;
|
|
4
|
+
createdByName: string;
|
|
5
|
+
createdOn: string; // ISO DateTime
|
|
6
|
+
lastModBy: string;
|
|
7
|
+
lastModByName: string;
|
|
8
|
+
lastModOn: string; // ISO DateTime
|
|
9
|
+
name: string;
|
|
10
|
+
description: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Entidad completa (con ID)
|
|
14
|
+
export interface Area extends AreaBase {
|
|
15
|
+
id: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Request para crear área
|
|
19
|
+
export interface CreateAreaRequest extends AreaBase {}
|
|
20
|
+
|
|
21
|
+
// Request para actualizar área
|
|
22
|
+
export interface UpdateAreaRequest extends AreaBase {
|
|
23
|
+
id: number;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Request para eliminar área
|
|
27
|
+
export interface DeleteAreaRequest {
|
|
28
|
+
id: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Respuesta del GET (lista de áreas)
|
|
32
|
+
export interface AreasResponse {
|
|
33
|
+
dataResult: Area[];
|
|
34
|
+
statusResponse: {
|
|
35
|
+
code: number;
|
|
36
|
+
success: boolean;
|
|
37
|
+
message: string;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Respuesta genérica para POST/PUT/DELETE
|
|
42
|
+
export interface AreaResponse {
|
|
43
|
+
dataResult?: Area;
|
|
44
|
+
statusResponse: {
|
|
45
|
+
code: number;
|
|
46
|
+
success: boolean;
|
|
47
|
+
message: string;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { ApiClient } from "../../../core/api-client";
|
|
2
|
+
import {
|
|
3
|
+
CreateClassificationTypeRequest,
|
|
4
|
+
UpdateClassificationTypeRequest,
|
|
5
|
+
DeleteClassificationTypeRequest,
|
|
6
|
+
ClassificationTypeResponse,
|
|
7
|
+
ClassificationTypesResponse
|
|
8
|
+
} from "./types";
|
|
9
|
+
|
|
10
|
+
export class ClassificationTypesApi {
|
|
11
|
+
private apiClient: ApiClient;
|
|
12
|
+
private readonly basePath = "/legacy/catalog/clasificationtype";
|
|
13
|
+
|
|
14
|
+
constructor(apiClient: ApiClient) {
|
|
15
|
+
this.apiClient = apiClient;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* GET - Obtener todos los tipos de clasificación
|
|
20
|
+
*/
|
|
21
|
+
async getClassificationTypes(): Promise<ClassificationTypesResponse> {
|
|
22
|
+
return await this.apiClient.get<ClassificationTypesResponse>(
|
|
23
|
+
this.basePath,
|
|
24
|
+
undefined,
|
|
25
|
+
{ useCache: false }
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* POST - Crear un nuevo tipo de clasificación
|
|
31
|
+
*/
|
|
32
|
+
async createClassificationType(
|
|
33
|
+
data: CreateClassificationTypeRequest
|
|
34
|
+
): Promise<ClassificationTypeResponse> {
|
|
35
|
+
const response = await this.apiClient.post<ClassificationTypeResponse>(
|
|
36
|
+
`${this.basePath}/create`,
|
|
37
|
+
data
|
|
38
|
+
);
|
|
39
|
+
return response;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* PUT - Actualizar un tipo de clasificación existente
|
|
44
|
+
*/
|
|
45
|
+
async updateClassificationType(
|
|
46
|
+
data: UpdateClassificationTypeRequest
|
|
47
|
+
): Promise<ClassificationTypeResponse> {
|
|
48
|
+
return await this.apiClient.put<ClassificationTypeResponse>(
|
|
49
|
+
`${this.basePath}/update`, // Puede necesitar /update
|
|
50
|
+
data
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* DELETE - Eliminar un tipo de clasificación
|
|
56
|
+
*/
|
|
57
|
+
async deleteClassificationType(
|
|
58
|
+
data: DeleteClassificationTypeRequest
|
|
59
|
+
): Promise<ClassificationTypeResponse> {
|
|
60
|
+
return await this.apiClient.delete<ClassificationTypeResponse>(
|
|
61
|
+
`${this.basePath}/delete`,
|
|
62
|
+
data
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Helper: Generar datos de auditoría actuales
|
|
68
|
+
*/
|
|
69
|
+
generateAuditData(userId: string, userName: string) {
|
|
70
|
+
const now = new Date().toISOString();
|
|
71
|
+
return {
|
|
72
|
+
createdBy: userId,
|
|
73
|
+
createdByName: userName,
|
|
74
|
+
createdOn: now,
|
|
75
|
+
lastModBy: userId,
|
|
76
|
+
lastModByName: userName,
|
|
77
|
+
lastModOn: now
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
}
|