@zerosls/clm-sdk 1.1.9 → 1.1.10

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.
@@ -3,7 +3,6 @@ import { RequestOptions } from "../types/common";
3
3
  import { EventEmitter } from "./event-emitter";
4
4
  export declare class ApiClient {
5
5
  private baseUrl;
6
- private fallbackBaseUrl;
7
6
  private organization;
8
7
  private token;
9
8
  private eventEmitter;
@@ -6,8 +6,6 @@ export class ApiClient {
6
6
  var _a, _b;
7
7
  this.token = null;
8
8
  this.baseUrl = config.baseUrl;
9
- this.fallbackBaseUrl =
10
- config.fallbackBaseUrl || "http://216.250.117.119/ZeroServicesQA/api/v1";
11
9
  this.organization = config.organization;
12
10
  this.token = config.token || null;
13
11
  this.eventEmitter = eventEmitter;
@@ -57,223 +55,31 @@ export class ApiClient {
57
55
  }
58
56
  }
59
57
  }
60
- /*private async request<T>(
61
- method: string,
62
- endpoint: string,
63
- data?: any,
64
- params?: Record<string, any>,
65
- options: RequestOptions = {}
66
- ): Promise<T> {
67
- // ✅ Primer intento con baseUrl normal
68
- const primaryUrl = buildUrl(this.baseUrl, endpoint, params);
69
-
70
- const base: HeadersInit = buildHeaders(this.token, {
71
- "X-Organization": this.organization,
72
- ...(options.headers || {}),
73
- });
74
-
75
- const headers = new Headers(base);
76
-
77
- // ✅ Obtener token legacy
78
- const legacyToken =
79
- (window as any).__LEGACY_TOKEN__ ||
80
- sessionStorage.getItem("legacy_token") ||
81
- null;
82
-
83
- if (legacyToken) {
84
- headers.set("Authorization", `Bearer ${legacyToken}`);
85
- if (this.debug) {
86
- console.log("🔐 Using legacy token for:", endpoint);
87
- }
88
- } else if (this.token) {
89
- if (this.debug) {
90
- console.log("🔐 Using v1 token for:", endpoint);
91
- }
92
- } else {
93
- console.warn("⚠️ No token available for endpoint:", endpoint);
94
- }
95
-
96
- const useCache = this.cacheEnabled && options.useCache !== false;
97
- if (useCache && method === "GET") {
98
- const cacheKey = generateCacheKey(method, primaryUrl, data);
99
- const cachedData = this.cache.get<T>(cacheKey);
100
- if (cachedData) {
101
- if (this.debug) {
102
- console.log(`[SDK-Cache] Hit: ${cacheKey}`);
103
- }
104
- return cachedData;
105
- }
106
- }
107
-
108
- this.eventEmitter.emit("beforeRequest", {
109
- url: primaryUrl,
110
- method,
111
- data,
112
- });
113
-
114
- try {
115
- const fetchOptions: RequestInit = {
116
- method,
117
- headers,
118
- credentials: "include",
119
- };
120
-
121
- if (data && method !== "GET") {
122
- fetchOptions.body = JSON.stringify(data);
123
- if (this.debug) {
124
- console.log(`📤 ${method} Body:`, data);
125
- }
126
- }
127
-
128
- if (this.debug) {
129
- console.log(`🌐 ${method} ${primaryUrl}`);
130
- }
131
-
132
- // ✅ Primer intento
133
- const response = await fetch(primaryUrl, fetchOptions);
134
-
135
- // ✅ Si es 404, intentar con fallback URL
136
- if (response.status === 404) {
137
- console.warn(`⚠️ 404 en ${primaryUrl}, intentando con fallback...`);
138
-
139
- const fallbackUrl = buildUrl(this.fallbackBaseUrl, endpoint, params);
140
-
141
- if (this.debug) {
142
- console.log(`🔄 Retry: ${method} ${fallbackUrl}`);
143
- }
144
-
145
- // ✅ Segundo intento con fallback
146
- const fallbackResponse = await fetch(fallbackUrl, fetchOptions);
147
-
148
- if (!fallbackResponse.ok) {
149
- let errorData;
150
- try {
151
- errorData = await fallbackResponse.json();
152
- } catch {
153
- errorData = { message: fallbackResponse.statusText };
154
- }
155
-
156
- console.error(`❌ Fallback también falló ${fallbackResponse.status}:`, errorData);
157
-
158
- if (fallbackResponse.status === 401) {
159
- this.eventEmitter.emit("authError", {
160
- statusCode: 401,
161
- message: errorData.message || "Authentication required",
162
- });
163
- }
164
-
165
- return errorData as T;
166
- }
167
-
168
- // ✅ Fallback exitoso
169
- const fallbackData = await parseResponse<T>(fallbackResponse);
170
-
171
- console.log(`✅ Fallback exitoso para: ${endpoint}`);
172
-
173
- this.eventEmitter.emit("afterRequest", {
174
- url: fallbackUrl,
175
- method,
176
- response: fallbackData,
177
- });
178
-
179
- return fallbackData;
180
- }
181
-
182
- // ✅ Otros errores (no 404)
183
- if (!response.ok) {
184
- let errorData;
185
- try {
186
- errorData = await response.json();
187
- } catch {
188
- errorData = { message: response.statusText };
189
- }
190
-
191
- console.error(`❌ ${method} ${response.status}:`, errorData);
192
-
193
- if (response.status === 401) {
194
- this.eventEmitter.emit("authError", {
195
- statusCode: 401,
196
- message: errorData.message || "Authentication required",
197
- });
198
- }
199
-
200
- return errorData as T;
201
- }
202
-
203
- // ✅ Respuesta exitosa del primer intento
204
- const responseData = await parseResponse<T>(response);
205
-
206
- if (useCache && method === "GET") {
207
- const cacheKey = generateCacheKey(method, primaryUrl, data);
208
- const cacheTime = options.cacheTime || undefined;
209
- this.cache.set(cacheKey, responseData, cacheTime);
210
-
211
- if (this.debug) {
212
- console.log(`[SDK-Cache] Set: ${cacheKey}`);
213
- }
214
- }
215
-
216
- this.eventEmitter.emit("afterRequest", {
217
- url: primaryUrl,
218
- method,
219
- response: responseData,
220
- });
221
-
222
- return responseData;
223
- } catch (error) {
224
- this.eventEmitter.emit("requestError", {
225
- url: primaryUrl,
226
- method,
227
- error,
228
- });
229
-
230
- if (error instanceof ApiError) {
231
- throw error;
232
- }
233
-
234
- throw new ApiError((error as Error).message || "Network error", 0, {
235
- originalError: error,
236
- });
237
- }
238
- }*/
239
58
  async request(method, endpoint, data, params, options = {}) {
240
- const primaryUrl = buildUrl(this.baseUrl, endpoint, params);
241
- const baseHeaders = buildHeaders(this.token, {
59
+ const url = buildUrl(this.baseUrl, endpoint, params);
60
+ const base = buildHeaders(this.token, {
242
61
  "X-Organization": this.organization,
243
62
  ...(options.headers || {}),
244
63
  });
245
- // Función helper para debug de headers
246
- const headersToObject = (headers) => {
247
- const obj = {};
248
- headers.forEach((value, key) => {
249
- obj[key] = value;
250
- });
251
- return obj;
252
- };
253
- const createHeaders = () => {
254
- const headers = new Headers(baseHeaders);
255
- const legacyToken = window.__LEGACY_TOKEN__ ||
256
- sessionStorage.getItem("legacy_token") ||
64
+ const headers = new Headers(base);
65
+ const legacyPattern = /(^|\/)legacy(\/|$)/i;
66
+ const isLegacyEndpoint = legacyPattern.test(endpoint);
67
+ const isLegacyLogin = /(^|\/)legacy\/login$/i.test(endpoint);
68
+ if (isLegacyEndpoint && !isLegacyLogin) {
69
+ const legacyToken = (typeof window !== "undefined" && window.__LEGACY_TOKEN__) ||
70
+ (typeof sessionStorage !== "undefined" &&
71
+ sessionStorage.getItem("legacy_token")) ||
257
72
  null;
258
73
  if (legacyToken) {
259
74
  headers.set("Authorization", `Bearer ${legacyToken}`);
260
- if (this.debug) {
261
- console.log("🔐 Using legacy token for:", endpoint);
262
- }
263
75
  }
264
- else if (this.token) {
265
- if (this.debug) {
266
- console.log("🔐 Using v1 token for:", endpoint);
267
- }
268
- }
269
- else {
270
- console.warn("⚠️ No token available for endpoint:", endpoint);
271
- }
272
- return headers;
273
- };
76
+ }
77
+ if (!isLegacyEndpoint && !this.token) {
78
+ headers.delete("Authorization");
79
+ }
274
80
  const useCache = this.cacheEnabled && options.useCache !== false;
275
81
  if (useCache && method === "GET") {
276
- const cacheKey = generateCacheKey(method, primaryUrl, data);
82
+ const cacheKey = generateCacheKey(method, url, data);
277
83
  const cachedData = this.cache.get(cacheKey);
278
84
  if (cachedData) {
279
85
  if (this.debug) {
@@ -283,89 +89,28 @@ export class ApiClient {
283
89
  }
284
90
  }
285
91
  this.eventEmitter.emit("beforeRequest", {
286
- url: primaryUrl,
92
+ url,
287
93
  method,
288
94
  data,
289
95
  });
290
96
  try {
291
- let body;
292
- if (data && method !== "GET") {
293
- body = JSON.stringify(data);
294
- if (this.debug) {
295
- console.log(`📤 ${method} Body:`, data);
296
- }
297
- }
298
- // ✅ Primer intento
299
- const headers1 = createHeaders();
300
- const fetchOptions1 = {
97
+ const fetchOptions = {
301
98
  method,
302
- headers: headers1,
303
- credentials: "include",
304
- ...(body && { body }),
99
+ headers,
100
+ credentials: this.credentials,
305
101
  };
306
- if (this.debug) {
307
- console.log(`🌐 ${method} ${primaryUrl}`);
308
- console.log("📋 Headers:", headersToObject(headers1)); // ✅ CORREGIDO
309
- }
310
- const response = await fetch(primaryUrl, fetchOptions1);
311
- if (response.status === 404) {
312
- console.warn(`⚠️ 404 en ${primaryUrl}, intentando con fallback...`);
313
- const fallbackUrl = buildUrl(this.fallbackBaseUrl, endpoint, params);
314
- if (this.debug) {
315
- console.log(`🔄 Retry: ${method} ${fallbackUrl}`);
316
- }
317
- // ✅ Segundo intento
318
- const headers2 = createHeaders();
319
- const fetchOptions2 = {
320
- method,
321
- headers: headers2,
322
- credentials: "include",
323
- ...(body && { body }),
324
- };
325
- if (this.debug) {
326
- console.log("📋 Fallback Headers:", headersToObject(headers2)); // ✅ CORREGIDO
327
- }
328
- const fallbackResponse = await fetch(fallbackUrl, fetchOptions2);
329
- if (fallbackResponse.status === 204) {
330
- console.log(`✅ Fallback exitoso (204 No Content): ${endpoint}`);
331
- return {};
332
- }
333
- if (!fallbackResponse.ok) {
334
- let errorData;
335
- try {
336
- errorData = await fallbackResponse.json();
337
- }
338
- catch (_a) {
339
- errorData = { message: fallbackResponse.statusText };
340
- }
341
- console.error(`❌ Fallback falló ${fallbackResponse.status}:`, errorData);
342
- if (fallbackResponse.status === 401) {
343
- this.eventEmitter.emit("authError", {
344
- statusCode: 401,
345
- message: errorData.message || "Authentication required",
346
- });
347
- }
348
- return errorData;
349
- }
350
- const fallbackData = await parseResponse(fallbackResponse);
351
- console.log(`✅ Fallback exitoso: ${endpoint}`);
352
- this.eventEmitter.emit("afterRequest", {
353
- url: fallbackUrl,
354
- method,
355
- response: fallbackData,
356
- });
357
- return fallbackData;
358
- }
359
- if (response.status === 204) {
360
- console.log(`✅ Request exitoso (204 No Content): ${endpoint}`);
361
- return {};
102
+ if (data && method !== "GET") {
103
+ fetchOptions.body = JSON.stringify(data);
104
+ console.log(`📤 ${method} Body:`, data);
362
105
  }
106
+ console.log(`🌐 ${method} ${url}`, fetchOptions);
107
+ const response = await fetch(url, fetchOptions);
363
108
  if (!response.ok) {
364
109
  let errorData;
365
110
  try {
366
111
  errorData = await response.json();
367
112
  }
368
- catch (_b) {
113
+ catch (_a) {
369
114
  errorData = { message: response.statusText };
370
115
  }
371
116
  console.error(`❌ ${method} ${response.status}:`, errorData);
@@ -379,7 +124,7 @@ export class ApiClient {
379
124
  }
380
125
  const responseData = await parseResponse(response);
381
126
  if (useCache && method === "GET") {
382
- const cacheKey = generateCacheKey(method, primaryUrl, data);
127
+ const cacheKey = generateCacheKey(method, url, data);
383
128
  const cacheTime = options.cacheTime || undefined;
384
129
  this.cache.set(cacheKey, responseData, cacheTime);
385
130
  if (this.debug) {
@@ -387,7 +132,7 @@ export class ApiClient {
387
132
  }
388
133
  }
389
134
  this.eventEmitter.emit("afterRequest", {
390
- url: primaryUrl,
135
+ url,
391
136
  method,
392
137
  response: responseData,
393
138
  });
@@ -395,7 +140,7 @@ export class ApiClient {
395
140
  }
396
141
  catch (error) {
397
142
  this.eventEmitter.emit("requestError", {
398
- url: primaryUrl,
143
+ url,
399
144
  method,
400
145
  error,
401
146
  });
package/dist/index.d.ts CHANGED
@@ -12,7 +12,6 @@ import { ClassificationTypesApi } from "./modules/legacy/classificationtypes/cla
12
12
  */
13
13
  export declare class ClmSdk {
14
14
  private apiClient;
15
- private legacyClient;
16
15
  private eventEmitter;
17
16
  private cacheInstance;
18
17
  auth: AuthApi;
@@ -23,8 +22,6 @@ export declare class ClmSdk {
23
22
  areas: AreasApi;
24
23
  classificationTypes: ClassificationTypesApi;
25
24
  constructor(config: Partial<SdkConfig>);
26
- legacyLogin(userName: string, password: string): Promise<import("./core/legacy-api-client").LegacyLoginResponse>;
27
- legacyLogout(): void;
28
25
  /**
29
26
  * Access to events system
30
27
  */
@@ -43,6 +40,5 @@ export * from "./modules/v1/auth/types";
43
40
  export * from "./modules/v1/users/types";
44
41
  export * from "./modules/v1/notifications/types";
45
42
  export * from "./modules/v1/_logs/types";
46
- export * from "./core/legacy-api-client";
47
43
  export * from "./modules/legacy/areas/types";
48
44
  export * from "./modules/legacy/classificationtypes/types";
package/dist/index.js CHANGED
@@ -11,7 +11,6 @@ import { LogsApi } from "./modules/v1/_logs/logs-api";
11
11
  // Legacy
12
12
  import { AreasApi } from "./modules/legacy/areas/areas-api";
13
13
  import { ClassificationTypesApi } from "./modules/legacy/classificationtypes/classificationtypes-api";
14
- import { LegacyApiClient } from "./core/legacy-api-client";
15
14
  /**
16
15
  * Main SDK for consuming CLM API
17
16
  */
@@ -31,7 +30,6 @@ export class ClmSdk {
31
30
  // Initialize core utilities
32
31
  this.cacheInstance = new Cache((_a = fullConfig.cache) === null || _a === void 0 ? void 0 : _a.ttl);
33
32
  this.apiClient = new ApiClient(fullConfig, this.eventEmitter);
34
- this.legacyClient = new LegacyApiClient("http://216.250.117.119/ZeroServicesQA/api/v1");
35
33
  // Initialize modules v1
36
34
  this.auth = new AuthApi(this.apiClient);
37
35
  this.users = new UsersApi(this.apiClient);
@@ -42,12 +40,6 @@ export class ClmSdk {
42
40
  this.areas = new AreasApi(this.apiClient);
43
41
  this.classificationTypes = new ClassificationTypesApi(this.apiClient);
44
42
  }
45
- async legacyLogin(userName, password) {
46
- return await this.legacyClient.login(userName, password);
47
- }
48
- legacyLogout() {
49
- this.legacyClient.logout();
50
- }
51
43
  /**
52
44
  * Access to events system
53
45
  */
@@ -63,6 +55,5 @@ export * from "./modules/v1/users/types";
63
55
  export * from "./modules/v1/notifications/types";
64
56
  export * from "./modules/v1/_logs/types";
65
57
  // Export legacy types
66
- export * from "./core/legacy-api-client";
67
58
  export * from "./modules/legacy/areas/types";
68
59
  export * from "./modules/legacy/classificationtypes/types";
@@ -1,13 +1,10 @@
1
1
  import { ApiClient } from "../../../core/api-client";
2
2
  import { LoginCredentials, LoginResponse, RefreshTokenRequest } from "./types";
3
+ type LoginMode = "new" | "legacy";
3
4
  export declare class AuthApi {
4
5
  private apiClient;
5
6
  constructor(apiClient: ApiClient);
6
- /**
7
- * Login con POST JSON (evita el modal del navegador).
8
- * El servidor setea cookie HttpOnly (zero_token).
9
- */
10
- login(credentials: LoginCredentials): Promise<{
7
+ login(credentials: LoginCredentials, mode?: LoginMode): Promise<{
11
8
  ok: boolean;
12
9
  }>;
13
10
  refreshToken(request?: RefreshTokenRequest): Promise<LoginResponse>;
@@ -15,3 +12,4 @@ export declare class AuthApi {
15
12
  isAuthenticated(): boolean;
16
13
  setToken(token: string | null): void;
17
14
  }
15
+ export {};
@@ -2,40 +2,42 @@ export class AuthApi {
2
2
  constructor(apiClient) {
3
3
  this.apiClient = apiClient;
4
4
  }
5
- /**
6
- * Login con POST JSON (evita el modal del navegador).
7
- * El servidor setea cookie HttpOnly (zero_token).
8
- */
9
- async login(credentials) {
10
- try {
11
- const response = await fetch(`${this.apiClient['baseUrl']}/auth/login`, {
12
- method: 'POST',
13
- headers: {
14
- 'Content-Type': 'application/json',
15
- 'X-Organization': this.apiClient['organization'] || 'default-org'
16
- },
17
- credentials: 'include', // ← Importante para cookies
18
- body: JSON.stringify({
19
- email: credentials.email,
20
- password: credentials.password
21
- })
22
- });
23
- if (!response.ok) {
24
- if (response.status === 401) {
25
- throw new Error('Invalid credentials');
5
+ async login(credentials, mode = "new") {
6
+ var _a;
7
+ const path = mode === "legacy" ? "/legacy/login" : "/auth/login";
8
+ const response = await fetch(`${this.apiClient["baseUrl"]}${path}`, {
9
+ method: "POST",
10
+ headers: {
11
+ "Content-Type": "application/json",
12
+ "X-Organization": this.apiClient["organization"] || "default-org",
13
+ },
14
+ credentials: "include",
15
+ body: JSON.stringify({
16
+ email: credentials.email,
17
+ password: credentials.password,
18
+ }),
19
+ });
20
+ if (!response.ok) {
21
+ if (response.status === 401)
22
+ throw new Error("Invalid credentials");
23
+ throw new Error(`Login failed: ${response.status}`);
24
+ }
25
+ const data = await response.json().catch(() => null);
26
+ // ✅ Si es legacy, guarda Bearer token para siguientes llamadas legacy
27
+ if (mode === "legacy") {
28
+ const legacyToken = ((_a = data === null || data === void 0 ? void 0 : data.dataResult) === null || _a === void 0 ? void 0 : _a.token) || (data === null || data === void 0 ? void 0 : data.token);
29
+ if (legacyToken) {
30
+ if (typeof sessionStorage !== "undefined") {
31
+ sessionStorage.setItem("legacy_token", legacyToken);
32
+ }
33
+ if (typeof window !== "undefined") {
34
+ window.__LEGACY_TOKEN__ = legacyToken;
26
35
  }
27
- throw new Error(`Login failed: ${response.status}`);
28
36
  }
29
- const data = await response.json();
30
- // No guardar token en memoria, solo usar cookie
31
- this.apiClient.setToken(null);
32
- console.log('✅ Login exitoso, cookie establecida');
33
- return { ok: true };
34
- }
35
- catch (error) {
36
- console.error('❌ SDK Login error:', error);
37
- throw error;
38
37
  }
38
+ // ✅ Nuevo: cookie HttpOnly, no guardes token en memoria del SDK
39
+ this.apiClient.setToken(null);
40
+ return { ok: true };
39
41
  }
40
42
  async refreshToken(request) {
41
43
  const response = await this.apiClient.post("/auth/refresh", request);
@@ -47,15 +49,24 @@ export class AuthApi {
47
49
  try {
48
50
  await this.apiClient.post("/auth/logout");
49
51
  }
50
- catch (error) {
51
- console.error("Error during logout:", error);
52
- }
53
52
  finally {
53
+ // limpia token nuevo
54
54
  this.apiClient.setToken(null);
55
+ // limpia legacy token
56
+ if (typeof sessionStorage !== "undefined") {
57
+ sessionStorage.removeItem("legacy_token");
58
+ }
59
+ if (typeof window !== "undefined") {
60
+ delete window.__LEGACY_TOKEN__;
61
+ }
55
62
  }
56
63
  }
57
64
  isAuthenticated() {
58
- return this.apiClient.getToken() !== null;
65
+ const hasToken = this.apiClient.getToken() !== null;
66
+ const hasLegacy = (typeof sessionStorage !== "undefined" &&
67
+ !!sessionStorage.getItem("legacy_token")) ||
68
+ (typeof window !== "undefined" && !!window.__LEGACY_TOKEN__);
69
+ return hasToken || hasLegacy;
59
70
  }
60
71
  setToken(token) {
61
72
  this.apiClient.setToken(token);
@@ -1,6 +1,5 @@
1
1
  export interface SdkConfig {
2
2
  baseUrl: string;
3
- fallbackBaseUrl?: string;
4
3
  organization: string;
5
4
  token?: string | null;
6
5
  cache?: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zerosls/clm-sdk",
3
- "version": "1.1.9",
3
+ "version": "1.1.10",
4
4
  "description": "SDK for ZeroCLM API",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,4 +1,3 @@
1
- // core/api-client.ts
2
1
  import { SdkConfig, SdkEventType, SdkEvents } from "../types/sdk";
3
2
  import { PaginatedResponse, RequestOptions } from "../types/common";
4
3
  import { EventEmitter } from "./event-emitter";
@@ -13,7 +12,6 @@ import {
13
12
 
14
13
  export class ApiClient {
15
14
  private baseUrl: string;
16
- private fallbackBaseUrl: string; // ✅ URL de respaldo
17
15
  private organization: string;
18
16
  private token: string | null = null;
19
17
  private eventEmitter: EventEmitter;
@@ -24,8 +22,6 @@ export class ApiClient {
24
22
 
25
23
  constructor(config: SdkConfig, eventEmitter: EventEmitter) {
26
24
  this.baseUrl = config.baseUrl;
27
- this.fallbackBaseUrl =
28
- config.fallbackBaseUrl || "http://216.250.117.119/ZeroServicesQA/api/v1";
29
25
  this.organization = config.organization;
30
26
  this.token = config.token || null;
31
27
  this.eventEmitter = eventEmitter;
@@ -126,185 +122,6 @@ export class ApiClient {
126
122
  }
127
123
  }
128
124
 
129
- /*private async request<T>(
130
- method: string,
131
- endpoint: string,
132
- data?: any,
133
- params?: Record<string, any>,
134
- options: RequestOptions = {}
135
- ): Promise<T> {
136
- // ✅ Primer intento con baseUrl normal
137
- const primaryUrl = buildUrl(this.baseUrl, endpoint, params);
138
-
139
- const base: HeadersInit = buildHeaders(this.token, {
140
- "X-Organization": this.organization,
141
- ...(options.headers || {}),
142
- });
143
-
144
- const headers = new Headers(base);
145
-
146
- // ✅ Obtener token legacy
147
- const legacyToken =
148
- (window as any).__LEGACY_TOKEN__ ||
149
- sessionStorage.getItem("legacy_token") ||
150
- null;
151
-
152
- if (legacyToken) {
153
- headers.set("Authorization", `Bearer ${legacyToken}`);
154
- if (this.debug) {
155
- console.log("🔐 Using legacy token for:", endpoint);
156
- }
157
- } else if (this.token) {
158
- if (this.debug) {
159
- console.log("🔐 Using v1 token for:", endpoint);
160
- }
161
- } else {
162
- console.warn("⚠️ No token available for endpoint:", endpoint);
163
- }
164
-
165
- const useCache = this.cacheEnabled && options.useCache !== false;
166
- if (useCache && method === "GET") {
167
- const cacheKey = generateCacheKey(method, primaryUrl, data);
168
- const cachedData = this.cache.get<T>(cacheKey);
169
- if (cachedData) {
170
- if (this.debug) {
171
- console.log(`[SDK-Cache] Hit: ${cacheKey}`);
172
- }
173
- return cachedData;
174
- }
175
- }
176
-
177
- this.eventEmitter.emit("beforeRequest", {
178
- url: primaryUrl,
179
- method,
180
- data,
181
- });
182
-
183
- try {
184
- const fetchOptions: RequestInit = {
185
- method,
186
- headers,
187
- credentials: "include",
188
- };
189
-
190
- if (data && method !== "GET") {
191
- fetchOptions.body = JSON.stringify(data);
192
- if (this.debug) {
193
- console.log(`📤 ${method} Body:`, data);
194
- }
195
- }
196
-
197
- if (this.debug) {
198
- console.log(`🌐 ${method} ${primaryUrl}`);
199
- }
200
-
201
- // ✅ Primer intento
202
- const response = await fetch(primaryUrl, fetchOptions);
203
-
204
- // ✅ Si es 404, intentar con fallback URL
205
- if (response.status === 404) {
206
- console.warn(`⚠️ 404 en ${primaryUrl}, intentando con fallback...`);
207
-
208
- const fallbackUrl = buildUrl(this.fallbackBaseUrl, endpoint, params);
209
-
210
- if (this.debug) {
211
- console.log(`🔄 Retry: ${method} ${fallbackUrl}`);
212
- }
213
-
214
- // ✅ Segundo intento con fallback
215
- const fallbackResponse = await fetch(fallbackUrl, fetchOptions);
216
-
217
- if (!fallbackResponse.ok) {
218
- let errorData;
219
- try {
220
- errorData = await fallbackResponse.json();
221
- } catch {
222
- errorData = { message: fallbackResponse.statusText };
223
- }
224
-
225
- console.error(`❌ Fallback también falló ${fallbackResponse.status}:`, errorData);
226
-
227
- if (fallbackResponse.status === 401) {
228
- this.eventEmitter.emit("authError", {
229
- statusCode: 401,
230
- message: errorData.message || "Authentication required",
231
- });
232
- }
233
-
234
- return errorData as T;
235
- }
236
-
237
- // ✅ Fallback exitoso
238
- const fallbackData = await parseResponse<T>(fallbackResponse);
239
-
240
- console.log(`✅ Fallback exitoso para: ${endpoint}`);
241
-
242
- this.eventEmitter.emit("afterRequest", {
243
- url: fallbackUrl,
244
- method,
245
- response: fallbackData,
246
- });
247
-
248
- return fallbackData;
249
- }
250
-
251
- // ✅ Otros errores (no 404)
252
- if (!response.ok) {
253
- let errorData;
254
- try {
255
- errorData = await response.json();
256
- } catch {
257
- errorData = { message: response.statusText };
258
- }
259
-
260
- console.error(`❌ ${method} ${response.status}:`, errorData);
261
-
262
- if (response.status === 401) {
263
- this.eventEmitter.emit("authError", {
264
- statusCode: 401,
265
- message: errorData.message || "Authentication required",
266
- });
267
- }
268
-
269
- return errorData as T;
270
- }
271
-
272
- // ✅ Respuesta exitosa del primer intento
273
- const responseData = await parseResponse<T>(response);
274
-
275
- if (useCache && method === "GET") {
276
- const cacheKey = generateCacheKey(method, primaryUrl, data);
277
- const cacheTime = options.cacheTime || undefined;
278
- this.cache.set(cacheKey, responseData, cacheTime);
279
-
280
- if (this.debug) {
281
- console.log(`[SDK-Cache] Set: ${cacheKey}`);
282
- }
283
- }
284
-
285
- this.eventEmitter.emit("afterRequest", {
286
- url: primaryUrl,
287
- method,
288
- response: responseData,
289
- });
290
-
291
- return responseData;
292
- } catch (error) {
293
- this.eventEmitter.emit("requestError", {
294
- url: primaryUrl,
295
- method,
296
- error,
297
- });
298
-
299
- if (error instanceof ApiError) {
300
- throw error;
301
- }
302
-
303
- throw new ApiError((error as Error).message || "Network error", 0, {
304
- originalError: error,
305
- });
306
- }
307
- }*/
308
125
  private async request<T>(
309
126
  method: string,
310
127
  endpoint: string,
@@ -312,49 +129,38 @@ export class ApiClient {
312
129
  params?: Record<string, any>,
313
130
  options: RequestOptions = {}
314
131
  ): Promise<T> {
315
- const primaryUrl = buildUrl(this.baseUrl, endpoint, params);
132
+ const url = buildUrl(this.baseUrl, endpoint, params);
316
133
 
317
- const baseHeaders: HeadersInit = buildHeaders(this.token, {
134
+ const base: HeadersInit = buildHeaders(this.token, {
318
135
  "X-Organization": this.organization,
319
136
  ...(options.headers || {}),
320
137
  });
321
138
 
322
- // Función helper para debug de headers
323
- const headersToObject = (headers: Headers): Record<string, string> => {
324
- const obj: Record<string, string> = {};
325
- headers.forEach((value, key) => {
326
- obj[key] = value;
327
- });
328
- return obj;
329
- };
139
+ const headers = new Headers(base);
330
140
 
331
- const createHeaders = (): Headers => {
332
- const headers = new Headers(baseHeaders);
141
+ const legacyPattern = /(^|\/)legacy(\/|$)/i;
142
+ const isLegacyEndpoint = legacyPattern.test(endpoint);
143
+ const isLegacyLogin = /(^|\/)legacy\/login$/i.test(endpoint);
333
144
 
145
+ if (isLegacyEndpoint && !isLegacyLogin) {
334
146
  const legacyToken =
335
- (window as any).__LEGACY_TOKEN__ ||
336
- sessionStorage.getItem("legacy_token") ||
147
+ (typeof window !== "undefined" && (window as any).__LEGACY_TOKEN__) ||
148
+ (typeof sessionStorage !== "undefined" &&
149
+ sessionStorage.getItem("legacy_token")) ||
337
150
  null;
338
151
 
339
152
  if (legacyToken) {
340
153
  headers.set("Authorization", `Bearer ${legacyToken}`);
341
- if (this.debug) {
342
- console.log("🔐 Using legacy token for:", endpoint);
343
- }
344
- } else if (this.token) {
345
- if (this.debug) {
346
- console.log("🔐 Using v1 token for:", endpoint);
347
- }
348
- } else {
349
- console.warn("⚠️ No token available for endpoint:", endpoint);
350
154
  }
155
+ }
351
156
 
352
- return headers;
353
- };
157
+ if (!isLegacyEndpoint && !this.token) {
158
+ headers.delete("Authorization");
159
+ }
354
160
 
355
161
  const useCache = this.cacheEnabled && options.useCache !== false;
356
162
  if (useCache && method === "GET") {
357
- const cacheKey = generateCacheKey(method, primaryUrl, data);
163
+ const cacheKey = generateCacheKey(method, url, data);
358
164
  const cachedData = this.cache.get<T>(cacheKey);
359
165
  if (cachedData) {
360
166
  if (this.debug) {
@@ -365,105 +171,25 @@ export class ApiClient {
365
171
  }
366
172
 
367
173
  this.eventEmitter.emit("beforeRequest", {
368
- url: primaryUrl,
174
+ url,
369
175
  method,
370
176
  data,
371
177
  });
372
178
 
373
179
  try {
374
- let body: string | undefined;
375
- if (data && method !== "GET") {
376
- body = JSON.stringify(data);
377
- if (this.debug) {
378
- console.log(`📤 ${method} Body:`, data);
379
- }
380
- }
381
-
382
- // ✅ Primer intento
383
- const headers1 = createHeaders();
384
- const fetchOptions1: RequestInit = {
180
+ const fetchOptions: RequestInit = {
385
181
  method,
386
- headers: headers1,
387
- credentials: "include",
388
- ...(body && { body }),
182
+ headers,
183
+ credentials: this.credentials,
389
184
  };
390
185
 
391
- if (this.debug) {
392
- console.log(`🌐 ${method} ${primaryUrl}`);
393
- console.log("📋 Headers:", headersToObject(headers1)); // ✅ CORREGIDO
394
- }
395
-
396
- const response = await fetch(primaryUrl, fetchOptions1);
397
-
398
- if (response.status === 404) {
399
- console.warn(`⚠️ 404 en ${primaryUrl}, intentando con fallback...`);
400
-
401
- const fallbackUrl = buildUrl(this.fallbackBaseUrl, endpoint, params);
402
-
403
- if (this.debug) {
404
- console.log(`🔄 Retry: ${method} ${fallbackUrl}`);
405
- }
406
-
407
- // ✅ Segundo intento
408
- const headers2 = createHeaders();
409
- const fetchOptions2: RequestInit = {
410
- method,
411
- headers: headers2,
412
- credentials: "include",
413
- ...(body && { body }),
414
- };
415
-
416
- if (this.debug) {
417
- console.log("📋 Fallback Headers:", headersToObject(headers2)); // ✅ CORREGIDO
418
- }
419
-
420
- const fallbackResponse = await fetch(fallbackUrl, fetchOptions2);
421
-
422
- if (fallbackResponse.status === 204) {
423
- console.log(`✅ Fallback exitoso (204 No Content): ${endpoint}`);
424
- return {} as T;
425
- }
426
-
427
- if (!fallbackResponse.ok) {
428
- let errorData;
429
- try {
430
- errorData = await fallbackResponse.json();
431
- } catch {
432
- errorData = { message: fallbackResponse.statusText };
433
- }
434
-
435
- console.error(
436
- `❌ Fallback falló ${fallbackResponse.status}:`,
437
- errorData
438
- );
439
-
440
- if (fallbackResponse.status === 401) {
441
- this.eventEmitter.emit("authError", {
442
- statusCode: 401,
443
- message: errorData.message || "Authentication required",
444
- });
445
- }
446
-
447
- return errorData as T;
448
- }
449
-
450
- const fallbackData = await parseResponse<T>(fallbackResponse);
451
-
452
- console.log(`✅ Fallback exitoso: ${endpoint}`);
453
-
454
- this.eventEmitter.emit("afterRequest", {
455
- url: fallbackUrl,
456
- method,
457
- response: fallbackData,
458
- });
459
-
460
- return fallbackData;
186
+ if (data && method !== "GET") {
187
+ fetchOptions.body = JSON.stringify(data);
188
+ console.log(`📤 ${method} Body:`, data);
461
189
  }
462
190
 
463
- if (response.status === 204) {
464
- console.log(`✅ Request exitoso (204 No Content): ${endpoint}`);
465
- return {} as T;
466
- }
191
+ console.log(`🌐 ${method} ${url}`, fetchOptions);
192
+ const response = await fetch(url, fetchOptions);
467
193
 
468
194
  if (!response.ok) {
469
195
  let errorData;
@@ -488,7 +214,7 @@ export class ApiClient {
488
214
  const responseData = await parseResponse<T>(response);
489
215
 
490
216
  if (useCache && method === "GET") {
491
- const cacheKey = generateCacheKey(method, primaryUrl, data);
217
+ const cacheKey = generateCacheKey(method, url, data);
492
218
  const cacheTime = options.cacheTime || undefined;
493
219
  this.cache.set(cacheKey, responseData, cacheTime);
494
220
 
@@ -498,7 +224,7 @@ export class ApiClient {
498
224
  }
499
225
 
500
226
  this.eventEmitter.emit("afterRequest", {
501
- url: primaryUrl,
227
+ url,
502
228
  method,
503
229
  response: responseData,
504
230
  });
@@ -506,7 +232,7 @@ export class ApiClient {
506
232
  return responseData;
507
233
  } catch (error) {
508
234
  this.eventEmitter.emit("requestError", {
509
- url: primaryUrl,
235
+ url,
510
236
  method,
511
237
  error,
512
238
  });
package/src/index.ts CHANGED
@@ -15,14 +15,12 @@ import { LogsApi } from "./modules/v1/_logs/logs-api";
15
15
  // Legacy
16
16
  import { AreasApi } from "./modules/legacy/areas/areas-api";
17
17
  import { ClassificationTypesApi } from "./modules/legacy/classificationtypes/classificationtypes-api";
18
- import { LegacyApiClient } from "./core/legacy-api-client";
19
18
 
20
19
  /**
21
20
  * Main SDK for consuming CLM API
22
21
  */
23
22
  export class ClmSdk {
24
23
  private apiClient: ApiClient;
25
- private legacyClient: LegacyApiClient;
26
24
  private eventEmitter: EventEmitter;
27
25
  private cacheInstance: Cache;
28
26
 
@@ -47,10 +45,6 @@ export class ClmSdk {
47
45
  this.cacheInstance = new Cache(fullConfig.cache?.ttl);
48
46
  this.apiClient = new ApiClient(fullConfig, this.eventEmitter);
49
47
 
50
- this.legacyClient = new LegacyApiClient(
51
- "http://216.250.117.119/ZeroServicesQA/api/v1"
52
- );
53
-
54
48
  // Initialize modules v1
55
49
  this.auth = new AuthApi(this.apiClient);
56
50
  this.users = new UsersApi(this.apiClient);
@@ -63,13 +57,6 @@ export class ClmSdk {
63
57
  this.classificationTypes = new ClassificationTypesApi(this.apiClient);
64
58
  }
65
59
 
66
- async legacyLogin(userName: string, password: string) {
67
- return await this.legacyClient.login(userName, password);
68
- }
69
-
70
- legacyLogout(): void {
71
- this.legacyClient.logout();
72
- }
73
60
 
74
61
  /**
75
62
  * Access to events system
@@ -100,6 +87,5 @@ export * from "./modules/v1/notifications/types";
100
87
  export * from "./modules/v1/_logs/types";
101
88
 
102
89
  // Export legacy types
103
- export * from "./core/legacy-api-client";
104
90
  export * from "./modules/legacy/areas/types";
105
91
  export * from "./modules/legacy/classificationtypes/types";
@@ -1,7 +1,8 @@
1
- // auth-api.ts
2
- import { ApiClient } from "../../../core/api-client";
1
+ import { ApiClient } from "../../../core/api-client";
3
2
  import { LoginCredentials, LoginResponse, RefreshTokenRequest } from "./types";
4
3
 
4
+ type LoginMode = "new" | "legacy";
5
+
5
6
  export class AuthApi {
6
7
  private apiClient: ApiClient;
7
8
 
@@ -9,67 +10,90 @@ export class AuthApi {
9
10
  this.apiClient = apiClient;
10
11
  }
11
12
 
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');
13
+ async login(
14
+ credentials: LoginCredentials,
15
+ mode: LoginMode = "new"
16
+ ): Promise<{ ok: boolean }> {
17
+ const path = mode === "legacy" ? "/legacy/login" : "/auth/login";
18
+
19
+ const response = await fetch(`${this.apiClient["baseUrl"]}${path}`, {
20
+ method: "POST",
21
+ headers: {
22
+ "Content-Type": "application/json",
23
+ "X-Organization": this.apiClient["organization"] || "default-org",
24
+ },
25
+ credentials: "include",
26
+ body: JSON.stringify({
27
+ email: credentials.email,
28
+ password: credentials.password,
29
+ }),
30
+ });
31
+
32
+ if (!response.ok) {
33
+ if (response.status === 401) throw new Error("Invalid credentials");
34
+ throw new Error(`Login failed: ${response.status}`);
35
+ }
36
+
37
+ const data: any = await response.json().catch(() => null);
38
+
39
+ // ✅ Si es legacy, guarda Bearer token para siguientes llamadas legacy
40
+ if (mode === "legacy") {
41
+ const legacyToken = data?.dataResult?.token || data?.token;
42
+
43
+ if (legacyToken) {
44
+ if (typeof sessionStorage !== "undefined") {
45
+ sessionStorage.setItem("legacy_token", legacyToken);
46
+ }
47
+ if (typeof window !== "undefined") {
48
+ (window as any).__LEGACY_TOKEN__ = legacyToken;
34
49
  }
35
- throw new Error(`Login failed: ${response.status}`);
36
50
  }
51
+ }
37
52
 
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 };
53
+ // Nuevo: cookie HttpOnly, no guardes token en memoria del SDK
54
+ this.apiClient.setToken(null);
45
55
 
46
- } catch (error) {
47
- console.error('❌ SDK Login error:', error);
48
- throw error;
49
- }
56
+ return { ok: true };
50
57
  }
51
58
 
52
59
  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);
60
+ const response = await this.apiClient.post<LoginResponse>(
61
+ "/auth/refresh",
62
+ request
63
+ );
64
+ if ((response as any)?.token)
65
+ this.apiClient.setToken((response as any).token);
55
66
  return response;
56
67
  }
57
68
 
58
69
  async logout(): Promise<void> {
59
70
  try {
60
71
  await this.apiClient.post<void>("/auth/logout");
61
- } catch (error) {
62
- console.error("Error during logout:", error);
63
72
  } finally {
73
+ // limpia token nuevo
64
74
  this.apiClient.setToken(null);
75
+
76
+ // limpia legacy token
77
+ if (typeof sessionStorage !== "undefined") {
78
+ sessionStorage.removeItem("legacy_token");
79
+ }
80
+ if (typeof window !== "undefined") {
81
+ delete (window as any).__LEGACY_TOKEN__;
82
+ }
65
83
  }
66
84
  }
67
85
 
68
86
  isAuthenticated(): boolean {
69
- return this.apiClient.getToken() !== null;
87
+ const hasToken = this.apiClient.getToken() !== null;
88
+ const hasLegacy =
89
+ (typeof sessionStorage !== "undefined" &&
90
+ !!sessionStorage.getItem("legacy_token")) ||
91
+ (typeof window !== "undefined" && !!(window as any).__LEGACY_TOKEN__);
92
+
93
+ return hasToken || hasLegacy;
70
94
  }
71
95
 
72
96
  setToken(token: string | null): void {
73
97
  this.apiClient.setToken(token);
74
98
  }
75
- }
99
+ }
package/src/types/sdk.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  export interface SdkConfig {
2
2
  baseUrl: string;
3
- fallbackBaseUrl?: string;
4
3
  organization: string;
5
4
  token?: string | null;
6
5
  cache?: {
@@ -1,26 +0,0 @@
1
- export interface LegacyLoginRequest {
2
- userName: string;
3
- password: string;
4
- }
5
- export interface LegacyLoginResponse {
6
- dataResult: {
7
- token: string;
8
- userType: string;
9
- userId: string;
10
- userName: string;
11
- area: string;
12
- id_Area: number;
13
- id_Role: string;
14
- };
15
- statusResponse: {
16
- code: number;
17
- success: boolean;
18
- message: string;
19
- };
20
- }
21
- export declare class LegacyApiClient {
22
- private baseUrl;
23
- constructor(baseUrl: string);
24
- login(userName: string, password: string): Promise<LegacyLoginResponse>;
25
- logout(): void;
26
- }
@@ -1,35 +0,0 @@
1
- export class LegacyApiClient {
2
- constructor(baseUrl) {
3
- this.baseUrl = baseUrl;
4
- }
5
- async login(userName, password) {
6
- var _a, _b;
7
- const url = `${this.baseUrl}/auth/login`;
8
- const response = await fetch(url, {
9
- method: 'POST',
10
- headers: { 'Content-Type': 'application/json' },
11
- credentials: 'include',
12
- body: JSON.stringify({ userName, password }),
13
- });
14
- if (!response.ok) {
15
- const errorData = await response.json().catch(() => ({
16
- statusResponse: {
17
- code: response.status,
18
- success: false,
19
- message: response.statusText
20
- }
21
- }));
22
- throw new Error(((_a = errorData.statusResponse) === null || _a === void 0 ? void 0 : _a.message) || 'Legacy login failed');
23
- }
24
- const data = await response.json();
25
- if ((_b = data.dataResult) === null || _b === void 0 ? void 0 : _b.token) {
26
- sessionStorage.setItem('legacy_token', data.dataResult.token);
27
- window.__LEGACY_TOKEN__ = data.dataResult.token;
28
- }
29
- return data;
30
- }
31
- logout() {
32
- sessionStorage.removeItem('legacy_token');
33
- delete window.__LEGACY_TOKEN__;
34
- }
35
- }
@@ -1,66 +0,0 @@
1
- export interface LegacyLoginRequest {
2
- userName: string;
3
- password: string;
4
- }
5
-
6
- export interface LegacyLoginResponse {
7
- dataResult: {
8
- token: string;
9
- userType: string;
10
- userId: string;
11
- userName: string;
12
- area: string;
13
- id_Area: number;
14
- id_Role: string;
15
- };
16
- statusResponse: {
17
- code: number;
18
- success: boolean;
19
- message: string;
20
- };
21
- }
22
-
23
- export class LegacyApiClient {
24
- private baseUrl: string;
25
-
26
- constructor(baseUrl: string) {
27
- this.baseUrl = baseUrl;
28
- }
29
-
30
- async login(userName: string, password: string): Promise<LegacyLoginResponse> {
31
- const url = `${this.baseUrl}/auth/login`;
32
-
33
- const response = await fetch(url, {
34
- method: 'POST',
35
- headers: { 'Content-Type': 'application/json' },
36
- credentials: 'include',
37
- body: JSON.stringify({ userName, password }),
38
- });
39
-
40
- if (!response.ok) {
41
- const errorData = await response.json().catch(() => ({
42
- statusResponse: {
43
- code: response.status,
44
- success: false,
45
- message: response.statusText
46
- }
47
- }));
48
-
49
- throw new Error(errorData.statusResponse?.message || 'Legacy login failed');
50
- }
51
-
52
- const data: LegacyLoginResponse = await response.json();
53
-
54
- if (data.dataResult?.token) {
55
- sessionStorage.setItem('legacy_token', data.dataResult.token);
56
- (window as any).__LEGACY_TOKEN__ = data.dataResult.token;
57
- }
58
-
59
- return data;
60
- }
61
-
62
- logout(): void {
63
- sessionStorage.removeItem('legacy_token');
64
- delete (window as any).__LEGACY_TOKEN__;
65
- }
66
- }