falconhub-apilibrary 1.3.1-dev.94 → 1.3.1-dev.96
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/dist/index.d.mts +100 -36
- package/dist/index.mjs +77 -25
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -500,6 +500,7 @@ interface UserAuthUpdateRequest {
|
|
|
500
500
|
* Interfaz que representa un tipo de usuario.
|
|
501
501
|
*/
|
|
502
502
|
interface UserType {
|
|
503
|
+
userTypeId: number;
|
|
503
504
|
userType: string;
|
|
504
505
|
key?: string;
|
|
505
506
|
description?: string;
|
|
@@ -1124,18 +1125,13 @@ interface LocationsFilter {
|
|
|
1124
1125
|
interface InventoryStatus {
|
|
1125
1126
|
inventoryStatusId: number;
|
|
1126
1127
|
inventoryStatus: string;
|
|
1128
|
+
key: string;
|
|
1127
1129
|
description: string;
|
|
1128
|
-
createdAt: string | null;
|
|
1129
|
-
updatedAt: string | null;
|
|
1130
|
-
deleted: boolean | null;
|
|
1131
1130
|
}
|
|
1132
1131
|
interface InventoryStatusRequest {
|
|
1133
|
-
|
|
1132
|
+
key?: string;
|
|
1134
1133
|
inventoryStatus: string;
|
|
1135
1134
|
description: string;
|
|
1136
|
-
createdAt?: string;
|
|
1137
|
-
updatedAt?: string;
|
|
1138
|
-
deleted?: boolean;
|
|
1139
1135
|
}
|
|
1140
1136
|
interface InventoryStatusesFilter {
|
|
1141
1137
|
Search?: string;
|
|
@@ -1149,30 +1145,30 @@ interface InventoryStatusesFilter {
|
|
|
1149
1145
|
interface Packing {
|
|
1150
1146
|
packingId: number;
|
|
1151
1147
|
packing: string;
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1148
|
+
key: string;
|
|
1149
|
+
materialId: number;
|
|
1150
|
+
length: number;
|
|
1151
|
+
width: number;
|
|
1152
|
+
height: number;
|
|
1156
1153
|
weightLimit: number | null;
|
|
1157
|
-
cost: number
|
|
1158
|
-
providerId: number
|
|
1159
|
-
isActive:
|
|
1160
|
-
createdAt: string | null;
|
|
1161
|
-
updatedAt: string | null;
|
|
1162
|
-
deleted: boolean | null;
|
|
1154
|
+
cost: number;
|
|
1155
|
+
providerId: number;
|
|
1156
|
+
isActive: boolean;
|
|
1163
1157
|
}
|
|
1164
1158
|
/**
|
|
1165
1159
|
* Request para crear o actualizar un empaque.
|
|
1166
1160
|
*/
|
|
1167
1161
|
interface PackingRequest {
|
|
1168
1162
|
packing: string;
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1163
|
+
key?: string;
|
|
1164
|
+
materialId: number;
|
|
1165
|
+
length: number;
|
|
1166
|
+
width: number;
|
|
1167
|
+
height: number;
|
|
1173
1168
|
weightLimit?: number;
|
|
1174
|
-
cost
|
|
1175
|
-
providerId
|
|
1169
|
+
cost: number;
|
|
1170
|
+
providerId: number;
|
|
1171
|
+
isActive: boolean;
|
|
1176
1172
|
}
|
|
1177
1173
|
/**
|
|
1178
1174
|
* Filtros disponibles para buscar empaques.
|
|
@@ -1191,12 +1187,10 @@ interface PackingsFilter {
|
|
|
1191
1187
|
interface Material {
|
|
1192
1188
|
materialId: number;
|
|
1193
1189
|
material: string;
|
|
1190
|
+
key: string;
|
|
1194
1191
|
description: string;
|
|
1195
|
-
isRecyclable: boolean
|
|
1196
|
-
isFragile: boolean
|
|
1197
|
-
createdAt: string | null;
|
|
1198
|
-
updatedAt: string | null;
|
|
1199
|
-
deleted: boolean | null;
|
|
1192
|
+
isRecyclable: boolean;
|
|
1193
|
+
isFragile: boolean;
|
|
1200
1194
|
}
|
|
1201
1195
|
/**
|
|
1202
1196
|
* Request para crear o actualizar un material.
|
|
@@ -1204,8 +1198,9 @@ interface Material {
|
|
|
1204
1198
|
interface MaterialRequest {
|
|
1205
1199
|
material: string;
|
|
1206
1200
|
description: string;
|
|
1207
|
-
|
|
1208
|
-
|
|
1201
|
+
key?: string;
|
|
1202
|
+
isRecyclable: boolean;
|
|
1203
|
+
isFragile: boolean;
|
|
1209
1204
|
}
|
|
1210
1205
|
/**
|
|
1211
1206
|
* Filtros disponibles para buscar materiales.
|
|
@@ -1218,6 +1213,40 @@ interface MaterialsFilter {
|
|
|
1218
1213
|
IsFragile?: boolean;
|
|
1219
1214
|
}
|
|
1220
1215
|
|
|
1216
|
+
/**
|
|
1217
|
+
* Interfaz que representa un proveedor del inventario.
|
|
1218
|
+
*/
|
|
1219
|
+
interface InventoryProvider {
|
|
1220
|
+
providerId: number;
|
|
1221
|
+
provider: string;
|
|
1222
|
+
contactName: string;
|
|
1223
|
+
areaCodeId: number;
|
|
1224
|
+
contactNumber: string;
|
|
1225
|
+
contactEmail: string;
|
|
1226
|
+
isActive: boolean;
|
|
1227
|
+
createdAt: string | null;
|
|
1228
|
+
updatedAt: string | null;
|
|
1229
|
+
}
|
|
1230
|
+
/**
|
|
1231
|
+
* Request para crear o actualizar un proveedor.
|
|
1232
|
+
*/
|
|
1233
|
+
interface InventoryProviderRequest {
|
|
1234
|
+
provider: string;
|
|
1235
|
+
contactName: string;
|
|
1236
|
+
areaCodeId: number;
|
|
1237
|
+
contactNumber: string;
|
|
1238
|
+
contactEmail: string;
|
|
1239
|
+
isActive: boolean;
|
|
1240
|
+
}
|
|
1241
|
+
/**
|
|
1242
|
+
* Filtros disponibles para buscar proveedores.
|
|
1243
|
+
*/
|
|
1244
|
+
interface InventoryProvidersFilter {
|
|
1245
|
+
Search?: string;
|
|
1246
|
+
Provider?: string;
|
|
1247
|
+
IsActive?: boolean;
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1221
1250
|
/**
|
|
1222
1251
|
* Servicio para gestionar inventario: ubicaciones, estatus, empaques y materiales.
|
|
1223
1252
|
*/
|
|
@@ -1285,11 +1314,6 @@ declare class InventoryService {
|
|
|
1285
1314
|
* @param request - Nuevos datos del estatus
|
|
1286
1315
|
*/
|
|
1287
1316
|
updateStatus(id: number, request: InventoryStatusRequest): Promise<ResponseModel<InventoryStatus>>;
|
|
1288
|
-
/**
|
|
1289
|
-
* Activa o desactiva un estatus de inventario.
|
|
1290
|
-
* @param id - ID del estatus
|
|
1291
|
-
*/
|
|
1292
|
-
toggleStatusActive(id: number): Promise<ResponseModel<InventoryStatus>>;
|
|
1293
1317
|
/**
|
|
1294
1318
|
* Elimina un estatus de inventario.
|
|
1295
1319
|
* @param id - ID del estatus a eliminar
|
|
@@ -1320,6 +1344,11 @@ declare class InventoryService {
|
|
|
1320
1344
|
* @param request - Nuevos datos del empaque
|
|
1321
1345
|
*/
|
|
1322
1346
|
updatePacking(id: number, request: PackingRequest): Promise<ResponseModel<Packing>>;
|
|
1347
|
+
/**
|
|
1348
|
+
* Activa o desactiva un empaque.
|
|
1349
|
+
* @param id - ID del empaque
|
|
1350
|
+
*/
|
|
1351
|
+
togglePackingStatus(id: number): Promise<ResponseModel<Packing>>;
|
|
1323
1352
|
/**
|
|
1324
1353
|
* Elimina un empaque.
|
|
1325
1354
|
* @param id - ID del empaque a eliminar
|
|
@@ -1355,6 +1384,41 @@ declare class InventoryService {
|
|
|
1355
1384
|
* @param id - ID del material a eliminar
|
|
1356
1385
|
*/
|
|
1357
1386
|
deleteMaterial(id: number): Promise<ResponseModel<void>>;
|
|
1387
|
+
/**
|
|
1388
|
+
* Obtiene todos los proveedores con filtros opcionales.
|
|
1389
|
+
* @param filter - Filtros opcionales para la búsqueda
|
|
1390
|
+
*/
|
|
1391
|
+
getProviders(filter?: InventoryProvidersFilter): Promise<ResponseModel<InventoryProvider[]>>;
|
|
1392
|
+
/**
|
|
1393
|
+
* Obtiene el modelo de filtros disponibles para proveedores.
|
|
1394
|
+
*/
|
|
1395
|
+
getProviderFiltersModel(): Promise<ResponseModel<FilterGroupsModel>>;
|
|
1396
|
+
/**
|
|
1397
|
+
* Obtiene un proveedor por su ID.
|
|
1398
|
+
* @param id - ID del proveedor
|
|
1399
|
+
*/
|
|
1400
|
+
getProviderById(id: number): Promise<ResponseModel<InventoryProvider>>;
|
|
1401
|
+
/**
|
|
1402
|
+
* Crea un nuevo proveedor.
|
|
1403
|
+
* @param request - Datos del proveedor a crear
|
|
1404
|
+
*/
|
|
1405
|
+
createProvider(request: InventoryProviderRequest): Promise<ResponseModel<InventoryProvider>>;
|
|
1406
|
+
/**
|
|
1407
|
+
* Actualiza un proveedor existente.
|
|
1408
|
+
* @param id - ID del proveedor a actualizar
|
|
1409
|
+
* @param request - Nuevos datos del proveedor
|
|
1410
|
+
*/
|
|
1411
|
+
updateProvider(id: number, request: InventoryProviderRequest): Promise<ResponseModel<InventoryProvider>>;
|
|
1412
|
+
/**
|
|
1413
|
+
* Activa o desactiva un proveedor.
|
|
1414
|
+
* @param id - ID del proveedor
|
|
1415
|
+
*/
|
|
1416
|
+
toggleProviderStatus(id: number): Promise<ResponseModel<InventoryProvider>>;
|
|
1417
|
+
/**
|
|
1418
|
+
* Elimina un proveedor.
|
|
1419
|
+
* @param id - ID del proveedor a eliminar
|
|
1420
|
+
*/
|
|
1421
|
+
deleteProvider(id: number): Promise<ResponseModel<void>>;
|
|
1358
1422
|
}
|
|
1359
1423
|
|
|
1360
1424
|
/**
|
|
@@ -2451,4 +2515,4 @@ declare class FalconHUBSDK {
|
|
|
2451
2515
|
|
|
2452
2516
|
declare function decrypt(encryptedBase64: string, secret: string, timestamp: string): string;
|
|
2453
2517
|
|
|
2454
|
-
export { API, type AdminAuthentication, type AdminUser, type AreaCode, type AreaCodeRequest, type AreaCodesFilter, AuthInterceptor, type AuthInterceptorConfig, AuthService, type BlankProduct, type BlankProductRequest, type BlankProductsFilter, CatalogService, type ChangePasswordAdminRequest, type ChangePasswordRequest, type ChangePasswordUserRequest, type ConfirmEmailRequest, CryptoService, type DetailProductPOD, type DetailProductPODFilter, type DetailProductPODRequest, type Endpoint, type EndpointRequest, type EndpointsFilter, ErrorResponse, FalconHUBSDK, FilterBuilder, type FilterFieldMetadata, type FilterGroup, type FilterGroupOption, type FilterGroupsModel, type FilterMetadataModel, type FilterModel, type Gender, type GenderRequest, type GendersFilter, type HttpMethodType, type InterceptorContext, InventoryService, type InventoryStatus, type InventoryStatusRequest, type InventoryStatusesFilter, type License, type LicenseRequest, type LicensesFilter, type Location, type LocationsFilter, type LocationsRequest, type LoginRequest, type LoginResponse, type Material, type MaterialRequest, type MaterialsFilter, type MethodTypes, type Module, type ModuleRequest, type ModulesFilter, type Packing, type PackingRequest, type PackingsFilter, type ProductBullet, type ProductBulletRequest, type ProductBulletsFilter, type ProductCategoriesFilter, type ProductCategory, type ProductCategoryRequest, type ProductImage, type ProductImageRequest, type ProductImagesFilter, type ProductKeyword, type ProductKeywordRequest, type ProductKeywordsFilter, type ProductPrice, type ProductPriceRequest, type ProductPricesFilter, ProductService, type ProductStatus, type ProductStatusRequest, type ProductStatusesFilter, type ProductType, type ProductTypeRequest, type ProductTypesFilter, type Provider, type ProviderRequest, type ProvidersFilter, type RefreshTokenRequest, type RefreshTokenResponse, type RequestConfig, type RequestInterceptor, type RequestOptions, type ResponseModel, type Role, type RoleRequest, type RolesFilter, type SendOtpRequest, type ServiceProperties, type Size, type SizeGroup, type SizeGroupRequest, type SizeGroupsFilter, type SizeRequest, type SizesFilter, type Studio, type StudioRequest, type StudiosFilter, SystemService, type TokenData, TokenManager, type UIRoute, type UIRouteRequest, type UIRoutesFilter, type UserAdminFilter, type UserAdminRequest, type UserAdminUpdateRequest, type UserAuthAdminRequest, type UserAuthUpdateRequest, type UserBasicResponse, type UserDataUpdateRequest, type UserProfileResponse, UserService, type UserType, type UserTypeRequest, type UserTypesFilter, type ValidateOtpRequest, type ValidateSessionRenewedResponse, type ValidateSessionResponse, decrypt };
|
|
2518
|
+
export { API, type AdminAuthentication, type AdminUser, type AreaCode, type AreaCodeRequest, type AreaCodesFilter, AuthInterceptor, type AuthInterceptorConfig, AuthService, type BlankProduct, type BlankProductRequest, type BlankProductsFilter, CatalogService, type ChangePasswordAdminRequest, type ChangePasswordRequest, type ChangePasswordUserRequest, type ConfirmEmailRequest, CryptoService, type DetailProductPOD, type DetailProductPODFilter, type DetailProductPODRequest, type Endpoint, type EndpointRequest, type EndpointsFilter, ErrorResponse, FalconHUBSDK, FilterBuilder, type FilterFieldMetadata, type FilterGroup, type FilterGroupOption, type FilterGroupsModel, type FilterMetadataModel, type FilterModel, type Gender, type GenderRequest, type GendersFilter, type HttpMethodType, type InterceptorContext, type InventoryProvider, type InventoryProviderRequest, type InventoryProvidersFilter, InventoryService, type InventoryStatus, type InventoryStatusRequest, type InventoryStatusesFilter, type License, type LicenseRequest, type LicensesFilter, type Location, type LocationsFilter, type LocationsRequest, type LoginRequest, type LoginResponse, type Material, type MaterialRequest, type MaterialsFilter, type MethodTypes, type Module, type ModuleRequest, type ModulesFilter, type Packing, type PackingRequest, type PackingsFilter, type ProductBullet, type ProductBulletRequest, type ProductBulletsFilter, type ProductCategoriesFilter, type ProductCategory, type ProductCategoryRequest, type ProductImage, type ProductImageRequest, type ProductImagesFilter, type ProductKeyword, type ProductKeywordRequest, type ProductKeywordsFilter, type ProductPrice, type ProductPriceRequest, type ProductPricesFilter, ProductService, type ProductStatus, type ProductStatusRequest, type ProductStatusesFilter, type ProductType, type ProductTypeRequest, type ProductTypesFilter, type Provider, type ProviderRequest, type ProvidersFilter, type RefreshTokenRequest, type RefreshTokenResponse, type RequestConfig, type RequestInterceptor, type RequestOptions, type ResponseModel, type Role, type RoleRequest, type RolesFilter, type SendOtpRequest, type ServiceProperties, type Size, type SizeGroup, type SizeGroupRequest, type SizeGroupsFilter, type SizeRequest, type SizesFilter, type Studio, type StudioRequest, type StudiosFilter, SystemService, type TokenData, TokenManager, type UIRoute, type UIRouteRequest, type UIRoutesFilter, type UserAdminFilter, type UserAdminRequest, type UserAdminUpdateRequest, type UserAuthAdminRequest, type UserAuthUpdateRequest, type UserBasicResponse, type UserDataUpdateRequest, type UserProfileResponse, UserService, type UserType, type UserTypeRequest, type UserTypesFilter, type ValidateOtpRequest, type ValidateSessionRenewedResponse, type ValidateSessionResponse, decrypt };
|
package/dist/index.mjs
CHANGED
|
@@ -1144,28 +1144,28 @@ var InventoryService = class {
|
|
|
1144
1144
|
* @param filter - Filtros opcionales para la búsqueda
|
|
1145
1145
|
*/
|
|
1146
1146
|
async getStatuses(filter) {
|
|
1147
|
-
const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/statuses`, filter);
|
|
1147
|
+
const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/catalogs/inventory-statuses`, filter);
|
|
1148
1148
|
return this.api.executeGET(endpoint, true);
|
|
1149
1149
|
}
|
|
1150
1150
|
/**
|
|
1151
1151
|
* Obtiene el modelo de filtros disponibles para estatus de inventario.
|
|
1152
1152
|
*/
|
|
1153
1153
|
async getStatusFiltersModel() {
|
|
1154
|
-
return this.api.executeGET(`${this.BASE_PATH}/statuses/filters`, true);
|
|
1154
|
+
return this.api.executeGET(`${this.BASE_PATH}/catalogs/inventory-statuses/filters`, true);
|
|
1155
1155
|
}
|
|
1156
1156
|
/**
|
|
1157
1157
|
* Obtiene un estatus de inventario por su ID.
|
|
1158
1158
|
* @param id - ID del estatus
|
|
1159
1159
|
*/
|
|
1160
1160
|
async getStatusById(id) {
|
|
1161
|
-
return this.api.executeGET(`${this.BASE_PATH}/statuses/${id}`, true);
|
|
1161
|
+
return this.api.executeGET(`${this.BASE_PATH}/catalogs/inventory-statuses/${id}`, true);
|
|
1162
1162
|
}
|
|
1163
1163
|
/**
|
|
1164
1164
|
* Crea un nuevo estatus de inventario.
|
|
1165
1165
|
* @param request - Datos del estatus a crear
|
|
1166
1166
|
*/
|
|
1167
1167
|
async createStatus(request) {
|
|
1168
|
-
return this.api.executePOST(`${this.BASE_PATH}/statuses`, request);
|
|
1168
|
+
return this.api.executePOST(`${this.BASE_PATH}/catalogs/inventory-statuses`, request);
|
|
1169
1169
|
}
|
|
1170
1170
|
/**
|
|
1171
1171
|
* Actualiza un estatus de inventario existente.
|
|
@@ -1173,21 +1173,14 @@ var InventoryService = class {
|
|
|
1173
1173
|
* @param request - Nuevos datos del estatus
|
|
1174
1174
|
*/
|
|
1175
1175
|
async updateStatus(id, request) {
|
|
1176
|
-
return this.api.executePUT(`${this.BASE_PATH}/statuses/${id}`, request);
|
|
1177
|
-
}
|
|
1178
|
-
/**
|
|
1179
|
-
* Activa o desactiva un estatus de inventario.
|
|
1180
|
-
* @param id - ID del estatus
|
|
1181
|
-
*/
|
|
1182
|
-
async toggleStatusActive(id) {
|
|
1183
|
-
return this.api.executePUT(`${this.BASE_PATH}/statuses/${id}/toggle-status`);
|
|
1176
|
+
return this.api.executePUT(`${this.BASE_PATH}/catalogs/inventory-statuses/${id}`, request);
|
|
1184
1177
|
}
|
|
1185
1178
|
/**
|
|
1186
1179
|
* Elimina un estatus de inventario.
|
|
1187
1180
|
* @param id - ID del estatus a eliminar
|
|
1188
1181
|
*/
|
|
1189
1182
|
async deleteStatus(id) {
|
|
1190
|
-
return this.api.executeDELETE(`${this.BASE_PATH}/statuses/${id}`);
|
|
1183
|
+
return this.api.executeDELETE(`${this.BASE_PATH}/catalogs/inventory-statuses/${id}`);
|
|
1191
1184
|
}
|
|
1192
1185
|
// #endregion
|
|
1193
1186
|
// #region PACKINGS
|
|
@@ -1196,28 +1189,28 @@ var InventoryService = class {
|
|
|
1196
1189
|
* @param filter - Filtros opcionales para la búsqueda
|
|
1197
1190
|
*/
|
|
1198
1191
|
async getPackings(filter) {
|
|
1199
|
-
const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/packings`, filter);
|
|
1192
|
+
const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/catalogs/packings`, filter);
|
|
1200
1193
|
return this.api.executeGET(endpoint, true);
|
|
1201
1194
|
}
|
|
1202
1195
|
/**
|
|
1203
1196
|
* Obtiene el modelo de filtros disponibles para empaques.
|
|
1204
1197
|
*/
|
|
1205
1198
|
async getPackingFiltersModel() {
|
|
1206
|
-
return this.api.executeGET(`${this.BASE_PATH}/packings/filters`, true);
|
|
1199
|
+
return this.api.executeGET(`${this.BASE_PATH}/catalogs/packings/filters`, true);
|
|
1207
1200
|
}
|
|
1208
1201
|
/**
|
|
1209
1202
|
* Obtiene un empaque por su ID.
|
|
1210
1203
|
* @param id - ID del empaque
|
|
1211
1204
|
*/
|
|
1212
1205
|
async getPackingById(id) {
|
|
1213
|
-
return this.api.executeGET(`${this.BASE_PATH}/packings/${id}`, true);
|
|
1206
|
+
return this.api.executeGET(`${this.BASE_PATH}/catalogs/packings/${id}`, true);
|
|
1214
1207
|
}
|
|
1215
1208
|
/**
|
|
1216
1209
|
* Crea un nuevo empaque.
|
|
1217
1210
|
* @param request - Datos del empaque a crear
|
|
1218
1211
|
*/
|
|
1219
1212
|
async createPacking(request) {
|
|
1220
|
-
return this.api.executePOST(`${this.BASE_PATH}/packings`, request);
|
|
1213
|
+
return this.api.executePOST(`${this.BASE_PATH}/catalogs/packings`, request);
|
|
1221
1214
|
}
|
|
1222
1215
|
/**
|
|
1223
1216
|
* Actualiza un empaque existente.
|
|
@@ -1225,14 +1218,21 @@ var InventoryService = class {
|
|
|
1225
1218
|
* @param request - Nuevos datos del empaque
|
|
1226
1219
|
*/
|
|
1227
1220
|
async updatePacking(id, request) {
|
|
1228
|
-
return this.api.executePUT(`${this.BASE_PATH}/packings/${id}`, request);
|
|
1221
|
+
return this.api.executePUT(`${this.BASE_PATH}/catalogs/packings/${id}`, request);
|
|
1222
|
+
}
|
|
1223
|
+
/**
|
|
1224
|
+
* Activa o desactiva un empaque.
|
|
1225
|
+
* @param id - ID del empaque
|
|
1226
|
+
*/
|
|
1227
|
+
async togglePackingStatus(id) {
|
|
1228
|
+
return this.api.executePUT(`${this.BASE_PATH}/catalogs/packings/${id}/toggle-status`);
|
|
1229
1229
|
}
|
|
1230
1230
|
/**
|
|
1231
1231
|
* Elimina un empaque.
|
|
1232
1232
|
* @param id - ID del empaque a eliminar
|
|
1233
1233
|
*/
|
|
1234
1234
|
async deletePacking(id) {
|
|
1235
|
-
return this.api.executeDELETE(`${this.BASE_PATH}/packings/${id}`);
|
|
1235
|
+
return this.api.executeDELETE(`${this.BASE_PATH}/catalogs/packings/${id}`);
|
|
1236
1236
|
}
|
|
1237
1237
|
// #endregion
|
|
1238
1238
|
// #region MATERIALS
|
|
@@ -1241,28 +1241,28 @@ var InventoryService = class {
|
|
|
1241
1241
|
* @param filter - Filtros opcionales para la búsqueda
|
|
1242
1242
|
*/
|
|
1243
1243
|
async getMaterials(filter) {
|
|
1244
|
-
const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/materials`, filter);
|
|
1244
|
+
const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/catalogs/materials`, filter);
|
|
1245
1245
|
return this.api.executeGET(endpoint, true);
|
|
1246
1246
|
}
|
|
1247
1247
|
/**
|
|
1248
1248
|
* Obtiene el modelo de filtros disponibles para materiales.
|
|
1249
1249
|
*/
|
|
1250
1250
|
async getMaterialFiltersModel() {
|
|
1251
|
-
return this.api.executeGET(`${this.BASE_PATH}/materials/filters`, true);
|
|
1251
|
+
return this.api.executeGET(`${this.BASE_PATH}/catalogs/materials/filters`, true);
|
|
1252
1252
|
}
|
|
1253
1253
|
/**
|
|
1254
1254
|
* Obtiene un material por su ID.
|
|
1255
1255
|
* @param id - ID del material
|
|
1256
1256
|
*/
|
|
1257
1257
|
async getMaterialById(id) {
|
|
1258
|
-
return this.api.executeGET(`${this.BASE_PATH}/materials/${id}`, true);
|
|
1258
|
+
return this.api.executeGET(`${this.BASE_PATH}/catalogs/materials/${id}`, true);
|
|
1259
1259
|
}
|
|
1260
1260
|
/**
|
|
1261
1261
|
* Crea un nuevo material.
|
|
1262
1262
|
* @param request - Datos del material a crear
|
|
1263
1263
|
*/
|
|
1264
1264
|
async createMaterial(request) {
|
|
1265
|
-
return this.api.executePOST(`${this.BASE_PATH}/materials`, request);
|
|
1265
|
+
return this.api.executePOST(`${this.BASE_PATH}/catalogs/materials`, request);
|
|
1266
1266
|
}
|
|
1267
1267
|
/**
|
|
1268
1268
|
* Actualiza un material existente.
|
|
@@ -1270,14 +1270,66 @@ var InventoryService = class {
|
|
|
1270
1270
|
* @param request - Nuevos datos del material
|
|
1271
1271
|
*/
|
|
1272
1272
|
async updateMaterial(id, request) {
|
|
1273
|
-
return this.api.executePUT(`${this.BASE_PATH}/materials/${id}`, request);
|
|
1273
|
+
return this.api.executePUT(`${this.BASE_PATH}/catalogs/materials/${id}`, request);
|
|
1274
1274
|
}
|
|
1275
1275
|
/**
|
|
1276
1276
|
* Elimina un material.
|
|
1277
1277
|
* @param id - ID del material a eliminar
|
|
1278
1278
|
*/
|
|
1279
1279
|
async deleteMaterial(id) {
|
|
1280
|
-
return this.api.executeDELETE(`${this.BASE_PATH}/materials/${id}`);
|
|
1280
|
+
return this.api.executeDELETE(`${this.BASE_PATH}/catalogs/materials/${id}`);
|
|
1281
|
+
}
|
|
1282
|
+
// #endregion
|
|
1283
|
+
// #region PROVIDERS
|
|
1284
|
+
/**
|
|
1285
|
+
* Obtiene todos los proveedores con filtros opcionales.
|
|
1286
|
+
* @param filter - Filtros opcionales para la búsqueda
|
|
1287
|
+
*/
|
|
1288
|
+
async getProviders(filter) {
|
|
1289
|
+
const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/catalogs/providers`, filter);
|
|
1290
|
+
return this.api.executeGET(endpoint, true);
|
|
1291
|
+
}
|
|
1292
|
+
/**
|
|
1293
|
+
* Obtiene el modelo de filtros disponibles para proveedores.
|
|
1294
|
+
*/
|
|
1295
|
+
async getProviderFiltersModel() {
|
|
1296
|
+
return this.api.executeGET(`${this.BASE_PATH}/catalogs/providers/filters`, true);
|
|
1297
|
+
}
|
|
1298
|
+
/**
|
|
1299
|
+
* Obtiene un proveedor por su ID.
|
|
1300
|
+
* @param id - ID del proveedor
|
|
1301
|
+
*/
|
|
1302
|
+
async getProviderById(id) {
|
|
1303
|
+
return this.api.executeGET(`${this.BASE_PATH}/catalogs/providers/${id}`, true);
|
|
1304
|
+
}
|
|
1305
|
+
/**
|
|
1306
|
+
* Crea un nuevo proveedor.
|
|
1307
|
+
* @param request - Datos del proveedor a crear
|
|
1308
|
+
*/
|
|
1309
|
+
async createProvider(request) {
|
|
1310
|
+
return this.api.executePOST(`${this.BASE_PATH}/catalogs/providers`, request);
|
|
1311
|
+
}
|
|
1312
|
+
/**
|
|
1313
|
+
* Actualiza un proveedor existente.
|
|
1314
|
+
* @param id - ID del proveedor a actualizar
|
|
1315
|
+
* @param request - Nuevos datos del proveedor
|
|
1316
|
+
*/
|
|
1317
|
+
async updateProvider(id, request) {
|
|
1318
|
+
return this.api.executePUT(`${this.BASE_PATH}/catalogs/providers/${id}`, request);
|
|
1319
|
+
}
|
|
1320
|
+
/**
|
|
1321
|
+
* Activa o desactiva un proveedor.
|
|
1322
|
+
* @param id - ID del proveedor
|
|
1323
|
+
*/
|
|
1324
|
+
async toggleProviderStatus(id) {
|
|
1325
|
+
return this.api.executePUT(`${this.BASE_PATH}/catalogs/providers/${id}/toggle-status`);
|
|
1326
|
+
}
|
|
1327
|
+
/**
|
|
1328
|
+
* Elimina un proveedor.
|
|
1329
|
+
* @param id - ID del proveedor a eliminar
|
|
1330
|
+
*/
|
|
1331
|
+
async deleteProvider(id) {
|
|
1332
|
+
return this.api.executeDELETE(`${this.BASE_PATH}/catalogs/providers/${id}`);
|
|
1281
1333
|
}
|
|
1282
1334
|
// #endregion
|
|
1283
1335
|
};
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/API.ts","../src/core/CryptoService.ts","../src/core/TokenManager.ts","../src/core/interceptors/AuthInterceptor.ts","../src/types/ErrorResponse.ts","../src/services/AuthService.ts","../src/utils/FilterBuilder.ts","../src/services/UserService.ts","../src/services/SystemService.ts","../src/services/InventoryService.ts","../src/services/ProductService.ts","../src/services/CatalogService.ts","../src/FalconHUBSDK.ts","../src/core/Encryption.ts"],"sourcesContent":["import { ServiceProperties } from \"@/types/ServiceProperties\";\nimport { CryptoService } from \"./CryptoService\";\nimport { MethodTypes, RequestOptions } from \"@/types/RequestOptions\";\nimport { RequestConfig } from \"@/types/RequestConfig\";\nimport { AuthInterceptor } from \"./interceptors/AuthInterceptor\";\nimport { InterceptorContext } from \"@/core/interceptors/types/InterceptorContext\";\nimport { ResponseModel } from \"@/types/ResponseModel\";\n\n\n/**\n * Clase base para la ejecución de request HTTP al API\n */\nexport class API {\n private properties: ServiceProperties;\n private cryptoService: CryptoService;\n private authInterceptor: AuthInterceptor | null;\n\n private getAccessToken: () => string | null;\n private getRefreshToken: () => string | null;\n\n constructor(\n properties: ServiceProperties,\n cryptoService: CryptoService,\n authInterceptor: AuthInterceptor | null,\n getAccessToken: () => string | null,\n getRefreshToken: () => string | null\n ) {\n this.properties = properties;\n this.cryptoService = cryptoService;\n this.getAccessToken = getAccessToken;\n this.getRefreshToken = getRefreshToken;\n this.authInterceptor = authInterceptor;\n };\n\n /**\n * Ejecuta una request HTTP al API\n *\n * @param options - Opciones de la request\n * @returns Respuesta del tipo ResponseModel\n */\n private async apiExecute<T>(options: RequestOptions): Promise<ResponseModel<T>> {\n const {\n endpoint,\n method,\n body,\n requiresAuth,\n timeStamp\n } = options;\n\n const context: InterceptorContext = {\n requestId: this.cryptoService.generateUniqueId(),\n startTime: Date.now(),\n retryCount: 0,\n metadata: {}\n };\n\n try {\n const url = `${this.properties.url}/${endpoint}`;\n const headers: Record<string, string> = {};\n\n if (body && method !== 'GET') {\n headers['Content-Type'] = 'application/json';\n };\n\n const accessToken = this.getAccessToken();\n if (accessToken) {\n headers['Authorization'] = `Bearer ${accessToken}`;\n };\n\n const newTimeStamp = timeStamp || new Date().toISOString();\n\n headers[\"X-Origin-Request\"] = this.properties.originRequest;\n headers['X-Timestamp'] = newTimeStamp;\n headers[\"X-Domain\"] = this.properties.domain;\n headers[\"X-Device\"] = this.properties.device;\n headers[\"X-Source\"] = this.properties.source;\n\n let bodyString: string | undefined;\n if (body && method !== 'GET') {\n bodyString = JSON.stringify(body);\n };\n\n const requestConfig: RequestConfig = {\n url,\n method,\n headers,\n body: bodyString,\n requiresAuth\n };\n\n const modifiedConfig = this.authInterceptor\n ? await this.authInterceptor.onRequest(requestConfig, context)\n : requestConfig;\n\n const requestInit: RequestInit = {\n method: modifiedConfig.method,\n headers: modifiedConfig.headers,\n mode: 'cors',\n credentials: 'omit'\n };\n\n if (modifiedConfig.body && modifiedConfig.method !== 'GET') {\n requestInit.body = typeof modifiedConfig.body === 'string'\n ? modifiedConfig.body\n : JSON.stringify(modifiedConfig.body);\n };\n\n const response = await fetch(\n modifiedConfig.url,\n requestInit\n );\n\n const newAccessToken = response.headers.get('X-New-Access-Token');\n const newRefreshToken = response.headers.get('X-New-Refresh-Token');\n\n if (newAccessToken || newRefreshToken) {\n this.properties.onTokensRefreshed?.({\n accessToken: newAccessToken,\n refreshToken: newRefreshToken\n });\n };\n\n let result: any;\n\n try {\n result = await response.json();\n } catch (e) {\n // Fallback en caso de que la respuesta no sea un JSON válido (errores de servidor 500, 502, etc.)\n return {\n success: false,\n message: `Error de servidor (${response.status}: ${response.statusText || 'Formato de respuesta no reconocido'})`,\n data: null,\n responseTime: new Date().toISOString()\n };\n }\n\n // Manejo de errores de validación (RFC 9110)\n if (result && result.errors && typeof result.errors === 'object') {\n const errorMessages: string[] = [];\n\n Object.values(result.errors).forEach((errors: any) => {\n if (Array.isArray(errors)) {\n errorMessages.push(...errors);\n } else if (typeof errors === 'string') {\n errorMessages.push(errors);\n }\n });\n\n if (errorMessages.length > 0) {\n return {\n success: false,\n message: errorMessages.join(', '),\n data: result.data ?? null,\n responseTime: result.responseTime ?? new Date().toISOString()\n } as ResponseModel<T>;\n }\n }\n\n return result as ResponseModel<T>;\n\n } catch (error) {\n return {\n success: false,\n message: error instanceof Error ? error.message : 'Error inesperado durante la petición al API.',\n data: null,\n responseTime: new Date().toISOString()\n };\n };\n };\n\n\n //#region REQUEST METHODS\n\n async executeGET<T>(\n endpoint: string,\n requiresAuth: boolean = false\n ): Promise<ResponseModel<T>> {\n return this.apiExecute<T>({\n endpoint,\n method: 'GET',\n requiresAuth: requiresAuth\n });\n };\n\n async executePOST<T>(\n endpoint: string,\n body?: any,\n requiresAuth: boolean = true,\n ): Promise<ResponseModel<T>> {\n return this.apiExecute<T>({\n endpoint,\n method: 'POST',\n body,\n requiresAuth: requiresAuth\n });\n };\n\n async executePATCH<T>(\n endpoint: string,\n body?: any,\n requiresAuth: boolean = true,\n ): Promise<ResponseModel<T>> {\n return this.apiExecute<T>({\n endpoint,\n method: 'PATCH',\n body,\n requiresAuth: requiresAuth\n });\n };\n\n async executeDELETE<T>(\n endpoint: string,\n body?: any,\n requiresAuth: boolean = true,\n ): Promise<ResponseModel<T>> {\n return this.apiExecute<T>({\n endpoint,\n method: 'DELETE',\n body,\n requiresAuth: requiresAuth\n });\n };\n\n async executePUT<T>(\n endpoint: string,\n body?: any,\n requiresAuth: boolean = true\n ): Promise<ResponseModel<T>> {\n return this.apiExecute<T>({\n endpoint,\n method: 'PUT',\n body,\n requiresAuth: requiresAuth,\n });\n };\n\n async executePublicRequest<T>(\n endpoint: string,\n method: MethodTypes,\n body?: any,\n timestamp?: string\n ): Promise<ResponseModel<T>> {\n return this.apiExecute<T>({\n endpoint,\n method,\n body,\n requiresAuth: false,\n timeStamp: timestamp\n });\n };\n\n //#endregion\n}\n","import * as CryptoJS from \"crypto-js\";\n\nexport class CryptoService {\n /**\n * Genera un hash SHA256 de un texto (útil para fingerprints)\n *\n * @param text - Texto a hashear\n * @returns Hash en formato hexadecimal\n */\n sha256(text: string): string {\n return CryptoJS.SHA256(text).toString(CryptoJS.enc.Hex);\n }\n\n /**\n * Genera un identificador único basado en timestamp y random\n * (útil para request IDs)\n *\n * @returns ID único\n */\n generateUniqueId(): string {\n const timestamp = Date.now().toString(36);\n const randomPart = Math.random().toString(36).substring(2, 15);\n return `${timestamp}-${randomPart}`;\n }\n}\n","import { TokenData } from \"@/types/TokenData\";\n\n/**\n * Manages authentication tokens.\n */\nexport class TokenManager {\n private tokens: TokenData | null = null;\n private onTokensChanged?: (tokens: TokenData | null) => void;\n private sessionCheckInterval: NodeJS.Timeout | null = null;\n private autoRefreshTimeout: NodeJS.Timeout | null = null;\n private onSessionExpiring?: (remainingMinutes: number) => void;\n private onSessionExpired?: () => Promise<void>;\n private onSessionRecovery?: () => Promise<boolean>;\n private hasNotifiedExpiring: boolean = false;\n private autoRefreshThresholdMinutes: number = 5;\n\n constructor(\n onTokensChanged?: (tokens: TokenData | null) => void,\n onSessionExpiring?: (remainingMinutes: number) => void,\n onSessionExpired?: () => Promise<void>,\n onSessionRecovery?: () => Promise<boolean>,\n autoRefreshThresholdMinutes?: number\n ) {\n this.onTokensChanged = onTokensChanged;\n this.onSessionExpiring = onSessionExpiring;\n this.onSessionExpired = onSessionExpired;\n this.onSessionRecovery = onSessionRecovery;\n this.autoRefreshThresholdMinutes = autoRefreshThresholdMinutes ?? 5;\n };\n\n /**\n * Guarda los tokens de autenticación y dispara el callback onTokensChanged.\n */\n setTokens(tokens: TokenData) {\n this.tokens = tokens;\n this.hasNotifiedExpiring = false;\n\n this.onTokensChanged?.(this.tokens);\n\n if (!tokens.rememberMe) {\n this.startExpirationCheck();\n this.stopAutoRefreshTimer();\n } else {\n this.stopExpirationCheck();\n this.scheduleAutoRefresh();\n };\n };\n\n /**\n * Guarda los tokens sin disparar el callback onTokensChanged.\n * Usar para inyectar tokens desde storage externo (cookies/localStorage).\n */\n setTokensSilent(tokens: TokenData) {\n this.tokens = tokens;\n this.hasNotifiedExpiring = false;\n\n if (!tokens.rememberMe) {\n this.startExpirationCheck();\n this.stopAutoRefreshTimer();\n } else {\n this.stopExpirationCheck();\n this.scheduleAutoRefresh();\n };\n };\n\n /**\n * Obtiene los tokens de autenticación almacenados.\n */\n getTokens(): TokenData | null {\n return this.tokens;\n };\n\n /**\n * Limpia los tokens de autenticación almacenados y dispara el callback onTokensChanged.\n */\n clearTokens() {\n this.stopExpirationCheck();\n this.stopAutoRefreshTimer();\n this.tokens = null;\n this.onTokensChanged?.(this.tokens);\n };\n\n /**\n * Valida si existen tokens y si el access token no ha expirado.\n */\n hasValidTokens(): boolean {\n if (!this.tokens) return false;\n\n return Date.now() < this.tokens.expiresAt;\n };\n\n /**\n * Valida si el access token expirará dentro del umbral especificado (en minutos).\n */\n isTokenExpiringSoon(thresholdMinutes: number): boolean {\n if (!this.tokens) return false;\n\n const thresholdMs = thresholdMinutes * 60 * 1000;\n const timeLeft = this.tokens.expiresAt - Date.now();\n\n return timeLeft > 0 && timeLeft <= thresholdMs;\n };\n\n /**\n * Obtiene el tiempo restante hasta la expiración del access token en milisegundos.\n */\n getTimeUntilExpiry(): number | null {\n if (!this.tokens) return null;\n\n return Math.max(0, this.tokens.expiresAt - Date.now());\n };\n\n /**\n * Obtiene el access token almacenado.\n */\n getAccessToken(): string | null {\n return this.tokens ? this.tokens.accessToken : null;\n };\n\n /**\n * Obtiene el refresh token almacenado.\n */\n getRefreshToken(): string | null {\n return this.tokens ? this.tokens.refreshToken : null;\n };\n\n /**\n * Verifica si el auto-refresh debe ejecutarse\n * Solo si el usuario activó \"rememberMe\" durante el login\n */\n shouldAutoRefresh(): boolean {\n if (!this.tokens) return false;\n\n return this.tokens.rememberMe === true;\n }\n\n /**\n * Inicia el monitoreo de expiración para sesiones sin rememberMe\n * - Notifica cuando quedan 5 minutos (onSessionExpiring)\n */\n private startExpirationCheck(): void {\n this.stopExpirationCheck();\n\n this.sessionCheckInterval = setInterval(async () => {\n if (!this.tokens) {\n this.stopExpirationCheck();\n return;\n };\n\n const timeLeft = this.getTimeUntilExpiry();\n if (timeLeft === null) return;\n\n const minutesLeft = Math.floor(timeLeft / (60 * 1000));\n\n if (minutesLeft <= 5 && minutesLeft > 1 && !this.hasNotifiedExpiring) {\n this.hasNotifiedExpiring = true;\n this.onSessionExpiring?.(minutesLeft);\n };\n\n if (minutesLeft <= 1) {\n this.stopExpirationCheck();\n\n if (this.onSessionRecovery) {\n try {\n const recovered = await this.onSessionRecovery();\n if (recovered) return;\n } catch (error) {\n }\n }\n\n if (this.onSessionExpired) {\n await this.onSessionExpired();\n };\n };\n }, 60000);\n }\n\n /**\n * Programa un auto-refresh proactivo para sesiones con rememberMe.\n * Se ejecuta X minutos antes de que expire el token\n */\n private scheduleAutoRefresh(): void {\n this.stopAutoRefreshTimer();\n\n if (!this.tokens || !this.tokens.rememberMe) return;\n\n const timeLeft = this.getTimeUntilExpiry();\n if (timeLeft === null || timeLeft <= 0) return;\n\n const thresholdMs = this.autoRefreshThresholdMinutes * 60 * 1000;\n const delay = Math.max(0, timeLeft - thresholdMs);\n\n this.autoRefreshTimeout = setTimeout(async () => {\n if (!this.tokens || !this.tokens.rememberMe) return;\n\n if (this.onSessionRecovery) {\n try {\n const recovered = await this.onSessionRecovery();\n if (recovered) return;\n } catch (error) {\n }\n }\n\n if (this.onSessionExpired) {\n await this.onSessionExpired();\n }\n }, delay);\n }\n\n /**\n * Detiene el monitoreo de expiración\n */\n private stopExpirationCheck(): void {\n if (this.sessionCheckInterval) {\n clearInterval(this.sessionCheckInterval);\n this.sessionCheckInterval = null;\n };\n }\n\n /**\n * Detiene el timer de auto-refresh proactivo\n */\n private stopAutoRefreshTimer(): void {\n if (this.autoRefreshTimeout) {\n clearTimeout(this.autoRefreshTimeout);\n this.autoRefreshTimeout = null;\n };\n }\n};\n","import { AuthInterceptorConfig } from \"./types/AuthInterceptorConfig\";\nimport { InterceptorContext } from \"@/core/interceptors/types/InterceptorContext\";\nimport { RequestConfig } from \"@/types/RequestConfig\";\nimport { RequestInterceptor } from \"./types/RequestInterceptor\";\n\nexport class AuthInterceptor implements RequestInterceptor {\n readonly name = \"AuthInterceptor\";\n\n private config: Required<AuthInterceptorConfig>;\n private refreshPromise: Promise<void> | null = null;\n private isRefreshing = false;\n\n constructor(config: AuthInterceptorConfig) {\n this.config = {\n enabled: config.enabled ?? true,\n thresholdMinutes: config.thresholdMinutes ?? 5,\n isTokenExpiringSoon: config.isTokenExpiringSoon,\n hasValidTokens: config.hasValidTokens,\n shouldAutoRefresh: config.shouldAutoRefresh,\n refreshSession: config.refreshSession\n };\n };\n\n async onRequest(\n config: RequestConfig,\n context: InterceptorContext\n ): Promise<RequestConfig> {\n\n //Actua en solicitudes que requieren autenticación\n if (!config.requiresAuth || !this.config.enabled) {\n return config;\n };\n\n //Actúa SOLO si los tokens son válidos\n if (!this.config.hasValidTokens()) {\n return config;\n };\n\n if (!this.config.shouldAutoRefresh()) {\n return config;\n };\n\n if (this.config.isTokenExpiringSoon()) {\n try {\n //Evita múltiples llamadas de actualización simultáneas\n if (this.isRefreshing && this.refreshPromise) {\n await this.refreshPromise;\n } else {\n this.isRefreshing = true;\n this.refreshPromise = this.config.refreshSession();\n await this.refreshPromise;\n this.isRefreshing = false;\n this.refreshPromise = null;\n };\n } catch (error) {\n this.isRefreshing = false;\n this.refreshPromise = null;\n };\n };\n\n return config;\n };\n\n updateConfig(config: Partial<AuthInterceptorConfig>): void {\n this.config = {\n ...this.config,\n ...config\n } as Required<AuthInterceptorConfig>;\n };\n\n reset(): void {\n this.isRefreshing = false;\n this.refreshPromise = null;\n };\n};\n","export class ErrorResponse extends Error {\n constructor(\n message: string,\n public statusCode?: number,\n public responseData?: any\n ){\n super(message);\n this.name = \"FalconHUB API Error\";\n };\n};\n","import { API } from \"@/core/API\";\nimport { CryptoService } from \"@/core/CryptoService\";\nimport { TokenManager } from \"@/core/TokenManager\";\nimport { LoginRequest } from \"@/interfaces/Auth/Login/LoginRequest\";\nimport { LoginResponse } from \"@/interfaces/Auth/Login/LoginResponse\";\nimport { RefreshTokenRequest } from \"@/interfaces/Auth/RefreshTokens/RefreshTokenRequest\";\nimport { RefreshTokenResponse } from \"@/interfaces/Auth/RefreshTokens/RefreshTokenResponse\";\nimport { ValidateSessionRenewedResponse, ValidateSessionResponse } from \"@/interfaces/Auth/ValidateSession/ValidateSessionResponse\";\nimport { ConfirmEmailRequest } from \"@/interfaces/Auth/ConfirmEmail/ConfirmEmailRequest\";\nimport { SendOtpRequest } from \"@/interfaces/Auth/SendOtp/SendOtpRequest\";\nimport { ValidateOtpRequest } from \"@/interfaces/Auth/ValidateOtp/ValidateOtpRequest\";\nimport { ChangePasswordRequest } from \"@/interfaces/Auth/ChangePassword/ChangePasswordRequest\";\nimport { ErrorResponse } from \"@/types/ErrorResponse\";\nimport { ResponseModel } from \"@/types/ResponseModel\";\nimport { ServiceProperties } from \"@/types/ServiceProperties\";\nimport { TokenData } from \"@/types/TokenData\";\n\nexport class AuthService {\n private api: API;\n private crytpoService: CryptoService;\n private tokenManager: TokenManager;\n private serviceProperties: ServiceProperties;\n\n constructor(\n serviceProperties: ServiceProperties,\n tokenManager: TokenManager,\n cryptoService: CryptoService,\n api: API\n ) {\n this.api = api;\n this.crytpoService = cryptoService;\n this.tokenManager = tokenManager;\n this.serviceProperties = serviceProperties;\n };\n\n /**\n * Login con las credenciales proporcionadas\n * @param credentials - Objeto con email, password y rememberMe\n * @returns Retorna el cuerpo de respuesta del login.\n */\n async login(credentials: LoginRequest): Promise<ResponseModel<LoginResponse>> {\n const timestamp = Date.now().toString();\n\n const loginData: LoginRequest = {\n email: credentials.email,\n password: credentials.password,\n rememberMe: credentials.rememberMe\n };\n\n const response = await this.api.executePublicRequest<LoginResponse>(\n 'oauth/login',\n 'POST',\n loginData,\n timestamp\n );\n\n if (!response) {\n throw new ErrorResponse('No response from server');\n };\n\n if (response.success && response.data) {\n const data: LoginResponse = response.data;\n\n const expiresIn = parseInt(data.expiresIn.replace('s', ''));\n const expiresAt = Date.now() + expiresIn * 1000;\n\n const tokens: TokenData = {\n accessToken: data.accessToken,\n refreshToken: data.refreshToken,\n expiresAt,\n rememberMe: credentials.rememberMe\n };\n\n await this.tokenManager.setTokens(tokens);\n\n this.serviceProperties.onTokensUpdated?.(tokens);\n }\n\n return response;\n };\n\n /**\n * Valida la sesión actual y retorna información de expiración\n *\n * El servidor puede responder de 2 formas:\n * 1. Sesión renovada (sliding window): retorna nuevos tokens\n * 2. Sesión válida: retorna info de expiración sin renovar\n */\n async validateSession(): Promise<ResponseModel<ValidateSessionRenewedResponse | ValidateSessionResponse>> {\n const response = await this.api.executePOST<ValidateSessionRenewedResponse | ValidateSessionResponse>(\n 'oauth/validateSession'\n );\n\n if (!response) {\n throw new ErrorResponse('No response from server');\n };\n\n if (response.success && response.data) {\n const respData = response.data;\n\n if ('expiresIn' in respData && respData.expiresIn) {\n const sessionData = respData as ValidateSessionRenewedResponse;\n const expiresIn = parseInt(sessionData.expiresIn.replace('s', ''));\n const expiresAt = Date.now() + expiresIn * 1000;\n\n const currentTokens = this.tokenManager.getTokens();\n const rememberMe = currentTokens?.rememberMe ?? sessionData.isRemembered;\n\n const tokens: TokenData = {\n accessToken: sessionData.accessToken,\n refreshToken: sessionData.refreshToken,\n expiresAt,\n rememberMe\n };\n\n this.tokenManager.setTokens(tokens);\n this.serviceProperties.onTokensUpdated?.(tokens);\n }\n else if ('expiresAt' in respData && respData.expiresAt) {\n const sessionData = respData as ValidateSessionResponse;\n\n if (sessionData.remainingMinutes <= 5 && sessionData.remainingMinutes > 1) {\n this.serviceProperties.onSessionExpiring?.(sessionData.remainingMinutes);\n } else if (sessionData.remainingMinutes <= 1) {\n if (this.serviceProperties.onSessionExpired) {\n await this.serviceProperties.onSessionExpired();\n }\n }\n }\n };\n\n return response;\n };\n\n /**\n * Refresca los tokens usando el refresh token\n */\n async refreshTokens(refreshRequest: RefreshTokenRequest): Promise<ResponseModel<RefreshTokenResponse>> {\n const currentTokens = this.tokenManager.getTokens();\n const refreshToken = this.tokenManager.getRefreshToken() ?? refreshRequest.refreshToken;\n\n if (!refreshToken) {\n throw new ErrorResponse('No refresh token available');\n };\n\n const refreshRequestData: RefreshTokenRequest = {\n refreshToken: refreshToken,\n rememberMe: refreshRequest.rememberMe ?? currentTokens?.rememberMe\n }\n\n const response = await this.api.executePublicRequest<RefreshTokenResponse>(\n 'oauth/refresh',\n 'POST',\n refreshRequestData\n );\n\n if (!response) {\n throw new ErrorResponse('No response from server');\n };\n\n if (response.success && response.data) {\n const sessionData: RefreshTokenResponse = response.data;\n\n\n const shouldRemember = refreshRequest.rememberMe ?? currentTokens?.rememberMe ?? false;\n const expiresIn = parseInt(sessionData.expiresIn.replace('s', ''));\n const expiresAt = Date.now() + expiresIn * 1000;\n\n const tokens: TokenData = {\n accessToken: sessionData.accessToken,\n refreshToken: sessionData.refreshToken,\n expiresAt,\n rememberMe: shouldRemember\n };\n\n this.tokenManager.setTokens(tokens);\n this.serviceProperties.onTokensUpdated?.(tokens);\n };\n\n return response;\n };\n\n /**\n * Cierra sesión: notifica al servidor y limpia tokens\n */\n async logout(): Promise<ResponseModel> {\n const res = await this.api.executePOST('oauth/logout');\n\n if (res.success) {\n this.tokenManager.clearTokens();\n this.serviceProperties.onTokensUpdated?.(null);\n }\n\n return res;\n }\n\n // #region Email & OTP & Password (public - no auth)\n\n /**\n * Confirma el correo electrónico de un usuario.\n * @param request - Email y expiresAt\n */\n async confirmEmail(request: ConfirmEmailRequest): Promise<ResponseModel> {\n return this.api.executePublicRequest('oauth/email/confirm', 'PUT', request);\n }\n\n /**\n * Envía un código OTP al correo electrónico.\n * @param request - Email del usuario\n */\n async sendOtp(request: SendOtpRequest): Promise<ResponseModel> {\n return this.api.executePublicRequest('oauth/otp', 'POST', request);\n }\n\n /**\n * Valida un código OTP.\n * @param request - Email y código OTP\n */\n async validateOtp(request: ValidateOtpRequest): Promise<ResponseModel> {\n return this.api.executePublicRequest('oauth/otp/verify', 'POST', request);\n }\n\n /**\n * Cambia la contraseña del usuario (flujo público, sin sesión).\n * @param request - Email, contraseña actual y nueva contraseña\n */\n async changePassword(request: ChangePasswordRequest): Promise<ResponseModel> {\n return this.api.executePublicRequest('oauth/password', 'PUT', request);\n }\n\n // #endregion\n\n /**\n * Verifica si el usuario está autenticado\n */\n isAuthenticated(): boolean {\n return this.tokenManager.hasValidTokens();\n };\n\n /**\n * Obtiene los tokens actuales\n */\n getTokens(): TokenData | null {\n return this.tokenManager.getTokens();\n };\n\n}\n","/**\n * Utilidad para construir query params a partir de objetos de filtro.\n *\n * @example\n * ```typescript\n * const filter: EndpointsFilter = { HttpMethod: 'GET', IsActive: true };\n * const queryString = FilterBuilder.toQueryString(filter);\n * // Result: \"HttpMethod=GET&IsActive=true\"\n * ```\n */\nexport class FilterBuilder {\n /**\n * Convierte un objeto de filtro a query string.\n * Ignora valores null, undefined y strings vacíos.\n *\n * @param filter - Objeto con los filtros a aplicar\n * @returns Query string sin el \"?\" inicial\n */\n static toQueryString<T extends Record<string, any>>(filter: T): string {\n const params = new URLSearchParams();\n\n for (const [key, value] of Object.entries(filter)) {\n if (value !== null && value !== undefined && value !== '') {\n params.append(key, String(value));\n }\n }\n\n return params.toString();\n }\n\n /**\n * Construye la URL completa con filtros aplicados.\n *\n * @param baseEndpoint - Endpoint base sin query params\n * @param filter - Objeto con los filtros a aplicar\n * @returns Endpoint con query params si hay filtros, o el endpoint base si no hay\n */\n static buildEndpoint<T extends Record<string, any>>(baseEndpoint: string, filter?: T): string {\n if (!filter) return baseEndpoint;\n\n const queryString = this.toQueryString(filter);\n\n if (!queryString) return baseEndpoint;\n\n return `${baseEndpoint}?${queryString}`;\n }\n\n /**\n * Verifica si un objeto de filtro tiene al menos un valor válido.\n *\n * @param filter - Objeto con los filtros a verificar\n * @returns true si hay al menos un filtro con valor válido\n */\n static hasFilters<T extends Record<string, any>>(filter?: T): boolean {\n if (!filter) return false;\n\n return Object.values(filter).some(\n value => value !== null && value !== undefined && value !== ''\n );\n }\n\n /**\n * Limpia un objeto de filtro removiendo valores vacíos.\n * Útil para normalizar filtros antes de enviarlos.\n *\n * @param filter - Objeto con los filtros\n * @returns Nuevo objeto solo con valores válidos\n */\n static clean<T extends Record<string, any>>(filter: T): Partial<T> {\n const cleaned: Partial<T> = {};\n\n for (const [key, value] of Object.entries(filter)) {\n if (value !== null && value !== undefined && value !== '') {\n (cleaned as any)[key] = value;\n }\n }\n\n return cleaned;\n }\n}\n\n/**\n * Tipo base para modelos de filtro.\n * Todos los campos son opcionales y pueden ser string, number, boolean o null.\n */\nexport type FilterModel = Record<string, string | number | boolean | null | undefined>;\n\n/**\n * Tipo para definir metadatos de un campo de filtro.\n */\nexport interface FilterFieldMetadata {\n /** Tipo de filtro */\n type: 'search' | 'string' | 'boolean' | 'number' | 'select' | 'multiselect' | 'date' | 'daterange';\n /** Descripción / label del filtro */\n description: string;\n /** Orden de renderizado (menor = primero, default 99) */\n order?: number;\n /** Opciones para select / multiselect */\n options?: string[];\n /** Labels personalizados para boolean (default: Activo/Inactivo) */\n labels?: { true: string; false: string };\n /** Campos en los que busca el backend (solo para type: 'search') */\n searchIn?: string[];\n /** Valor mínimo (para number) */\n min?: number;\n /** Valor máximo (para number) */\n max?: number;\n /** Fecha mínima (para date / daterange) */\n minDate?: string;\n /** Fecha máxima (para date / daterange) */\n maxDate?: string;\n}\n\n/**\n * Tipo para el modelo de filtros retornado por el endpoint /filters.\n */\nexport type FilterMetadataModel = Record<string, FilterFieldMetadata>;\n\n// ── Filter Groups (array-based format) ──\n\n/**\n * Opción dentro de un grupo de filtros.\n */\nexport interface FilterGroupOption {\n /** Campo del backend (e.g. \"Module\", \"IsActive\") */\n key: string;\n /** Label visible en el frontend */\n label: string;\n /** Placeholder del input (solo para string) */\n placeholder?: string;\n /** Opciones disponibles (solo para select) */\n values?: string[];\n /** Label cuando el valor es true (solo para boolean) */\n trueLabel?: string;\n /** Label cuando el valor es false (solo para boolean) */\n falseLabel?: string;\n}\n\n/**\n * Grupo de filtros agrupados por tipo.\n * El frontend renderiza cada grupo de forma diferente.\n */\nexport interface FilterGroup {\n /** Tipo de filtro: \"string\" | \"boolean\" | \"select\" | \"date\" */\n type: 'string' | 'boolean' | 'select' | 'date';\n /** Label del grupo */\n label: string;\n /** Opciones del grupo */\n options: FilterGroupOption[];\n}\n\n/**\n * Modelo retornado por el endpoint /filters (formato array-based).\n */\nexport type FilterGroupsModel = FilterGroup[];\n","import { API } from \"@/core/API\";\nimport { UserProfileResponse } from \"@/interfaces/User/UserProfileResponse\";\nimport { UserBasicResponse } from \"@/interfaces/User/UserBasicResponse\";\nimport {\n AdminUser,\n AdminAuthentication,\n UserAdminRequest,\n UserAuthAdminRequest,\n ChangePasswordAdminRequest,\n UserAdminFilter,\n UserAdminUpdateRequest,\n UserAuthUpdateRequest\n} from \"@/interfaces/User/Admin\";\nimport {\n UserType,\n UserTypeRequest,\n UserTypesFilter\n} from \"@/interfaces/User/UserTypes/UserTypesInterface\";\nimport {\n Role,\n RoleRequest,\n RolesFilter\n} from \"@/interfaces/User/Roles/RolesInterface\";\nimport { ResponseModel } from \"@/types/ResponseModel\";\nimport { FilterBuilder, type FilterGroupsModel } from \"@/utils/FilterBuilder\";\nimport { ChangePasswordUserRequest } from \"@/interfaces/User/ChangePassword/ChangePasswordUserRequest\";\nimport { UserDataUpdateRequest } from \"@/interfaces/User/UserDataUpdateRequest\";\n\nexport class UserService {\n private api: API;\n private readonly BASE_PATH = 'users';\n\n constructor(\n api: API,\n ){\n this.api = api;\n };\n\n async me(): Promise<ResponseModel<UserBasicResponse>> {\n const response: ResponseModel<UserBasicResponse> = await this.api.executeGET(\n `${this.BASE_PATH}/me`,\n true,\n );\n\n return response;\n };\n\n async profile(): Promise<ResponseModel<UserProfileResponse>>{\n const response: ResponseModel<UserProfileResponse> = await this.api.executeGET(\n `${this.BASE_PATH}/profile`,\n true\n );\n\n return response;\n }\n\n async changePasswordUser(request: ChangePasswordUserRequest): Promise<ResponseModel>{\n return this.api.executePUT(`${this.BASE_PATH}/me/password`, request);\n }\n\n async updateUserData(request: UserDataUpdateRequest): Promise<ResponseModel>{\n return this.api.executePUT(`${this.BASE_PATH}/me`, request);\n }\n\n // #region Admin CRUD\n\n /**\n * Crea un nuevo usuario administrador.\n * @param request - Datos del nuevo administrador\n */\n async newAdminUser(request: UserAdminRequest): Promise<ResponseModel<AdminUser>> {\n return this.api.executePOST<AdminUser>(`${this.BASE_PATH}/admin`, request);\n }\n\n /**\n * Crea la autenticación para un usuario.\n * @param request - Datos de autenticación del usuario\n */\n async createUserAuthentication(request: UserAuthAdminRequest): Promise<ResponseModel<AdminAuthentication>> {\n return this.api.executePOST<AdminAuthentication>(`${this.BASE_PATH}/admin/authentication`, request);\n }\n\n /**\n * Cambia la contraseña de un administrador.\n * @param id - ID del usuario\n * @param request - Nueva contraseña\n */\n async changePasswordAdmin(id: number, request: ChangePasswordAdminRequest): Promise<ResponseModel> {\n return this.api.executePOST(`${this.BASE_PATH}/admin/${id}/password`, request);\n }\n\n /**\n * Obtiene todos los administradores con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getAllAdmins(filter?: UserAdminFilter): Promise<ResponseModel<AdminUser[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/admin`, filter);\n return this.api.executeGET<AdminUser[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para administradores.\n */\n async getAdminFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/admin/filters`, true);\n }\n\n /**\n * Obtiene un administrador por su ID.\n * @param id - ID del administrador\n */\n async getAdminById(id: number): Promise<ResponseModel<AdminUser>> {\n return this.api.executeGET<AdminUser>(`${this.BASE_PATH}/admin/${id}`, true);\n }\n\n /**\n * Obtiene la autenticación de un administrador.\n * @param id - ID del usuario\n */\n async getAdminAuthentication(id: number): Promise<ResponseModel<AdminAuthentication>> {\n return this.api.executeGET<AdminAuthentication>(`${this.BASE_PATH}/admin/authentication/${id}`, true);\n }\n\n /**\n * Actualiza un administrador existente.\n * @param id - ID del administrador\n * @param request - Nuevos datos del administrador\n */\n async updateAdmin(id: number, request: UserAdminUpdateRequest): Promise<ResponseModel<AdminUser>> {\n return this.api.executePUT<AdminUser>(`${this.BASE_PATH}/admin/${id}`, request);\n }\n\n /**\n * Activa o desactiva un administrador.\n * @param id - ID del administrador\n */\n async toggleAdminStatus(id: number): Promise<ResponseModel<AdminUser>> {\n return this.api.executePUT<AdminUser>(`${this.BASE_PATH}/admin/${id}/toggle-status`);\n }\n\n /**\n * Actualiza la autenticación de un administrador.\n * @param id - ID del usuario\n * @param request - Nuevos datos de autenticación\n */\n async updateAdminAuthentication(id: number, request: UserAuthUpdateRequest): Promise<ResponseModel<AdminAuthentication>> {\n return this.api.executePUT<AdminAuthentication>(`${this.BASE_PATH}/admin/authentication/${id}`, request);\n }\n\n // #endregion\n\n // #region User Types\n\n /**\n * Obtiene todos los tipos de usuario con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getUserTypes(filter?: UserTypesFilter): Promise<ResponseModel<UserType[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/catalogs/user-types`, filter);\n return this.api.executeGET<UserType[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para tipos de usuario.\n */\n async getUserTypesFilters(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/catalogs/user-types/filters`, true);\n }\n\n /**\n * Obtiene un tipo de usuario por su ID.\n * @param id - ID del tipo de usuario\n */\n async getUserTypeById(id: number): Promise<ResponseModel<UserType>> {\n return this.api.executeGET<UserType>(`${this.BASE_PATH}/catalogs/user-types/${id}`, true);\n }\n\n /**\n * Crea un nuevo tipo de usuario.\n * @param request - Datos del tipo de usuario a crear\n */\n async createUserType(request: UserTypeRequest): Promise<ResponseModel<UserType>> {\n return this.api.executePOST<UserType>(`${this.BASE_PATH}/catalogs/user-types`, request);\n }\n\n /**\n * Actualiza un tipo de usuario existente.\n * @param id - ID del tipo de usuario a actualizar\n * @param request - Nuevos datos del tipo de usuario\n */\n async updateUserType(id: number, request: UserTypeRequest): Promise<ResponseModel<UserType>> {\n return this.api.executePUT<UserType>(`${this.BASE_PATH}/catalogs/user-types/${id}`, request);\n }\n\n /**\n * Elimina un tipo de usuario.\n * @param id - ID del tipo de usuario a eliminar\n */\n async deleteUserType(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/catalogs/user-types/${id}`);\n }\n\n // #endregion\n\n // #region Roles\n\n /**\n * Obtiene todos los roles con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getRoles(filter?: RolesFilter): Promise<ResponseModel<Role[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/catalogs/roles`, filter);\n return this.api.executeGET<Role[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para roles.\n */\n async getRolesFilters(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/catalogs/roles/filters`, true);\n }\n\n /**\n * Obtiene un rol por su ID.\n * @param id - ID del rol\n */\n async getRoleById(id: number): Promise<ResponseModel<Role>> {\n return this.api.executeGET<Role>(`${this.BASE_PATH}/catalogs/roles/${id}`, true);\n }\n\n /**\n * Obtiene los roles asociados a un tipo de usuario.\n * @param userTypeId - ID del tipo de usuario\n */\n async getRolesByUserType(userTypeId: number): Promise<ResponseModel<Role[]>> {\n return this.api.executeGET<Role[]>(`${this.BASE_PATH}/catalogs/roles/user-type/${userTypeId}`, true);\n }\n\n /**\n * Crea un nuevo rol.\n * @param request - Datos del rol a crear\n */\n async createRole(request: RoleRequest): Promise<ResponseModel<Role>> {\n return this.api.executePOST<Role>(`${this.BASE_PATH}/catalogs/roles`, request);\n }\n\n /**\n * Actualiza un rol existente.\n * @param id - ID del rol a actualizar\n * @param request - Nuevos datos del rol\n */\n async updateRole(id: number, request: RoleRequest): Promise<ResponseModel<Role>> {\n return this.api.executePUT<Role>(`${this.BASE_PATH}/catalogs/roles/${id}`, request);\n }\n\n /**\n * Activa o desactiva un rol.\n * @param id - ID del rol\n */\n async toggleRoleStatus(id: number): Promise<ResponseModel<Role>> {\n return this.api.executePUT<Role>(`${this.BASE_PATH}/catalogs/roles/${id}/toggle-status`);\n }\n\n /**\n * Elimina un rol.\n * @param id - ID del rol a eliminar\n */\n async deleteRole(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/catalogs/roles/${id}`);\n }\n\n // #endregion\n}\n","import { API } from \"@/core/API\";\nimport { ResponseModel } from \"@/types/ResponseModel\";\nimport { FilterBuilder, type FilterGroupsModel } from \"@/utils/FilterBuilder\";\nimport {\n Module,\n ModuleRequest,\n ModulesFilter,\n Endpoint,\n EndpointRequest,\n EndpointsFilter,\n UIRoute,\n UIRouteRequest,\n UIRoutesFilter\n} from \"@/interfaces/System\";\n\n/**\n * Servicio para gestionar las configuraciones del sistema.\n */\nexport class SystemService {\n private api: API;\n private readonly BASE_PATH = 'system';\n\n constructor(api: API) {\n this.api = api;\n }\n\n // #region MODULES\n\n /**\n * Obtiene todos los módulos con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getModules(filter?: ModulesFilter): Promise<ResponseModel<Module[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/modules`, filter);\n return this.api.executeGET<Module[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para módulos.\n */\n async getModulesFilters(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/modules/filters`, true);\n }\n\n /**\n * Obtiene un módulo por su ID.\n * @param id - ID del módulo\n */\n async getModuleById(id: number): Promise<ResponseModel<Module>> {\n return this.api.executeGET<Module>(`${this.BASE_PATH}/modules/${id}`, true);\n }\n\n /**\n * Crea un nuevo módulo.\n * @param request - Datos del módulo a crear\n */\n async createModule(request: ModuleRequest): Promise<ResponseModel<Module>> {\n return this.api.executePOST<Module>(`${this.BASE_PATH}/modules`, request);\n }\n\n /**\n * Actualiza un módulo existente.\n * @param id - ID del módulo a actualizar\n * @param request - Nuevos datos del módulo\n */\n async updateModule(id: number, request: ModuleRequest): Promise<ResponseModel<Module>> {\n return this.api.executePUT<Module>(`${this.BASE_PATH}/modules/${id}`, request);\n }\n\n /**\n * Activa o desactiva un módulo.\n * @param id - ID del módulo\n */\n async toggleModuleStatus(id: number): Promise<ResponseModel<Module>> {\n return this.api.executePUT<Module>(`${this.BASE_PATH}/modules/${id}/toggle-status`);\n }\n\n /**\n * Elimina un módulo.\n * @param id - ID del módulo a eliminar\n */\n async deleteModule(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/modules/${id}`);\n }\n\n // #endregion\n\n // #region ENDPOINTS\n\n /**\n * Obtiene todos los endpoints con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getEndpoints(filter?: EndpointsFilter): Promise<ResponseModel<Endpoint[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/endpoints`, filter);\n return this.api.executeGET<Endpoint[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para endpoints.\n */\n async getEndpointsFilters(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/endpoints/filters`, true);\n }\n\n /**\n * Obtiene los módulos disponibles (valores únicos del primer segmento del path).\n */\n async getEndpointModules(): Promise<ResponseModel<string[]>> {\n return this.api.executeGET<string[]>(`${this.BASE_PATH}/endpoints/modules`, true);\n }\n\n /**\n * Obtiene un endpoint por su ID.\n * @param id - ID del endpoint\n */\n async getEndpointById(id: number): Promise<ResponseModel<Endpoint>> {\n return this.api.executeGET<Endpoint>(`${this.BASE_PATH}/endpoints/${id}`, true);\n }\n\n /**\n * Crea un nuevo endpoint.\n * @param request - Datos del endpoint a crear\n */\n async createEndpoint(request: EndpointRequest): Promise<ResponseModel<Endpoint>> {\n return this.api.executePOST<Endpoint>(`${this.BASE_PATH}/endpoints`, request);\n }\n\n /**\n * Actualiza un endpoint existente.\n * @param id - ID del endpoint a actualizar\n * @param request - Nuevos datos del endpoint\n */\n async updateEndpoint(id: number, request: EndpointRequest): Promise<ResponseModel<Endpoint>> {\n return this.api.executePUT<Endpoint>(`${this.BASE_PATH}/endpoints/${id}`, request);\n }\n\n /**\n * Activa o desactiva un endpoint.\n * @param id - ID del endpoint\n */\n async toggleEndpointStatus(id: number): Promise<ResponseModel<Endpoint>> {\n return this.api.executePUT<Endpoint>(`${this.BASE_PATH}/endpoints/${id}/toggle-status`);\n }\n\n /**\n * Elimina un endpoint.\n * @param id - ID del endpoint a eliminar\n */\n async deleteEndpoint(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/endpoints/${id}`);\n }\n\n // #endregion\n\n // #region UI ROUTES\n\n /**\n * Obtiene todas las rutas de UI con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getUIRoutes(filter?: UIRoutesFilter): Promise<ResponseModel<UIRoute[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/ui-routes`, filter);\n return this.api.executeGET<UIRoute[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para rutas de UI.\n */\n async getUIRoutesFilters(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/ui-routes/filters`, true);\n }\n\n /**\n * Obtiene una ruta de UI por su ID.\n * @param id - ID de la ruta\n */\n async getUIRouteById(id: number): Promise<ResponseModel<UIRoute>> {\n return this.api.executeGET<UIRoute>(`${this.BASE_PATH}/ui-routes/${id}`, true);\n }\n\n /**\n * Crea una nueva ruta de UI.\n * @param request - Datos de la ruta a crear\n */\n async createUIRoute(request: UIRouteRequest): Promise<ResponseModel<UIRoute>> {\n return this.api.executePOST<UIRoute>(`${this.BASE_PATH}/ui-routes`, request);\n }\n\n /**\n * Actualiza una ruta de UI existente.\n * @param id - ID de la ruta a actualizar\n * @param request - Nuevos datos de la ruta\n */\n async updateUIRoute(id: number, request: UIRouteRequest): Promise<ResponseModel<UIRoute>> {\n return this.api.executePUT<UIRoute>(`${this.BASE_PATH}/ui-routes/${id}`, request);\n }\n\n /**\n * Activa o desactiva una ruta de UI.\n * @param id - ID de la ruta\n */\n async toggleUIRouteStatus(id: number): Promise<ResponseModel<UIRoute>> {\n return this.api.executePUT<UIRoute>(`${this.BASE_PATH}/ui-routes/${id}/toggle-status`);\n }\n\n /**\n * Elimina una ruta de UI.\n * @param id - ID de la ruta a eliminar\n */\n async deleteUIRoute(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/ui-routes/${id}`);\n }\n\n // #endregion\n}\n","import { API } from \"@/core/API\";\nimport { ResponseModel } from \"@/types/ResponseModel\";\nimport { FilterBuilder, type FilterGroupsModel } from \"@/utils/FilterBuilder\";\nimport {\n Location,\n LocationsRequest,\n LocationsFilter,\n InventoryStatus,\n InventoryStatusRequest,\n InventoryStatusesFilter,\n Packing,\n PackingRequest,\n PackingsFilter,\n Material,\n MaterialRequest,\n MaterialsFilter\n} from \"@/interfaces/Inventory\";\n\n/**\n * Servicio para gestionar inventario: ubicaciones, estatus, empaques y materiales.\n */\nexport class InventoryService {\n private api: API;\n private readonly BASE_PATH = 'inventory';\n\n constructor(api: API) {\n this.api = api;\n }\n\n // #region LOCATIONS\n\n /**\n * Obtiene todas las ubicaciones con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getLocations(filter?: LocationsFilter): Promise<ResponseModel<Location[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/locations`, filter);\n return this.api.executeGET<Location[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para ubicaciones.\n */\n async getLocationFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/locations/filters`, true);\n }\n\n /**\n * Obtiene una ubicación por su ID.\n * @param id - ID de la ubicación\n */\n async getLocationById(id: number): Promise<ResponseModel<Location>> {\n return this.api.executeGET<Location>(`${this.BASE_PATH}/locations/${id}`, true);\n }\n\n /**\n * Crea una nueva ubicación.\n * @param request - Datos de la ubicación a crear\n */\n async createLocation(request: LocationsRequest): Promise<ResponseModel<Location>> {\n return this.api.executePOST<Location>(`${this.BASE_PATH}/locations`, request);\n }\n\n /**\n * Actualiza una ubicación existente.\n * @param id - ID de la ubicación a actualizar\n * @param request - Nuevos datos de la ubicación\n */\n async updateLocation(id: number, request: LocationsRequest): Promise<ResponseModel<Location>> {\n return this.api.executePUT<Location>(`${this.BASE_PATH}/locations/${id}`, request);\n }\n\n /**\n * Activa o desactiva una ubicación.\n * @param id - ID de la ubicación\n */\n async toggleLocationStatus(id: number): Promise<ResponseModel<Location>> {\n return this.api.executePUT<Location>(`${this.BASE_PATH}/locations/${id}/toggle-status`);\n }\n\n /**\n * Elimina una ubicación.\n * @param id - ID de la ubicación a eliminar\n */\n async deleteLocation(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/locations/${id}`);\n }\n\n // #endregion\n\n // #region STATUSES\n\n /**\n * Obtiene todos los estatus de inventario con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getStatuses(filter?: InventoryStatusesFilter): Promise<ResponseModel<InventoryStatus[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/statuses`, filter);\n return this.api.executeGET<InventoryStatus[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para estatus de inventario.\n */\n async getStatusFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/statuses/filters`, true);\n }\n\n /**\n * Obtiene un estatus de inventario por su ID.\n * @param id - ID del estatus\n */\n async getStatusById(id: number): Promise<ResponseModel<InventoryStatus>> {\n return this.api.executeGET<InventoryStatus>(`${this.BASE_PATH}/statuses/${id}`, true);\n }\n\n /**\n * Crea un nuevo estatus de inventario.\n * @param request - Datos del estatus a crear\n */\n async createStatus(request: InventoryStatusRequest): Promise<ResponseModel<InventoryStatus>> {\n return this.api.executePOST<InventoryStatus>(`${this.BASE_PATH}/statuses`, request);\n }\n\n /**\n * Actualiza un estatus de inventario existente.\n * @param id - ID del estatus a actualizar\n * @param request - Nuevos datos del estatus\n */\n async updateStatus(id: number, request: InventoryStatusRequest): Promise<ResponseModel<InventoryStatus>> {\n return this.api.executePUT<InventoryStatus>(`${this.BASE_PATH}/statuses/${id}`, request);\n }\n\n /**\n * Activa o desactiva un estatus de inventario.\n * @param id - ID del estatus\n */\n async toggleStatusActive(id: number): Promise<ResponseModel<InventoryStatus>> {\n return this.api.executePUT<InventoryStatus>(`${this.BASE_PATH}/statuses/${id}/toggle-status`);\n }\n\n /**\n * Elimina un estatus de inventario.\n * @param id - ID del estatus a eliminar\n */\n async deleteStatus(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/statuses/${id}`);\n }\n\n // #endregion\n\n // #region PACKINGS\n\n /**\n * Obtiene todos los empaques con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getPackings(filter?: PackingsFilter): Promise<ResponseModel<Packing[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/packings`, filter);\n return this.api.executeGET<Packing[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para empaques.\n */\n async getPackingFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/packings/filters`, true);\n }\n\n /**\n * Obtiene un empaque por su ID.\n * @param id - ID del empaque\n */\n async getPackingById(id: number): Promise<ResponseModel<Packing>> {\n return this.api.executeGET<Packing>(`${this.BASE_PATH}/packings/${id}`, true);\n }\n\n /**\n * Crea un nuevo empaque.\n * @param request - Datos del empaque a crear\n */\n async createPacking(request: PackingRequest): Promise<ResponseModel<Packing>> {\n return this.api.executePOST<Packing>(`${this.BASE_PATH}/packings`, request);\n }\n\n /**\n * Actualiza un empaque existente.\n * @param id - ID del empaque a actualizar\n * @param request - Nuevos datos del empaque\n */\n async updatePacking(id: number, request: PackingRequest): Promise<ResponseModel<Packing>> {\n return this.api.executePUT<Packing>(`${this.BASE_PATH}/packings/${id}`, request);\n }\n\n /**\n * Elimina un empaque.\n * @param id - ID del empaque a eliminar\n */\n async deletePacking(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/packings/${id}`);\n }\n\n // #endregion\n\n // #region MATERIALS\n\n /**\n * Obtiene todos los materiales con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getMaterials(filter?: MaterialsFilter): Promise<ResponseModel<Material[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/materials`, filter);\n return this.api.executeGET<Material[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para materiales.\n */\n async getMaterialFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/materials/filters`, true);\n }\n\n /**\n * Obtiene un material por su ID.\n * @param id - ID del material\n */\n async getMaterialById(id: number): Promise<ResponseModel<Material>> {\n return this.api.executeGET<Material>(`${this.BASE_PATH}/materials/${id}`, true);\n }\n\n /**\n * Crea un nuevo material.\n * @param request - Datos del material a crear\n */\n async createMaterial(request: MaterialRequest): Promise<ResponseModel<Material>> {\n return this.api.executePOST<Material>(`${this.BASE_PATH}/materials`, request);\n }\n\n /**\n * Actualiza un material existente.\n * @param id - ID del material a actualizar\n * @param request - Nuevos datos del material\n */\n async updateMaterial(id: number, request: MaterialRequest): Promise<ResponseModel<Material>> {\n return this.api.executePUT<Material>(`${this.BASE_PATH}/materials/${id}`, request);\n }\n\n /**\n * Elimina un material.\n * @param id - ID del material a eliminar\n */\n async deleteMaterial(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/materials/${id}`);\n }\n\n // #endregion\n}\n","import { API } from \"@/core/API\";\nimport { ResponseModel } from \"@/types/ResponseModel\";\nimport { FilterBuilder, type FilterGroupsModel } from \"@/utils/FilterBuilder\";\nimport {\n ProductImage,\n ProductImageRequest,\n ProductImagesFilter,\n ProductBullet,\n ProductBulletRequest,\n ProductBulletsFilter,\n ProductKeyword,\n ProductKeywordRequest,\n ProductKeywordsFilter,\n ProductPrice,\n ProductPriceRequest,\n ProductPricesFilter,\n BlankProduct,\n BlankProductRequest,\n BlankProductsFilter,\n DetailProductPOD,\n DetailProductPODRequest,\n DetailProductPODFilter,\n Size,\n SizeRequest,\n SizesFilter,\n SizeGroup,\n SizeGroupRequest,\n SizeGroupsFilter,\n ProductType,\n ProductTypeRequest,\n ProductTypesFilter,\n ProductCategory,\n ProductCategoryRequest,\n ProductCategoriesFilter,\n ProductStatus,\n ProductStatusRequest,\n ProductStatusesFilter,\n Studio,\n StudioRequest,\n StudiosFilter,\n License,\n LicenseRequest,\n LicensesFilter,\n Provider,\n ProviderRequest,\n ProvidersFilter\n} from \"@/interfaces/Products\";\n\n/**\n * Servicio para gestionar productos y catálogos de productos.\n */\nexport class ProductService {\n private api: API;\n private readonly BASE_PATH = 'products';\n\n constructor(api: API) {\n this.api = api;\n }\n\n // #region PRODUCT IMAGES\n\n /**\n * Obtiene todas las imágenes de producto con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getImages(filter?: ProductImagesFilter): Promise<ResponseModel<ProductImage[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/images`, filter);\n return this.api.executeGET<ProductImage[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para imágenes de producto.\n */\n async getImageFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/images/filters`, true);\n }\n\n /**\n * Obtiene una imagen de producto por su ID.\n * @param id - ID de la imagen\n */\n async getImageById(id: number): Promise<ResponseModel<ProductImage>> {\n return this.api.executeGET<ProductImage>(`${this.BASE_PATH}/images/${id}`, true);\n }\n\n /**\n * Crea una nueva imagen de producto.\n * @param request - Datos de la imagen a crear\n */\n async createImage(request: ProductImageRequest): Promise<ResponseModel<ProductImage>> {\n return this.api.executePOST<ProductImage>(`${this.BASE_PATH}/images`, request);\n }\n\n /**\n * Actualiza una imagen de producto existente.\n * @param id - ID de la imagen a actualizar\n * @param request - Nuevos datos de la imagen\n */\n async updateImage(id: number, request: ProductImageRequest): Promise<ResponseModel<ProductImage>> {\n return this.api.executePUT<ProductImage>(`${this.BASE_PATH}/images/${id}`, request);\n }\n\n /**\n * Elimina una imagen de producto.\n * @param id - ID de la imagen a eliminar\n */\n async deleteImage(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/images/${id}`);\n }\n\n // #endregion\n\n // #region PRODUCT BULLETS\n\n /**\n * Obtiene todos los bullets de producto con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getBullets(filter?: ProductBulletsFilter): Promise<ResponseModel<ProductBullet[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/bullets`, filter);\n return this.api.executeGET<ProductBullet[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para bullets de producto.\n */\n async getBulletFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/bullets/filters`, true);\n }\n\n /**\n * Obtiene un bullet de producto por su ID.\n * @param id - ID del bullet\n */\n async getBulletById(id: number): Promise<ResponseModel<ProductBullet>> {\n return this.api.executeGET<ProductBullet>(`${this.BASE_PATH}/bullets/${id}`, true);\n }\n\n /**\n * Crea un nuevo bullet de producto.\n * @param request - Datos del bullet a crear\n */\n async createBullet(request: ProductBulletRequest): Promise<ResponseModel<ProductBullet>> {\n return this.api.executePOST<ProductBullet>(`${this.BASE_PATH}/bullets`, request);\n }\n\n /**\n * Actualiza un bullet de producto existente.\n * @param id - ID del bullet a actualizar\n * @param request - Nuevos datos del bullet\n */\n async updateBullet(id: number, request: ProductBulletRequest): Promise<ResponseModel<ProductBullet>> {\n return this.api.executePUT<ProductBullet>(`${this.BASE_PATH}/bullets/${id}`, request);\n }\n\n /**\n * Elimina un bullet de producto.\n * @param id - ID del bullet a eliminar\n */\n async deleteBullet(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/bullets/${id}`);\n }\n\n // #endregion\n\n // #region PRODUCT KEYWORDS\n\n /**\n * Obtiene todos los keywords de producto con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getKeywords(filter?: ProductKeywordsFilter): Promise<ResponseModel<ProductKeyword[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/keywords`, filter);\n return this.api.executeGET<ProductKeyword[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para keywords de producto.\n */\n async getKeywordFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/keywords/filters`, true);\n }\n\n /**\n * Obtiene un keyword de producto por su ID.\n * @param id - ID del keyword\n */\n async getKeywordById(id: number): Promise<ResponseModel<ProductKeyword>> {\n return this.api.executeGET<ProductKeyword>(`${this.BASE_PATH}/keywords/${id}`, true);\n }\n\n /**\n * Crea un nuevo keyword de producto.\n * @param request - Datos del keyword a crear\n */\n async createKeyword(request: ProductKeywordRequest): Promise<ResponseModel<ProductKeyword>> {\n return this.api.executePOST<ProductKeyword>(`${this.BASE_PATH}/keywords`, request);\n }\n\n /**\n * Actualiza un keyword de producto existente.\n * @param id - ID del keyword a actualizar\n * @param request - Nuevos datos del keyword\n */\n async updateKeyword(id: number, request: ProductKeywordRequest): Promise<ResponseModel<ProductKeyword>> {\n return this.api.executePUT<ProductKeyword>(`${this.BASE_PATH}/keywords/${id}`, request);\n }\n\n /**\n * Elimina un keyword de producto.\n * @param id - ID del keyword a eliminar\n */\n async deleteKeyword(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/keywords/${id}`);\n }\n\n // #endregion\n\n // #region PRODUCT PRICES\n\n /**\n * Obtiene todos los precios de producto con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getPrices(filter?: ProductPricesFilter): Promise<ResponseModel<ProductPrice[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/prices`, filter);\n return this.api.executeGET<ProductPrice[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para precios de producto.\n */\n async getPriceFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/prices/filters`, true);\n }\n\n /**\n * Obtiene un precio de producto por su ID.\n * @param id - ID del precio\n */\n async getPriceById(id: number): Promise<ResponseModel<ProductPrice>> {\n return this.api.executeGET<ProductPrice>(`${this.BASE_PATH}/prices/${id}`, true);\n }\n\n /**\n * Crea un nuevo precio de producto.\n * @param request - Datos del precio a crear\n */\n async createPrice(request: ProductPriceRequest): Promise<ResponseModel<ProductPrice>> {\n return this.api.executePOST<ProductPrice>(`${this.BASE_PATH}/prices`, request);\n }\n\n /**\n * Actualiza un precio de producto existente.\n * @param id - ID del precio a actualizar\n * @param request - Nuevos datos del precio\n */\n async updatePrice(id: number, request: ProductPriceRequest): Promise<ResponseModel<ProductPrice>> {\n return this.api.executePUT<ProductPrice>(`${this.BASE_PATH}/prices/${id}`, request);\n }\n\n /**\n * Elimina un precio de producto.\n * @param id - ID del precio a eliminar\n */\n async deletePrice(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/prices/${id}`);\n }\n\n // #endregion\n\n // #region BLANK PRODUCTS\n\n /**\n * Obtiene todos los productos en blanco con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getBlankProducts(filter?: BlankProductsFilter): Promise<ResponseModel<BlankProduct[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/blanks`, filter);\n return this.api.executeGET<BlankProduct[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para productos en blanco.\n */\n async getBlankProductFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/blanks/filters`, true);\n }\n\n /**\n * Obtiene un producto en blanco por su ID.\n * @param id - ID del producto en blanco\n */\n async getBlankProductById(id: number): Promise<ResponseModel<BlankProduct>> {\n return this.api.executeGET<BlankProduct>(`${this.BASE_PATH}/blanks/${id}`, true);\n }\n\n /**\n * Crea un nuevo producto en blanco.\n * @param request - Datos del producto en blanco a crear\n */\n async createBlankProduct(request: BlankProductRequest): Promise<ResponseModel<BlankProduct>> {\n return this.api.executePOST<BlankProduct>(`${this.BASE_PATH}/blanks`, request);\n }\n\n /**\n * Actualiza un producto en blanco existente.\n * @param id - ID del producto en blanco a actualizar\n * @param request - Nuevos datos del producto en blanco\n */\n async updateBlankProduct(id: number, request: BlankProductRequest): Promise<ResponseModel<BlankProduct>> {\n return this.api.executePUT<BlankProduct>(`${this.BASE_PATH}/blanks/${id}`, request);\n }\n\n /**\n * Elimina un producto en blanco.\n * @param id - ID del producto en blanco a eliminar\n */\n async deleteBlankProduct(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/blanks/${id}`);\n }\n\n // #endregion\n\n // #region DETAIL PRODUCT POD\n\n /**\n * Obtiene todos los detalles de producto POD con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getPODDetails(filter?: DetailProductPODFilter): Promise<ResponseModel<DetailProductPOD[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/pod-details`, filter);\n return this.api.executeGET<DetailProductPOD[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para detalles de producto POD.\n */\n async getPODDetailFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/pod-details/filters`, true);\n }\n\n /**\n * Obtiene un detalle de producto POD por su ID.\n * @param id - ID del detalle POD\n */\n async getPODDetailById(id: number): Promise<ResponseModel<DetailProductPOD>> {\n return this.api.executeGET<DetailProductPOD>(`${this.BASE_PATH}/pod-details/${id}`, true);\n }\n\n /**\n * Crea un nuevo detalle de producto POD.\n * @param request - Datos del detalle POD a crear\n */\n async createPODDetail(request: DetailProductPODRequest): Promise<ResponseModel<DetailProductPOD>> {\n return this.api.executePOST<DetailProductPOD>(`${this.BASE_PATH}/pod-details`, request);\n }\n\n /**\n * Actualiza un detalle de producto POD existente.\n * @param id - ID del detalle POD a actualizar\n * @param request - Nuevos datos del detalle POD\n */\n async updatePODDetail(id: number, request: DetailProductPODRequest): Promise<ResponseModel<DetailProductPOD>> {\n return this.api.executePUT<DetailProductPOD>(`${this.BASE_PATH}/pod-details/${id}`, request);\n }\n\n /**\n * Elimina un detalle de producto POD.\n * @param id - ID del detalle POD a eliminar\n */\n async deletePODDetail(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/pod-details/${id}`);\n }\n\n // #endregion\n\n // #region CATALOG - SIZES\n\n /**\n * Obtiene todas las tallas con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getSizes(filter?: SizesFilter): Promise<ResponseModel<Size[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/catalog/sizes`, filter);\n return this.api.executeGET<Size[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para tallas.\n */\n async getSizeFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/catalog/sizes/filters`, true);\n }\n\n /**\n * Obtiene una talla por su ID.\n * @param id - ID de la talla\n */\n async getSizeById(id: number): Promise<ResponseModel<Size>> {\n return this.api.executeGET<Size>(`${this.BASE_PATH}/catalog/sizes/${id}`, true);\n }\n\n /**\n * Crea una nueva talla.\n * @param request - Datos de la talla a crear\n */\n async createSize(request: SizeRequest): Promise<ResponseModel<Size>> {\n return this.api.executePOST<Size>(`${this.BASE_PATH}/catalog/sizes`, request);\n }\n\n /**\n * Actualiza una talla existente.\n * @param id - ID de la talla a actualizar\n * @param request - Nuevos datos de la talla\n */\n async updateSize(id: number, request: SizeRequest): Promise<ResponseModel<Size>> {\n return this.api.executePUT<Size>(`${this.BASE_PATH}/catalog/sizes/${id}`, request);\n }\n\n /**\n * Elimina una talla.\n * @param id - ID de la talla a eliminar\n */\n async deleteSize(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/catalog/sizes/${id}`);\n }\n\n // #endregion\n\n // #region CATALOG - SIZE GROUPS\n\n /**\n * Obtiene todos los grupos de tallas con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getSizeGroups(filter?: SizeGroupsFilter): Promise<ResponseModel<SizeGroup[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/catalog/size-groups`, filter);\n return this.api.executeGET<SizeGroup[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para grupos de tallas.\n */\n async getSizeGroupFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/catalog/size-groups/filters`, true);\n }\n\n /**\n * Obtiene un grupo de tallas por su ID.\n * @param id - ID del grupo de tallas\n */\n async getSizeGroupById(id: number): Promise<ResponseModel<SizeGroup>> {\n return this.api.executeGET<SizeGroup>(`${this.BASE_PATH}/catalog/size-groups/${id}`, true);\n }\n\n /**\n * Crea un nuevo grupo de tallas.\n * @param request - Datos del grupo de tallas a crear\n */\n async createSizeGroup(request: SizeGroupRequest): Promise<ResponseModel<SizeGroup>> {\n return this.api.executePOST<SizeGroup>(`${this.BASE_PATH}/catalog/size-groups`, request);\n }\n\n /**\n * Actualiza un grupo de tallas existente.\n * @param id - ID del grupo de tallas a actualizar\n * @param request - Nuevos datos del grupo de tallas\n */\n async updateSizeGroup(id: number, request: SizeGroupRequest): Promise<ResponseModel<SizeGroup>> {\n return this.api.executePUT<SizeGroup>(`${this.BASE_PATH}/catalog/size-groups/${id}`, request);\n }\n\n /**\n * Elimina un grupo de tallas.\n * @param id - ID del grupo de tallas a eliminar\n */\n async deleteSizeGroup(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/catalog/size-groups/${id}`);\n }\n\n // #endregion\n\n // #region CATALOG - PRODUCT TYPES\n\n /**\n * Obtiene todos los tipos de producto con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getProductTypes(filter?: ProductTypesFilter): Promise<ResponseModel<ProductType[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/catalog/product-types`, filter);\n return this.api.executeGET<ProductType[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para tipos de producto.\n */\n async getProductTypeFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/catalog/product-types/filters`, true);\n }\n\n /**\n * Obtiene un tipo de producto por su ID.\n * @param id - ID del tipo de producto\n */\n async getProductTypeById(id: number): Promise<ResponseModel<ProductType>> {\n return this.api.executeGET<ProductType>(`${this.BASE_PATH}/catalog/product-types/${id}`, true);\n }\n\n /**\n * Crea un nuevo tipo de producto.\n * @param request - Datos del tipo de producto a crear\n */\n async createProductType(request: ProductTypeRequest): Promise<ResponseModel<ProductType>> {\n return this.api.executePOST<ProductType>(`${this.BASE_PATH}/catalog/product-types`, request);\n }\n\n /**\n * Actualiza un tipo de producto existente.\n * @param id - ID del tipo de producto a actualizar\n * @param request - Nuevos datos del tipo de producto\n */\n async updateProductType(id: number, request: ProductTypeRequest): Promise<ResponseModel<ProductType>> {\n return this.api.executePUT<ProductType>(`${this.BASE_PATH}/catalog/product-types/${id}`, request);\n }\n\n /**\n * Elimina un tipo de producto.\n * @param id - ID del tipo de producto a eliminar\n */\n async deleteProductType(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/catalog/product-types/${id}`);\n }\n\n // #endregion\n\n // #region CATALOG - PRODUCT CATEGORIES\n\n /**\n * Obtiene todas las categorías de producto con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getProductCategories(filter?: ProductCategoriesFilter): Promise<ResponseModel<ProductCategory[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/catalog/product-categories`, filter);\n return this.api.executeGET<ProductCategory[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para categorías de producto.\n */\n async getProductCategoryFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/catalog/product-categories/filters`, true);\n }\n\n /**\n * Obtiene una categoría de producto por su ID.\n * @param id - ID de la categoría\n */\n async getProductCategoryById(id: number): Promise<ResponseModel<ProductCategory>> {\n return this.api.executeGET<ProductCategory>(`${this.BASE_PATH}/catalog/product-categories/${id}`, true);\n }\n\n /**\n * Crea una nueva categoría de producto.\n * @param request - Datos de la categoría a crear\n */\n async createProductCategory(request: ProductCategoryRequest): Promise<ResponseModel<ProductCategory>> {\n return this.api.executePOST<ProductCategory>(`${this.BASE_PATH}/catalog/product-categories`, request);\n }\n\n /**\n * Actualiza una categoría de producto existente.\n * @param id - ID de la categoría a actualizar\n * @param request - Nuevos datos de la categoría\n */\n async updateProductCategory(id: number, request: ProductCategoryRequest): Promise<ResponseModel<ProductCategory>> {\n return this.api.executePUT<ProductCategory>(`${this.BASE_PATH}/catalog/product-categories/${id}`, request);\n }\n\n /**\n * Activa o desactiva una categoría de producto.\n * @param id - ID de la categoría\n */\n async toggleProductCategoryStatus(id: number): Promise<ResponseModel<ProductCategory>> {\n return this.api.executePUT<ProductCategory>(`${this.BASE_PATH}/catalog/product-categories/${id}/toggle-status`);\n }\n\n /**\n * Elimina una categoría de producto.\n * @param id - ID de la categoría a eliminar\n */\n async deleteProductCategory(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/catalog/product-categories/${id}`);\n }\n\n // #endregion\n\n // #region CATALOG - PRODUCT STATUSES\n\n /**\n * Obtiene todos los estatus de producto con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getProductStatuses(filter?: ProductStatusesFilter): Promise<ResponseModel<ProductStatus[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/catalog/product-statuses`, filter);\n return this.api.executeGET<ProductStatus[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para estatus de producto.\n */\n async getProductStatusFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/catalog/product-statuses/filters`, true);\n }\n\n /**\n * Obtiene un estatus de producto por su ID.\n * @param id - ID del estatus\n */\n async getProductStatusById(id: number): Promise<ResponseModel<ProductStatus>> {\n return this.api.executeGET<ProductStatus>(`${this.BASE_PATH}/catalog/product-statuses/${id}`, true);\n }\n\n /**\n * Crea un nuevo estatus de producto.\n * @param request - Datos del estatus a crear\n */\n async createProductStatus(request: ProductStatusRequest): Promise<ResponseModel<ProductStatus>> {\n return this.api.executePOST<ProductStatus>(`${this.BASE_PATH}/catalog/product-statuses`, request);\n }\n\n /**\n * Actualiza un estatus de producto existente.\n * @param id - ID del estatus a actualizar\n * @param request - Nuevos datos del estatus\n */\n async updateProductStatus(id: number, request: ProductStatusRequest): Promise<ResponseModel<ProductStatus>> {\n return this.api.executePUT<ProductStatus>(`${this.BASE_PATH}/catalog/product-statuses/${id}`, request);\n }\n\n /**\n * Elimina un estatus de producto.\n * @param id - ID del estatus a eliminar\n */\n async deleteProductStatus(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/catalog/product-statuses/${id}`);\n }\n\n // #endregion\n\n // #region CATALOG - STUDIOS\n\n /**\n * Obtiene todos los estudios con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getStudios(filter?: StudiosFilter): Promise<ResponseModel<Studio[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/catalog/studios`, filter);\n return this.api.executeGET<Studio[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para estudios.\n */\n async getStudioFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/catalog/studios/filters`, true);\n }\n\n /**\n * Obtiene un estudio por su ID.\n * @param id - ID del estudio\n */\n async getStudioById(id: number): Promise<ResponseModel<Studio>> {\n return this.api.executeGET<Studio>(`${this.BASE_PATH}/catalog/studios/${id}`, true);\n }\n\n /**\n * Crea un nuevo estudio.\n * @param request - Datos del estudio a crear\n */\n async createStudio(request: StudioRequest): Promise<ResponseModel<Studio>> {\n return this.api.executePOST<Studio>(`${this.BASE_PATH}/catalog/studios`, request);\n }\n\n /**\n * Actualiza un estudio existente.\n * @param id - ID del estudio a actualizar\n * @param request - Nuevos datos del estudio\n */\n async updateStudio(id: number, request: StudioRequest): Promise<ResponseModel<Studio>> {\n return this.api.executePUT<Studio>(`${this.BASE_PATH}/catalog/studios/${id}`, request);\n }\n\n /**\n * Activa o desactiva un estudio.\n * @param id - ID del estudio\n */\n async toggleStudioStatus(id: number): Promise<ResponseModel<Studio>> {\n return this.api.executePUT<Studio>(`${this.BASE_PATH}/catalog/studios/${id}/toggle-status`);\n }\n\n /**\n * Elimina un estudio.\n * @param id - ID del estudio a eliminar\n */\n async deleteStudio(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/catalog/studios/${id}`);\n }\n\n // #endregion\n\n // #region CATALOG - LICENSES\n\n /**\n * Obtiene todas las licencias con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getLicenses(filter?: LicensesFilter): Promise<ResponseModel<License[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/catalog/licenses`, filter);\n return this.api.executeGET<License[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para licencias.\n */\n async getLicenseFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/catalog/licenses/filters`, true);\n }\n\n /**\n * Obtiene una licencia por su ID.\n * @param id - ID de la licencia\n */\n async getLicenseById(id: number): Promise<ResponseModel<License>> {\n return this.api.executeGET<License>(`${this.BASE_PATH}/catalog/licenses/${id}`, true);\n }\n\n /**\n * Crea una nueva licencia.\n * @param request - Datos de la licencia a crear\n */\n async createLicense(request: LicenseRequest): Promise<ResponseModel<License>> {\n return this.api.executePOST<License>(`${this.BASE_PATH}/catalog/licenses`, request);\n }\n\n /**\n * Actualiza una licencia existente.\n * @param id - ID de la licencia a actualizar\n * @param request - Nuevos datos de la licencia\n */\n async updateLicense(id: number, request: LicenseRequest): Promise<ResponseModel<License>> {\n return this.api.executePUT<License>(`${this.BASE_PATH}/catalog/licenses/${id}`, request);\n }\n\n /**\n * Activa o desactiva una licencia.\n * @param id - ID de la licencia\n */\n async toggleLicenseStatus(id: number): Promise<ResponseModel<License>> {\n return this.api.executePUT<License>(`${this.BASE_PATH}/catalog/licenses/${id}/toggle-status`);\n }\n\n /**\n * Elimina una licencia.\n * @param id - ID de la licencia a eliminar\n */\n async deleteLicense(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/catalog/licenses/${id}`);\n }\n\n // #endregion\n\n // #region CATALOG - PROVIDERS\n\n /**\n * Obtiene todos los proveedores con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getProviders(filter?: ProvidersFilter): Promise<ResponseModel<Provider[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/catalog/providers`, filter);\n return this.api.executeGET<Provider[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para proveedores.\n */\n async getProviderFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/catalog/providers/filters`, true);\n }\n\n /**\n * Obtiene un proveedor por su ID.\n * @param id - ID del proveedor\n */\n async getProviderById(id: number): Promise<ResponseModel<Provider>> {\n return this.api.executeGET<Provider>(`${this.BASE_PATH}/catalog/providers/${id}`, true);\n }\n\n /**\n * Crea un nuevo proveedor.\n * @param request - Datos del proveedor a crear\n */\n async createProvider(request: ProviderRequest): Promise<ResponseModel<Provider>> {\n return this.api.executePOST<Provider>(`${this.BASE_PATH}/catalog/providers`, request);\n }\n\n /**\n * Actualiza un proveedor existente.\n * @param id - ID del proveedor a actualizar\n * @param request - Nuevos datos del proveedor\n */\n async updateProvider(id: number, request: ProviderRequest): Promise<ResponseModel<Provider>> {\n return this.api.executePUT<Provider>(`${this.BASE_PATH}/catalog/providers/${id}`, request);\n }\n\n /**\n * Activa o desactiva un proveedor.\n * @param id - ID del proveedor\n */\n async toggleProviderStatus(id: number): Promise<ResponseModel<Provider>> {\n return this.api.executePUT<Provider>(`${this.BASE_PATH}/catalog/providers/${id}/toggle-status`);\n }\n\n /**\n * Elimina un proveedor.\n * @param id - ID del proveedor a eliminar\n */\n async deleteProvider(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/catalog/providers/${id}`);\n }\n\n // #endregion\n}\n","import { API } from \"@/core/API\";\nimport { ResponseModel } from \"@/types/ResponseModel\";\nimport { FilterBuilder, type FilterGroupsModel } from \"@/utils/FilterBuilder\";\nimport {\n Gender,\n GenderRequest,\n GendersFilter,\n AreaCode,\n AreaCodeRequest,\n AreaCodesFilter\n} from \"@/interfaces/Catalogs\";\n\n/**\n * Servicio para gestionar catálogos públicos.\n * No requiere autenticación.\n */\nexport class CatalogService {\n private api: API;\n private readonly BASE_PATH = 'catalogs';\n\n constructor(api: API) {\n this.api = api;\n }\n\n // #region GENDERS\n\n /**\n * Obtiene todos los géneros con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getGenders(filter?: GendersFilter): Promise<ResponseModel<Gender[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/genders`, filter);\n return this.api.executeGET<Gender[]>(endpoint, false);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para géneros.\n */\n async getGendersFilters(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/genders/filters`, false);\n }\n\n /**\n * Obtiene un género por su ID.\n * @param id - ID del género\n */\n async getGenderById(id: number): Promise<ResponseModel<Gender>> {\n return this.api.executeGET<Gender>(`${this.BASE_PATH}/genders/${id}`, false);\n }\n\n /**\n * Crea un nuevo género.\n * @param request - Datos del género a crear\n */\n async createGender(request: GenderRequest): Promise<ResponseModel<Gender>> {\n return this.api.executePOST<Gender>(`${this.BASE_PATH}/genders`, request);\n }\n\n /**\n * Actualiza un género existente.\n * @param id - ID del género a actualizar\n * @param request - Nuevos datos del género\n */\n async updateGender(id: number, request: GenderRequest): Promise<ResponseModel<Gender>> {\n return this.api.executePUT<Gender>(`${this.BASE_PATH}/genders/${id}`, request);\n }\n\n /**\n * Elimina un género.\n * @param id - ID del género a eliminar\n */\n async deleteGender(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/genders/${id}`);\n }\n\n // #endregion\n\n // #region AREA CODES\n\n /**\n * Obtiene todos los códigos de área con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getAreaCodes(filter?: AreaCodesFilter): Promise<ResponseModel<AreaCode[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/area-codes`, filter);\n return this.api.executeGET<AreaCode[]>(endpoint, false);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para códigos de área.\n */\n async getAreaCodesFilters(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/area-codes/filters`, false);\n }\n\n /**\n * Obtiene un código de área por su ID.\n * @param id - ID del código de área\n */\n async getAreaCodeById(id: number): Promise<ResponseModel<AreaCode>> {\n return this.api.executeGET<AreaCode>(`${this.BASE_PATH}/area-codes/${id}`, false);\n }\n\n /**\n * Crea un nuevo código de área.\n * @param request - Datos del código de área a crear\n */\n async createAreaCode(request: AreaCodeRequest): Promise<ResponseModel<AreaCode>> {\n return this.api.executePOST<AreaCode>(`${this.BASE_PATH}/area-codes`, request);\n }\n\n /**\n * Actualiza un código de área existente.\n * @param id - ID del código de área a actualizar\n * @param request - Nuevos datos del código de área\n */\n async updateAreaCode(id: number, request: AreaCodeRequest): Promise<ResponseModel<AreaCode>> {\n return this.api.executePUT<AreaCode>(`${this.BASE_PATH}/area-codes/${id}`, request);\n }\n\n /**\n * Activa o desactiva un código de área.\n * @param id - ID del código de área\n */\n async toggleAreaCodeStatus(id: number): Promise<ResponseModel<AreaCode>> {\n return this.api.executePUT<AreaCode>(`${this.BASE_PATH}/area-codes/${id}/toggle-status`);\n }\n\n /**\n * Elimina un código de área.\n * @param id - ID del código de área a eliminar\n */\n async deleteAreaCode(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/area-codes/${id}`);\n }\n\n // #endregion\n}\n","import { API } from \"./core/API\";\nimport { CryptoService } from \"./core/CryptoService\";\nimport { TokenManager } from \"./core/TokenManager\";\nimport { AuthInterceptor } from \"./core/interceptors/AuthInterceptor\";\nimport { ServiceProperties } from \"./types/ServiceProperties\";\nimport { TokenData } from \"./types/TokenData\";\nimport { AuthService } from \"./services/AuthService\";\nimport { UserService } from \"./services/UserService\";\nimport { SystemService } from \"./services/SystemService\";\nimport { InventoryService } from \"./services/InventoryService\";\nimport { ProductService } from \"./services/ProductService\";\nimport { CatalogService } from \"./services/CatalogService\";\n\n/**\n * SDK principal de FalconHUB\n */\nexport class FalconHUBSDK {\n public auth: AuthService;\n public user: UserService;\n public system: SystemService;\n public inventory: InventoryService;\n public product: ProductService;\n public catalog: CatalogService;\n\n private serviceProperties: ServiceProperties;\n private cryptoService: CryptoService;\n private tokenManager: TokenManager;\n private authInterceptor: AuthInterceptor | null;\n private api: API;\n\n constructor(serviceProperties: ServiceProperties) {\n this.serviceProperties = serviceProperties;\n\n this.cryptoService = new CryptoService();\n\n const autoRefreshConfig = this.normalizeAutoRefreshConfig(this.serviceProperties.autoRefresh);\n\n this.tokenManager = new TokenManager(\n this.serviceProperties.onTokensUpdated,\n this.serviceProperties.onSessionExpiring,\n async () => {\n await this.auth.logout();\n },\n async () => {\n const currentTokens = this.tokenManager.getTokens();\n if (!currentTokens?.refreshToken) return false;\n\n try {\n const response = await this.auth.refreshTokens({\n refreshToken: currentTokens.refreshToken,\n rememberMe: currentTokens.rememberMe\n });\n return response.success === true;\n } catch {\n return false;\n }\n },\n autoRefreshConfig.enabled ? autoRefreshConfig.thresholdMinutes : undefined\n );\n\n if (autoRefreshConfig.enabled) {\n this.authInterceptor = new AuthInterceptor({\n enabled: true,\n thresholdMinutes: autoRefreshConfig.thresholdMinutes,\n isTokenExpiringSoon: () => this.tokenManager.isTokenExpiringSoon(autoRefreshConfig.thresholdMinutes),\n hasValidTokens: () => this.tokenManager.hasValidTokens(),\n shouldAutoRefresh: () => this.tokenManager.shouldAutoRefresh(),\n refreshSession: async () => {\n await this.auth.validateSession();\n }\n });\n } else {\n this.authInterceptor = null;\n }\n\n this.api = new API(\n this.serviceProperties,\n this.cryptoService,\n this.authInterceptor,\n () => this.tokenManager.getAccessToken(),\n () => this.tokenManager.getRefreshToken()\n );\n\n this.auth = new AuthService(\n this.serviceProperties,\n this.tokenManager,\n this.cryptoService,\n this.api\n );\n\n this.user = new UserService(\n this.api\n );\n\n this.system = new SystemService(\n this.api\n );\n\n this.inventory = new InventoryService(\n this.api\n );\n\n this.product = new ProductService(\n this.api\n );\n\n this.catalog = new CatalogService(\n this.api\n );\n }\n\n private normalizeAutoRefreshConfig(\n config: ServiceProperties[\"autoRefresh\"]\n ): { enabled: boolean; thresholdMinutes: number } {\n if (typeof config === \"boolean\") {\n return { enabled: config, thresholdMinutes: 5 };\n }\n if (typeof config === \"object\" && config !== null) {\n return {\n enabled: config.enabled,\n thresholdMinutes: config.thresholdMinutes ?? 5\n };\n }\n return { enabled: true, thresholdMinutes: 5 };\n }\n\n /**\n * Inyecta tokens desde storage externo (cookies/localStorage/etc)\n * @param expiresAt - Timestamp en milisegundos\n */\n setTokensFromExternal(\n accessToken: string,\n refreshToken: string,\n expiresAt: number,\n rememberMe: boolean = false\n ): void {\n const tokens: TokenData = {\n accessToken,\n refreshToken,\n expiresAt,\n rememberMe\n };\n\n this.tokenManager.setTokensSilent(tokens);\n }\n\n /**\n * Obtiene los tokens actuales\n */\n getTokens(): TokenData | null {\n return this.tokenManager.getTokens();\n }\n\n /**\n * Verifica si el usuario está autenticado\n */\n isAuthenticated(): boolean {\n return this.tokenManager.hasValidTokens();\n }\n\n /**\n * Verifica si la sesión está por expirar\n */\n isSessionExpiringSoon(thresholdMinutes: number = 5): boolean {\n return this.tokenManager.isTokenExpiringSoon(thresholdMinutes);\n }\n\n /**\n * Obtiene el tiempo restante hasta la expiración en milisegundos\n */\n getTimeUntilExpiry(): number | null {\n return this.tokenManager.getTimeUntilExpiry();\n }\n}\n","import CryptoJS from 'crypto-js';\n\nexport function decrypt(encryptedBase64: string, secret: string, timestamp: string): string {\n const fullKey = `${secret}:${timestamp}`;\n // Generate key using SHA256\n const key = CryptoJS.SHA256(fullKey);\n\n // Parse total encrypted data from Base64\n const allData = CryptoJS.enc.Base64.parse(encryptedBase64);\n\n // Extract IV (first 16 bytes = 4 words)\n const iv = CryptoJS.lib.WordArray.create(allData.words.slice(0, 4), 16);\n\n // Extract ciphertext (remaining bytes)\n const ciphertext = CryptoJS.lib.WordArray.create(allData.words.slice(4), allData.sigBytes - 16);\n\n // Decrypt using AES-256-CBC\n // We use PKCS7 padding as it's the default in Node.js createDecipheriv for aes-256-cbc\n const decrypted = CryptoJS.AES.decrypt(\n { ciphertext: ciphertext } as any,\n key,\n {\n iv: iv,\n mode: CryptoJS.mode.CBC,\n padding: CryptoJS.pad.Pkcs7\n }\n );\n\n return decrypted.toString(CryptoJS.enc.Utf8);\n}\n"],"mappings":"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","names":["CryptoJS"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/API.ts","../src/core/CryptoService.ts","../src/core/TokenManager.ts","../src/core/interceptors/AuthInterceptor.ts","../src/types/ErrorResponse.ts","../src/services/AuthService.ts","../src/utils/FilterBuilder.ts","../src/services/UserService.ts","../src/services/SystemService.ts","../src/services/InventoryService.ts","../src/services/ProductService.ts","../src/services/CatalogService.ts","../src/FalconHUBSDK.ts","../src/core/Encryption.ts"],"sourcesContent":["import { ServiceProperties } from \"@/types/ServiceProperties\";\nimport { CryptoService } from \"./CryptoService\";\nimport { MethodTypes, RequestOptions } from \"@/types/RequestOptions\";\nimport { RequestConfig } from \"@/types/RequestConfig\";\nimport { AuthInterceptor } from \"./interceptors/AuthInterceptor\";\nimport { InterceptorContext } from \"@/core/interceptors/types/InterceptorContext\";\nimport { ResponseModel } from \"@/types/ResponseModel\";\n\n\n/**\n * Clase base para la ejecución de request HTTP al API\n */\nexport class API {\n private properties: ServiceProperties;\n private cryptoService: CryptoService;\n private authInterceptor: AuthInterceptor | null;\n\n private getAccessToken: () => string | null;\n private getRefreshToken: () => string | null;\n\n constructor(\n properties: ServiceProperties,\n cryptoService: CryptoService,\n authInterceptor: AuthInterceptor | null,\n getAccessToken: () => string | null,\n getRefreshToken: () => string | null\n ) {\n this.properties = properties;\n this.cryptoService = cryptoService;\n this.getAccessToken = getAccessToken;\n this.getRefreshToken = getRefreshToken;\n this.authInterceptor = authInterceptor;\n };\n\n /**\n * Ejecuta una request HTTP al API\n *\n * @param options - Opciones de la request\n * @returns Respuesta del tipo ResponseModel\n */\n private async apiExecute<T>(options: RequestOptions): Promise<ResponseModel<T>> {\n const {\n endpoint,\n method,\n body,\n requiresAuth,\n timeStamp\n } = options;\n\n const context: InterceptorContext = {\n requestId: this.cryptoService.generateUniqueId(),\n startTime: Date.now(),\n retryCount: 0,\n metadata: {}\n };\n\n try {\n const url = `${this.properties.url}/${endpoint}`;\n const headers: Record<string, string> = {};\n\n if (body && method !== 'GET') {\n headers['Content-Type'] = 'application/json';\n };\n\n const accessToken = this.getAccessToken();\n if (accessToken) {\n headers['Authorization'] = `Bearer ${accessToken}`;\n };\n\n const newTimeStamp = timeStamp || new Date().toISOString();\n\n headers[\"X-Origin-Request\"] = this.properties.originRequest;\n headers['X-Timestamp'] = newTimeStamp;\n headers[\"X-Domain\"] = this.properties.domain;\n headers[\"X-Device\"] = this.properties.device;\n headers[\"X-Source\"] = this.properties.source;\n\n let bodyString: string | undefined;\n if (body && method !== 'GET') {\n bodyString = JSON.stringify(body);\n };\n\n const requestConfig: RequestConfig = {\n url,\n method,\n headers,\n body: bodyString,\n requiresAuth\n };\n\n const modifiedConfig = this.authInterceptor\n ? await this.authInterceptor.onRequest(requestConfig, context)\n : requestConfig;\n\n const requestInit: RequestInit = {\n method: modifiedConfig.method,\n headers: modifiedConfig.headers,\n mode: 'cors',\n credentials: 'omit'\n };\n\n if (modifiedConfig.body && modifiedConfig.method !== 'GET') {\n requestInit.body = typeof modifiedConfig.body === 'string'\n ? modifiedConfig.body\n : JSON.stringify(modifiedConfig.body);\n };\n\n const response = await fetch(\n modifiedConfig.url,\n requestInit\n );\n\n const newAccessToken = response.headers.get('X-New-Access-Token');\n const newRefreshToken = response.headers.get('X-New-Refresh-Token');\n\n if (newAccessToken || newRefreshToken) {\n this.properties.onTokensRefreshed?.({\n accessToken: newAccessToken,\n refreshToken: newRefreshToken\n });\n };\n\n let result: any;\n\n try {\n result = await response.json();\n } catch (e) {\n // Fallback en caso de que la respuesta no sea un JSON válido (errores de servidor 500, 502, etc.)\n return {\n success: false,\n message: `Error de servidor (${response.status}: ${response.statusText || 'Formato de respuesta no reconocido'})`,\n data: null,\n responseTime: new Date().toISOString()\n };\n }\n\n // Manejo de errores de validación (RFC 9110)\n if (result && result.errors && typeof result.errors === 'object') {\n const errorMessages: string[] = [];\n\n Object.values(result.errors).forEach((errors: any) => {\n if (Array.isArray(errors)) {\n errorMessages.push(...errors);\n } else if (typeof errors === 'string') {\n errorMessages.push(errors);\n }\n });\n\n if (errorMessages.length > 0) {\n return {\n success: false,\n message: errorMessages.join(', '),\n data: result.data ?? null,\n responseTime: result.responseTime ?? new Date().toISOString()\n } as ResponseModel<T>;\n }\n }\n\n return result as ResponseModel<T>;\n\n } catch (error) {\n return {\n success: false,\n message: error instanceof Error ? error.message : 'Error inesperado durante la petición al API.',\n data: null,\n responseTime: new Date().toISOString()\n };\n };\n };\n\n\n //#region REQUEST METHODS\n\n async executeGET<T>(\n endpoint: string,\n requiresAuth: boolean = false\n ): Promise<ResponseModel<T>> {\n return this.apiExecute<T>({\n endpoint,\n method: 'GET',\n requiresAuth: requiresAuth\n });\n };\n\n async executePOST<T>(\n endpoint: string,\n body?: any,\n requiresAuth: boolean = true,\n ): Promise<ResponseModel<T>> {\n return this.apiExecute<T>({\n endpoint,\n method: 'POST',\n body,\n requiresAuth: requiresAuth\n });\n };\n\n async executePATCH<T>(\n endpoint: string,\n body?: any,\n requiresAuth: boolean = true,\n ): Promise<ResponseModel<T>> {\n return this.apiExecute<T>({\n endpoint,\n method: 'PATCH',\n body,\n requiresAuth: requiresAuth\n });\n };\n\n async executeDELETE<T>(\n endpoint: string,\n body?: any,\n requiresAuth: boolean = true,\n ): Promise<ResponseModel<T>> {\n return this.apiExecute<T>({\n endpoint,\n method: 'DELETE',\n body,\n requiresAuth: requiresAuth\n });\n };\n\n async executePUT<T>(\n endpoint: string,\n body?: any,\n requiresAuth: boolean = true\n ): Promise<ResponseModel<T>> {\n return this.apiExecute<T>({\n endpoint,\n method: 'PUT',\n body,\n requiresAuth: requiresAuth,\n });\n };\n\n async executePublicRequest<T>(\n endpoint: string,\n method: MethodTypes,\n body?: any,\n timestamp?: string\n ): Promise<ResponseModel<T>> {\n return this.apiExecute<T>({\n endpoint,\n method,\n body,\n requiresAuth: false,\n timeStamp: timestamp\n });\n };\n\n //#endregion\n}\n","import * as CryptoJS from \"crypto-js\";\n\nexport class CryptoService {\n /**\n * Genera un hash SHA256 de un texto (útil para fingerprints)\n *\n * @param text - Texto a hashear\n * @returns Hash en formato hexadecimal\n */\n sha256(text: string): string {\n return CryptoJS.SHA256(text).toString(CryptoJS.enc.Hex);\n }\n\n /**\n * Genera un identificador único basado en timestamp y random\n * (útil para request IDs)\n *\n * @returns ID único\n */\n generateUniqueId(): string {\n const timestamp = Date.now().toString(36);\n const randomPart = Math.random().toString(36).substring(2, 15);\n return `${timestamp}-${randomPart}`;\n }\n}\n","import { TokenData } from \"@/types/TokenData\";\n\n/**\n * Manages authentication tokens.\n */\nexport class TokenManager {\n private tokens: TokenData | null = null;\n private onTokensChanged?: (tokens: TokenData | null) => void;\n private sessionCheckInterval: NodeJS.Timeout | null = null;\n private autoRefreshTimeout: NodeJS.Timeout | null = null;\n private onSessionExpiring?: (remainingMinutes: number) => void;\n private onSessionExpired?: () => Promise<void>;\n private onSessionRecovery?: () => Promise<boolean>;\n private hasNotifiedExpiring: boolean = false;\n private autoRefreshThresholdMinutes: number = 5;\n\n constructor(\n onTokensChanged?: (tokens: TokenData | null) => void,\n onSessionExpiring?: (remainingMinutes: number) => void,\n onSessionExpired?: () => Promise<void>,\n onSessionRecovery?: () => Promise<boolean>,\n autoRefreshThresholdMinutes?: number\n ) {\n this.onTokensChanged = onTokensChanged;\n this.onSessionExpiring = onSessionExpiring;\n this.onSessionExpired = onSessionExpired;\n this.onSessionRecovery = onSessionRecovery;\n this.autoRefreshThresholdMinutes = autoRefreshThresholdMinutes ?? 5;\n };\n\n /**\n * Guarda los tokens de autenticación y dispara el callback onTokensChanged.\n */\n setTokens(tokens: TokenData) {\n this.tokens = tokens;\n this.hasNotifiedExpiring = false;\n\n this.onTokensChanged?.(this.tokens);\n\n if (!tokens.rememberMe) {\n this.startExpirationCheck();\n this.stopAutoRefreshTimer();\n } else {\n this.stopExpirationCheck();\n this.scheduleAutoRefresh();\n };\n };\n\n /**\n * Guarda los tokens sin disparar el callback onTokensChanged.\n * Usar para inyectar tokens desde storage externo (cookies/localStorage).\n */\n setTokensSilent(tokens: TokenData) {\n this.tokens = tokens;\n this.hasNotifiedExpiring = false;\n\n if (!tokens.rememberMe) {\n this.startExpirationCheck();\n this.stopAutoRefreshTimer();\n } else {\n this.stopExpirationCheck();\n this.scheduleAutoRefresh();\n };\n };\n\n /**\n * Obtiene los tokens de autenticación almacenados.\n */\n getTokens(): TokenData | null {\n return this.tokens;\n };\n\n /**\n * Limpia los tokens de autenticación almacenados y dispara el callback onTokensChanged.\n */\n clearTokens() {\n this.stopExpirationCheck();\n this.stopAutoRefreshTimer();\n this.tokens = null;\n this.onTokensChanged?.(this.tokens);\n };\n\n /**\n * Valida si existen tokens y si el access token no ha expirado.\n */\n hasValidTokens(): boolean {\n if (!this.tokens) return false;\n\n return Date.now() < this.tokens.expiresAt;\n };\n\n /**\n * Valida si el access token expirará dentro del umbral especificado (en minutos).\n */\n isTokenExpiringSoon(thresholdMinutes: number): boolean {\n if (!this.tokens) return false;\n\n const thresholdMs = thresholdMinutes * 60 * 1000;\n const timeLeft = this.tokens.expiresAt - Date.now();\n\n return timeLeft > 0 && timeLeft <= thresholdMs;\n };\n\n /**\n * Obtiene el tiempo restante hasta la expiración del access token en milisegundos.\n */\n getTimeUntilExpiry(): number | null {\n if (!this.tokens) return null;\n\n return Math.max(0, this.tokens.expiresAt - Date.now());\n };\n\n /**\n * Obtiene el access token almacenado.\n */\n getAccessToken(): string | null {\n return this.tokens ? this.tokens.accessToken : null;\n };\n\n /**\n * Obtiene el refresh token almacenado.\n */\n getRefreshToken(): string | null {\n return this.tokens ? this.tokens.refreshToken : null;\n };\n\n /**\n * Verifica si el auto-refresh debe ejecutarse\n * Solo si el usuario activó \"rememberMe\" durante el login\n */\n shouldAutoRefresh(): boolean {\n if (!this.tokens) return false;\n\n return this.tokens.rememberMe === true;\n }\n\n /**\n * Inicia el monitoreo de expiración para sesiones sin rememberMe\n * - Notifica cuando quedan 5 minutos (onSessionExpiring)\n */\n private startExpirationCheck(): void {\n this.stopExpirationCheck();\n\n this.sessionCheckInterval = setInterval(async () => {\n if (!this.tokens) {\n this.stopExpirationCheck();\n return;\n };\n\n const timeLeft = this.getTimeUntilExpiry();\n if (timeLeft === null) return;\n\n const minutesLeft = Math.floor(timeLeft / (60 * 1000));\n\n if (minutesLeft <= 5 && minutesLeft > 1 && !this.hasNotifiedExpiring) {\n this.hasNotifiedExpiring = true;\n this.onSessionExpiring?.(minutesLeft);\n };\n\n if (minutesLeft <= 1) {\n this.stopExpirationCheck();\n\n if (this.onSessionRecovery) {\n try {\n const recovered = await this.onSessionRecovery();\n if (recovered) return;\n } catch (error) {\n }\n }\n\n if (this.onSessionExpired) {\n await this.onSessionExpired();\n };\n };\n }, 60000);\n }\n\n /**\n * Programa un auto-refresh proactivo para sesiones con rememberMe.\n * Se ejecuta X minutos antes de que expire el token\n */\n private scheduleAutoRefresh(): void {\n this.stopAutoRefreshTimer();\n\n if (!this.tokens || !this.tokens.rememberMe) return;\n\n const timeLeft = this.getTimeUntilExpiry();\n if (timeLeft === null || timeLeft <= 0) return;\n\n const thresholdMs = this.autoRefreshThresholdMinutes * 60 * 1000;\n const delay = Math.max(0, timeLeft - thresholdMs);\n\n this.autoRefreshTimeout = setTimeout(async () => {\n if (!this.tokens || !this.tokens.rememberMe) return;\n\n if (this.onSessionRecovery) {\n try {\n const recovered = await this.onSessionRecovery();\n if (recovered) return;\n } catch (error) {\n }\n }\n\n if (this.onSessionExpired) {\n await this.onSessionExpired();\n }\n }, delay);\n }\n\n /**\n * Detiene el monitoreo de expiración\n */\n private stopExpirationCheck(): void {\n if (this.sessionCheckInterval) {\n clearInterval(this.sessionCheckInterval);\n this.sessionCheckInterval = null;\n };\n }\n\n /**\n * Detiene el timer de auto-refresh proactivo\n */\n private stopAutoRefreshTimer(): void {\n if (this.autoRefreshTimeout) {\n clearTimeout(this.autoRefreshTimeout);\n this.autoRefreshTimeout = null;\n };\n }\n};\n","import { AuthInterceptorConfig } from \"./types/AuthInterceptorConfig\";\nimport { InterceptorContext } from \"@/core/interceptors/types/InterceptorContext\";\nimport { RequestConfig } from \"@/types/RequestConfig\";\nimport { RequestInterceptor } from \"./types/RequestInterceptor\";\n\nexport class AuthInterceptor implements RequestInterceptor {\n readonly name = \"AuthInterceptor\";\n\n private config: Required<AuthInterceptorConfig>;\n private refreshPromise: Promise<void> | null = null;\n private isRefreshing = false;\n\n constructor(config: AuthInterceptorConfig) {\n this.config = {\n enabled: config.enabled ?? true,\n thresholdMinutes: config.thresholdMinutes ?? 5,\n isTokenExpiringSoon: config.isTokenExpiringSoon,\n hasValidTokens: config.hasValidTokens,\n shouldAutoRefresh: config.shouldAutoRefresh,\n refreshSession: config.refreshSession\n };\n };\n\n async onRequest(\n config: RequestConfig,\n context: InterceptorContext\n ): Promise<RequestConfig> {\n\n //Actua en solicitudes que requieren autenticación\n if (!config.requiresAuth || !this.config.enabled) {\n return config;\n };\n\n //Actúa SOLO si los tokens son válidos\n if (!this.config.hasValidTokens()) {\n return config;\n };\n\n if (!this.config.shouldAutoRefresh()) {\n return config;\n };\n\n if (this.config.isTokenExpiringSoon()) {\n try {\n //Evita múltiples llamadas de actualización simultáneas\n if (this.isRefreshing && this.refreshPromise) {\n await this.refreshPromise;\n } else {\n this.isRefreshing = true;\n this.refreshPromise = this.config.refreshSession();\n await this.refreshPromise;\n this.isRefreshing = false;\n this.refreshPromise = null;\n };\n } catch (error) {\n this.isRefreshing = false;\n this.refreshPromise = null;\n };\n };\n\n return config;\n };\n\n updateConfig(config: Partial<AuthInterceptorConfig>): void {\n this.config = {\n ...this.config,\n ...config\n } as Required<AuthInterceptorConfig>;\n };\n\n reset(): void {\n this.isRefreshing = false;\n this.refreshPromise = null;\n };\n};\n","export class ErrorResponse extends Error {\n constructor(\n message: string,\n public statusCode?: number,\n public responseData?: any\n ){\n super(message);\n this.name = \"FalconHUB API Error\";\n };\n};\n","import { API } from \"@/core/API\";\nimport { CryptoService } from \"@/core/CryptoService\";\nimport { TokenManager } from \"@/core/TokenManager\";\nimport { LoginRequest } from \"@/interfaces/Auth/Login/LoginRequest\";\nimport { LoginResponse } from \"@/interfaces/Auth/Login/LoginResponse\";\nimport { RefreshTokenRequest } from \"@/interfaces/Auth/RefreshTokens/RefreshTokenRequest\";\nimport { RefreshTokenResponse } from \"@/interfaces/Auth/RefreshTokens/RefreshTokenResponse\";\nimport { ValidateSessionRenewedResponse, ValidateSessionResponse } from \"@/interfaces/Auth/ValidateSession/ValidateSessionResponse\";\nimport { ConfirmEmailRequest } from \"@/interfaces/Auth/ConfirmEmail/ConfirmEmailRequest\";\nimport { SendOtpRequest } from \"@/interfaces/Auth/SendOtp/SendOtpRequest\";\nimport { ValidateOtpRequest } from \"@/interfaces/Auth/ValidateOtp/ValidateOtpRequest\";\nimport { ChangePasswordRequest } from \"@/interfaces/Auth/ChangePassword/ChangePasswordRequest\";\nimport { ErrorResponse } from \"@/types/ErrorResponse\";\nimport { ResponseModel } from \"@/types/ResponseModel\";\nimport { ServiceProperties } from \"@/types/ServiceProperties\";\nimport { TokenData } from \"@/types/TokenData\";\n\nexport class AuthService {\n private api: API;\n private crytpoService: CryptoService;\n private tokenManager: TokenManager;\n private serviceProperties: ServiceProperties;\n\n constructor(\n serviceProperties: ServiceProperties,\n tokenManager: TokenManager,\n cryptoService: CryptoService,\n api: API\n ) {\n this.api = api;\n this.crytpoService = cryptoService;\n this.tokenManager = tokenManager;\n this.serviceProperties = serviceProperties;\n };\n\n /**\n * Login con las credenciales proporcionadas\n * @param credentials - Objeto con email, password y rememberMe\n * @returns Retorna el cuerpo de respuesta del login.\n */\n async login(credentials: LoginRequest): Promise<ResponseModel<LoginResponse>> {\n const timestamp = Date.now().toString();\n\n const loginData: LoginRequest = {\n email: credentials.email,\n password: credentials.password,\n rememberMe: credentials.rememberMe\n };\n\n const response = await this.api.executePublicRequest<LoginResponse>(\n 'oauth/login',\n 'POST',\n loginData,\n timestamp\n );\n\n if (!response) {\n throw new ErrorResponse('No response from server');\n };\n\n if (response.success && response.data) {\n const data: LoginResponse = response.data;\n\n const expiresIn = parseInt(data.expiresIn.replace('s', ''));\n const expiresAt = Date.now() + expiresIn * 1000;\n\n const tokens: TokenData = {\n accessToken: data.accessToken,\n refreshToken: data.refreshToken,\n expiresAt,\n rememberMe: credentials.rememberMe\n };\n\n await this.tokenManager.setTokens(tokens);\n\n this.serviceProperties.onTokensUpdated?.(tokens);\n }\n\n return response;\n };\n\n /**\n * Valida la sesión actual y retorna información de expiración\n *\n * El servidor puede responder de 2 formas:\n * 1. Sesión renovada (sliding window): retorna nuevos tokens\n * 2. Sesión válida: retorna info de expiración sin renovar\n */\n async validateSession(): Promise<ResponseModel<ValidateSessionRenewedResponse | ValidateSessionResponse>> {\n const response = await this.api.executePOST<ValidateSessionRenewedResponse | ValidateSessionResponse>(\n 'oauth/validateSession'\n );\n\n if (!response) {\n throw new ErrorResponse('No response from server');\n };\n\n if (response.success && response.data) {\n const respData = response.data;\n\n if ('expiresIn' in respData && respData.expiresIn) {\n const sessionData = respData as ValidateSessionRenewedResponse;\n const expiresIn = parseInt(sessionData.expiresIn.replace('s', ''));\n const expiresAt = Date.now() + expiresIn * 1000;\n\n const currentTokens = this.tokenManager.getTokens();\n const rememberMe = currentTokens?.rememberMe ?? sessionData.isRemembered;\n\n const tokens: TokenData = {\n accessToken: sessionData.accessToken,\n refreshToken: sessionData.refreshToken,\n expiresAt,\n rememberMe\n };\n\n this.tokenManager.setTokens(tokens);\n this.serviceProperties.onTokensUpdated?.(tokens);\n }\n else if ('expiresAt' in respData && respData.expiresAt) {\n const sessionData = respData as ValidateSessionResponse;\n\n if (sessionData.remainingMinutes <= 5 && sessionData.remainingMinutes > 1) {\n this.serviceProperties.onSessionExpiring?.(sessionData.remainingMinutes);\n } else if (sessionData.remainingMinutes <= 1) {\n if (this.serviceProperties.onSessionExpired) {\n await this.serviceProperties.onSessionExpired();\n }\n }\n }\n };\n\n return response;\n };\n\n /**\n * Refresca los tokens usando el refresh token\n */\n async refreshTokens(refreshRequest: RefreshTokenRequest): Promise<ResponseModel<RefreshTokenResponse>> {\n const currentTokens = this.tokenManager.getTokens();\n const refreshToken = this.tokenManager.getRefreshToken() ?? refreshRequest.refreshToken;\n\n if (!refreshToken) {\n throw new ErrorResponse('No refresh token available');\n };\n\n const refreshRequestData: RefreshTokenRequest = {\n refreshToken: refreshToken,\n rememberMe: refreshRequest.rememberMe ?? currentTokens?.rememberMe\n }\n\n const response = await this.api.executePublicRequest<RefreshTokenResponse>(\n 'oauth/refresh',\n 'POST',\n refreshRequestData\n );\n\n if (!response) {\n throw new ErrorResponse('No response from server');\n };\n\n if (response.success && response.data) {\n const sessionData: RefreshTokenResponse = response.data;\n\n\n const shouldRemember = refreshRequest.rememberMe ?? currentTokens?.rememberMe ?? false;\n const expiresIn = parseInt(sessionData.expiresIn.replace('s', ''));\n const expiresAt = Date.now() + expiresIn * 1000;\n\n const tokens: TokenData = {\n accessToken: sessionData.accessToken,\n refreshToken: sessionData.refreshToken,\n expiresAt,\n rememberMe: shouldRemember\n };\n\n this.tokenManager.setTokens(tokens);\n this.serviceProperties.onTokensUpdated?.(tokens);\n };\n\n return response;\n };\n\n /**\n * Cierra sesión: notifica al servidor y limpia tokens\n */\n async logout(): Promise<ResponseModel> {\n const res = await this.api.executePOST('oauth/logout');\n\n if (res.success) {\n this.tokenManager.clearTokens();\n this.serviceProperties.onTokensUpdated?.(null);\n }\n\n return res;\n }\n\n // #region Email & OTP & Password (public - no auth)\n\n /**\n * Confirma el correo electrónico de un usuario.\n * @param request - Email y expiresAt\n */\n async confirmEmail(request: ConfirmEmailRequest): Promise<ResponseModel> {\n return this.api.executePublicRequest('oauth/email/confirm', 'PUT', request);\n }\n\n /**\n * Envía un código OTP al correo electrónico.\n * @param request - Email del usuario\n */\n async sendOtp(request: SendOtpRequest): Promise<ResponseModel> {\n return this.api.executePublicRequest('oauth/otp', 'POST', request);\n }\n\n /**\n * Valida un código OTP.\n * @param request - Email y código OTP\n */\n async validateOtp(request: ValidateOtpRequest): Promise<ResponseModel> {\n return this.api.executePublicRequest('oauth/otp/verify', 'POST', request);\n }\n\n /**\n * Cambia la contraseña del usuario (flujo público, sin sesión).\n * @param request - Email, contraseña actual y nueva contraseña\n */\n async changePassword(request: ChangePasswordRequest): Promise<ResponseModel> {\n return this.api.executePublicRequest('oauth/password', 'PUT', request);\n }\n\n // #endregion\n\n /**\n * Verifica si el usuario está autenticado\n */\n isAuthenticated(): boolean {\n return this.tokenManager.hasValidTokens();\n };\n\n /**\n * Obtiene los tokens actuales\n */\n getTokens(): TokenData | null {\n return this.tokenManager.getTokens();\n };\n\n}\n","/**\n * Utilidad para construir query params a partir de objetos de filtro.\n *\n * @example\n * ```typescript\n * const filter: EndpointsFilter = { HttpMethod: 'GET', IsActive: true };\n * const queryString = FilterBuilder.toQueryString(filter);\n * // Result: \"HttpMethod=GET&IsActive=true\"\n * ```\n */\nexport class FilterBuilder {\n /**\n * Convierte un objeto de filtro a query string.\n * Ignora valores null, undefined y strings vacíos.\n *\n * @param filter - Objeto con los filtros a aplicar\n * @returns Query string sin el \"?\" inicial\n */\n static toQueryString<T extends Record<string, any>>(filter: T): string {\n const params = new URLSearchParams();\n\n for (const [key, value] of Object.entries(filter)) {\n if (value !== null && value !== undefined && value !== '') {\n params.append(key, String(value));\n }\n }\n\n return params.toString();\n }\n\n /**\n * Construye la URL completa con filtros aplicados.\n *\n * @param baseEndpoint - Endpoint base sin query params\n * @param filter - Objeto con los filtros a aplicar\n * @returns Endpoint con query params si hay filtros, o el endpoint base si no hay\n */\n static buildEndpoint<T extends Record<string, any>>(baseEndpoint: string, filter?: T): string {\n if (!filter) return baseEndpoint;\n\n const queryString = this.toQueryString(filter);\n\n if (!queryString) return baseEndpoint;\n\n return `${baseEndpoint}?${queryString}`;\n }\n\n /**\n * Verifica si un objeto de filtro tiene al menos un valor válido.\n *\n * @param filter - Objeto con los filtros a verificar\n * @returns true si hay al menos un filtro con valor válido\n */\n static hasFilters<T extends Record<string, any>>(filter?: T): boolean {\n if (!filter) return false;\n\n return Object.values(filter).some(\n value => value !== null && value !== undefined && value !== ''\n );\n }\n\n /**\n * Limpia un objeto de filtro removiendo valores vacíos.\n * Útil para normalizar filtros antes de enviarlos.\n *\n * @param filter - Objeto con los filtros\n * @returns Nuevo objeto solo con valores válidos\n */\n static clean<T extends Record<string, any>>(filter: T): Partial<T> {\n const cleaned: Partial<T> = {};\n\n for (const [key, value] of Object.entries(filter)) {\n if (value !== null && value !== undefined && value !== '') {\n (cleaned as any)[key] = value;\n }\n }\n\n return cleaned;\n }\n}\n\n/**\n * Tipo base para modelos de filtro.\n * Todos los campos son opcionales y pueden ser string, number, boolean o null.\n */\nexport type FilterModel = Record<string, string | number | boolean | null | undefined>;\n\n/**\n * Tipo para definir metadatos de un campo de filtro.\n */\nexport interface FilterFieldMetadata {\n /** Tipo de filtro */\n type: 'search' | 'string' | 'boolean' | 'number' | 'select' | 'multiselect' | 'date' | 'daterange';\n /** Descripción / label del filtro */\n description: string;\n /** Orden de renderizado (menor = primero, default 99) */\n order?: number;\n /** Opciones para select / multiselect */\n options?: string[];\n /** Labels personalizados para boolean (default: Activo/Inactivo) */\n labels?: { true: string; false: string };\n /** Campos en los que busca el backend (solo para type: 'search') */\n searchIn?: string[];\n /** Valor mínimo (para number) */\n min?: number;\n /** Valor máximo (para number) */\n max?: number;\n /** Fecha mínima (para date / daterange) */\n minDate?: string;\n /** Fecha máxima (para date / daterange) */\n maxDate?: string;\n}\n\n/**\n * Tipo para el modelo de filtros retornado por el endpoint /filters.\n */\nexport type FilterMetadataModel = Record<string, FilterFieldMetadata>;\n\n// ── Filter Groups (array-based format) ──\n\n/**\n * Opción dentro de un grupo de filtros.\n */\nexport interface FilterGroupOption {\n /** Campo del backend (e.g. \"Module\", \"IsActive\") */\n key: string;\n /** Label visible en el frontend */\n label: string;\n /** Placeholder del input (solo para string) */\n placeholder?: string;\n /** Opciones disponibles (solo para select) */\n values?: string[];\n /** Label cuando el valor es true (solo para boolean) */\n trueLabel?: string;\n /** Label cuando el valor es false (solo para boolean) */\n falseLabel?: string;\n}\n\n/**\n * Grupo de filtros agrupados por tipo.\n * El frontend renderiza cada grupo de forma diferente.\n */\nexport interface FilterGroup {\n /** Tipo de filtro: \"string\" | \"boolean\" | \"select\" | \"date\" */\n type: 'string' | 'boolean' | 'select' | 'date';\n /** Label del grupo */\n label: string;\n /** Opciones del grupo */\n options: FilterGroupOption[];\n}\n\n/**\n * Modelo retornado por el endpoint /filters (formato array-based).\n */\nexport type FilterGroupsModel = FilterGroup[];\n","import { API } from \"@/core/API\";\nimport { UserProfileResponse } from \"@/interfaces/User/UserProfileResponse\";\nimport { UserBasicResponse } from \"@/interfaces/User/UserBasicResponse\";\nimport {\n AdminUser,\n AdminAuthentication,\n UserAdminRequest,\n UserAuthAdminRequest,\n ChangePasswordAdminRequest,\n UserAdminFilter,\n UserAdminUpdateRequest,\n UserAuthUpdateRequest\n} from \"@/interfaces/User/Admin\";\nimport {\n UserType,\n UserTypeRequest,\n UserTypesFilter\n} from \"@/interfaces/User/UserTypes/UserTypesInterface\";\nimport {\n Role,\n RoleRequest,\n RolesFilter\n} from \"@/interfaces/User/Roles/RolesInterface\";\nimport { ResponseModel } from \"@/types/ResponseModel\";\nimport { FilterBuilder, type FilterGroupsModel } from \"@/utils/FilterBuilder\";\nimport { ChangePasswordUserRequest } from \"@/interfaces/User/ChangePassword/ChangePasswordUserRequest\";\nimport { UserDataUpdateRequest } from \"@/interfaces/User/UserDataUpdateRequest\";\n\nexport class UserService {\n private api: API;\n private readonly BASE_PATH = 'users';\n\n constructor(\n api: API,\n ){\n this.api = api;\n };\n\n async me(): Promise<ResponseModel<UserBasicResponse>> {\n const response: ResponseModel<UserBasicResponse> = await this.api.executeGET(\n `${this.BASE_PATH}/me`,\n true,\n );\n\n return response;\n };\n\n async profile(): Promise<ResponseModel<UserProfileResponse>>{\n const response: ResponseModel<UserProfileResponse> = await this.api.executeGET(\n `${this.BASE_PATH}/profile`,\n true\n );\n\n return response;\n }\n\n async changePasswordUser(request: ChangePasswordUserRequest): Promise<ResponseModel>{\n return this.api.executePUT(`${this.BASE_PATH}/me/password`, request);\n }\n\n async updateUserData(request: UserDataUpdateRequest): Promise<ResponseModel>{\n return this.api.executePUT(`${this.BASE_PATH}/me`, request);\n }\n\n // #region Admin CRUD\n\n /**\n * Crea un nuevo usuario administrador.\n * @param request - Datos del nuevo administrador\n */\n async newAdminUser(request: UserAdminRequest): Promise<ResponseModel<AdminUser>> {\n return this.api.executePOST<AdminUser>(`${this.BASE_PATH}/admin`, request);\n }\n\n /**\n * Crea la autenticación para un usuario.\n * @param request - Datos de autenticación del usuario\n */\n async createUserAuthentication(request: UserAuthAdminRequest): Promise<ResponseModel<AdminAuthentication>> {\n return this.api.executePOST<AdminAuthentication>(`${this.BASE_PATH}/admin/authentication`, request);\n }\n\n /**\n * Cambia la contraseña de un administrador.\n * @param id - ID del usuario\n * @param request - Nueva contraseña\n */\n async changePasswordAdmin(id: number, request: ChangePasswordAdminRequest): Promise<ResponseModel> {\n return this.api.executePOST(`${this.BASE_PATH}/admin/${id}/password`, request);\n }\n\n /**\n * Obtiene todos los administradores con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getAllAdmins(filter?: UserAdminFilter): Promise<ResponseModel<AdminUser[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/admin`, filter);\n return this.api.executeGET<AdminUser[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para administradores.\n */\n async getAdminFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/admin/filters`, true);\n }\n\n /**\n * Obtiene un administrador por su ID.\n * @param id - ID del administrador\n */\n async getAdminById(id: number): Promise<ResponseModel<AdminUser>> {\n return this.api.executeGET<AdminUser>(`${this.BASE_PATH}/admin/${id}`, true);\n }\n\n /**\n * Obtiene la autenticación de un administrador.\n * @param id - ID del usuario\n */\n async getAdminAuthentication(id: number): Promise<ResponseModel<AdminAuthentication>> {\n return this.api.executeGET<AdminAuthentication>(`${this.BASE_PATH}/admin/authentication/${id}`, true);\n }\n\n /**\n * Actualiza un administrador existente.\n * @param id - ID del administrador\n * @param request - Nuevos datos del administrador\n */\n async updateAdmin(id: number, request: UserAdminUpdateRequest): Promise<ResponseModel<AdminUser>> {\n return this.api.executePUT<AdminUser>(`${this.BASE_PATH}/admin/${id}`, request);\n }\n\n /**\n * Activa o desactiva un administrador.\n * @param id - ID del administrador\n */\n async toggleAdminStatus(id: number): Promise<ResponseModel<AdminUser>> {\n return this.api.executePUT<AdminUser>(`${this.BASE_PATH}/admin/${id}/toggle-status`);\n }\n\n /**\n * Actualiza la autenticación de un administrador.\n * @param id - ID del usuario\n * @param request - Nuevos datos de autenticación\n */\n async updateAdminAuthentication(id: number, request: UserAuthUpdateRequest): Promise<ResponseModel<AdminAuthentication>> {\n return this.api.executePUT<AdminAuthentication>(`${this.BASE_PATH}/admin/authentication/${id}`, request);\n }\n\n // #endregion\n\n // #region User Types\n\n /**\n * Obtiene todos los tipos de usuario con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getUserTypes(filter?: UserTypesFilter): Promise<ResponseModel<UserType[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/catalogs/user-types`, filter);\n return this.api.executeGET<UserType[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para tipos de usuario.\n */\n async getUserTypesFilters(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/catalogs/user-types/filters`, true);\n }\n\n /**\n * Obtiene un tipo de usuario por su ID.\n * @param id - ID del tipo de usuario\n */\n async getUserTypeById(id: number): Promise<ResponseModel<UserType>> {\n return this.api.executeGET<UserType>(`${this.BASE_PATH}/catalogs/user-types/${id}`, true);\n }\n\n /**\n * Crea un nuevo tipo de usuario.\n * @param request - Datos del tipo de usuario a crear\n */\n async createUserType(request: UserTypeRequest): Promise<ResponseModel<UserType>> {\n return this.api.executePOST<UserType>(`${this.BASE_PATH}/catalogs/user-types`, request);\n }\n\n /**\n * Actualiza un tipo de usuario existente.\n * @param id - ID del tipo de usuario a actualizar\n * @param request - Nuevos datos del tipo de usuario\n */\n async updateUserType(id: number, request: UserTypeRequest): Promise<ResponseModel<UserType>> {\n return this.api.executePUT<UserType>(`${this.BASE_PATH}/catalogs/user-types/${id}`, request);\n }\n\n /**\n * Elimina un tipo de usuario.\n * @param id - ID del tipo de usuario a eliminar\n */\n async deleteUserType(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/catalogs/user-types/${id}`);\n }\n\n // #endregion\n\n // #region Roles\n\n /**\n * Obtiene todos los roles con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getRoles(filter?: RolesFilter): Promise<ResponseModel<Role[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/catalogs/roles`, filter);\n return this.api.executeGET<Role[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para roles.\n */\n async getRolesFilters(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/catalogs/roles/filters`, true);\n }\n\n /**\n * Obtiene un rol por su ID.\n * @param id - ID del rol\n */\n async getRoleById(id: number): Promise<ResponseModel<Role>> {\n return this.api.executeGET<Role>(`${this.BASE_PATH}/catalogs/roles/${id}`, true);\n }\n\n /**\n * Obtiene los roles asociados a un tipo de usuario.\n * @param userTypeId - ID del tipo de usuario\n */\n async getRolesByUserType(userTypeId: number): Promise<ResponseModel<Role[]>> {\n return this.api.executeGET<Role[]>(`${this.BASE_PATH}/catalogs/roles/user-type/${userTypeId}`, true);\n }\n\n /**\n * Crea un nuevo rol.\n * @param request - Datos del rol a crear\n */\n async createRole(request: RoleRequest): Promise<ResponseModel<Role>> {\n return this.api.executePOST<Role>(`${this.BASE_PATH}/catalogs/roles`, request);\n }\n\n /**\n * Actualiza un rol existente.\n * @param id - ID del rol a actualizar\n * @param request - Nuevos datos del rol\n */\n async updateRole(id: number, request: RoleRequest): Promise<ResponseModel<Role>> {\n return this.api.executePUT<Role>(`${this.BASE_PATH}/catalogs/roles/${id}`, request);\n }\n\n /**\n * Activa o desactiva un rol.\n * @param id - ID del rol\n */\n async toggleRoleStatus(id: number): Promise<ResponseModel<Role>> {\n return this.api.executePUT<Role>(`${this.BASE_PATH}/catalogs/roles/${id}/toggle-status`);\n }\n\n /**\n * Elimina un rol.\n * @param id - ID del rol a eliminar\n */\n async deleteRole(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/catalogs/roles/${id}`);\n }\n\n // #endregion\n}\n","import { API } from \"@/core/API\";\nimport { ResponseModel } from \"@/types/ResponseModel\";\nimport { FilterBuilder, type FilterGroupsModel } from \"@/utils/FilterBuilder\";\nimport {\n Module,\n ModuleRequest,\n ModulesFilter,\n Endpoint,\n EndpointRequest,\n EndpointsFilter,\n UIRoute,\n UIRouteRequest,\n UIRoutesFilter\n} from \"@/interfaces/System\";\n\n/**\n * Servicio para gestionar las configuraciones del sistema.\n */\nexport class SystemService {\n private api: API;\n private readonly BASE_PATH = 'system';\n\n constructor(api: API) {\n this.api = api;\n }\n\n // #region MODULES\n\n /**\n * Obtiene todos los módulos con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getModules(filter?: ModulesFilter): Promise<ResponseModel<Module[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/modules`, filter);\n return this.api.executeGET<Module[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para módulos.\n */\n async getModulesFilters(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/modules/filters`, true);\n }\n\n /**\n * Obtiene un módulo por su ID.\n * @param id - ID del módulo\n */\n async getModuleById(id: number): Promise<ResponseModel<Module>> {\n return this.api.executeGET<Module>(`${this.BASE_PATH}/modules/${id}`, true);\n }\n\n /**\n * Crea un nuevo módulo.\n * @param request - Datos del módulo a crear\n */\n async createModule(request: ModuleRequest): Promise<ResponseModel<Module>> {\n return this.api.executePOST<Module>(`${this.BASE_PATH}/modules`, request);\n }\n\n /**\n * Actualiza un módulo existente.\n * @param id - ID del módulo a actualizar\n * @param request - Nuevos datos del módulo\n */\n async updateModule(id: number, request: ModuleRequest): Promise<ResponseModel<Module>> {\n return this.api.executePUT<Module>(`${this.BASE_PATH}/modules/${id}`, request);\n }\n\n /**\n * Activa o desactiva un módulo.\n * @param id - ID del módulo\n */\n async toggleModuleStatus(id: number): Promise<ResponseModel<Module>> {\n return this.api.executePUT<Module>(`${this.BASE_PATH}/modules/${id}/toggle-status`);\n }\n\n /**\n * Elimina un módulo.\n * @param id - ID del módulo a eliminar\n */\n async deleteModule(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/modules/${id}`);\n }\n\n // #endregion\n\n // #region ENDPOINTS\n\n /**\n * Obtiene todos los endpoints con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getEndpoints(filter?: EndpointsFilter): Promise<ResponseModel<Endpoint[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/endpoints`, filter);\n return this.api.executeGET<Endpoint[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para endpoints.\n */\n async getEndpointsFilters(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/endpoints/filters`, true);\n }\n\n /**\n * Obtiene los módulos disponibles (valores únicos del primer segmento del path).\n */\n async getEndpointModules(): Promise<ResponseModel<string[]>> {\n return this.api.executeGET<string[]>(`${this.BASE_PATH}/endpoints/modules`, true);\n }\n\n /**\n * Obtiene un endpoint por su ID.\n * @param id - ID del endpoint\n */\n async getEndpointById(id: number): Promise<ResponseModel<Endpoint>> {\n return this.api.executeGET<Endpoint>(`${this.BASE_PATH}/endpoints/${id}`, true);\n }\n\n /**\n * Crea un nuevo endpoint.\n * @param request - Datos del endpoint a crear\n */\n async createEndpoint(request: EndpointRequest): Promise<ResponseModel<Endpoint>> {\n return this.api.executePOST<Endpoint>(`${this.BASE_PATH}/endpoints`, request);\n }\n\n /**\n * Actualiza un endpoint existente.\n * @param id - ID del endpoint a actualizar\n * @param request - Nuevos datos del endpoint\n */\n async updateEndpoint(id: number, request: EndpointRequest): Promise<ResponseModel<Endpoint>> {\n return this.api.executePUT<Endpoint>(`${this.BASE_PATH}/endpoints/${id}`, request);\n }\n\n /**\n * Activa o desactiva un endpoint.\n * @param id - ID del endpoint\n */\n async toggleEndpointStatus(id: number): Promise<ResponseModel<Endpoint>> {\n return this.api.executePUT<Endpoint>(`${this.BASE_PATH}/endpoints/${id}/toggle-status`);\n }\n\n /**\n * Elimina un endpoint.\n * @param id - ID del endpoint a eliminar\n */\n async deleteEndpoint(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/endpoints/${id}`);\n }\n\n // #endregion\n\n // #region UI ROUTES\n\n /**\n * Obtiene todas las rutas de UI con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getUIRoutes(filter?: UIRoutesFilter): Promise<ResponseModel<UIRoute[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/ui-routes`, filter);\n return this.api.executeGET<UIRoute[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para rutas de UI.\n */\n async getUIRoutesFilters(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/ui-routes/filters`, true);\n }\n\n /**\n * Obtiene una ruta de UI por su ID.\n * @param id - ID de la ruta\n */\n async getUIRouteById(id: number): Promise<ResponseModel<UIRoute>> {\n return this.api.executeGET<UIRoute>(`${this.BASE_PATH}/ui-routes/${id}`, true);\n }\n\n /**\n * Crea una nueva ruta de UI.\n * @param request - Datos de la ruta a crear\n */\n async createUIRoute(request: UIRouteRequest): Promise<ResponseModel<UIRoute>> {\n return this.api.executePOST<UIRoute>(`${this.BASE_PATH}/ui-routes`, request);\n }\n\n /**\n * Actualiza una ruta de UI existente.\n * @param id - ID de la ruta a actualizar\n * @param request - Nuevos datos de la ruta\n */\n async updateUIRoute(id: number, request: UIRouteRequest): Promise<ResponseModel<UIRoute>> {\n return this.api.executePUT<UIRoute>(`${this.BASE_PATH}/ui-routes/${id}`, request);\n }\n\n /**\n * Activa o desactiva una ruta de UI.\n * @param id - ID de la ruta\n */\n async toggleUIRouteStatus(id: number): Promise<ResponseModel<UIRoute>> {\n return this.api.executePUT<UIRoute>(`${this.BASE_PATH}/ui-routes/${id}/toggle-status`);\n }\n\n /**\n * Elimina una ruta de UI.\n * @param id - ID de la ruta a eliminar\n */\n async deleteUIRoute(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/ui-routes/${id}`);\n }\n\n // #endregion\n}\n","import { API } from \"@/core/API\";\nimport { ResponseModel } from \"@/types/ResponseModel\";\nimport { FilterBuilder, type FilterGroupsModel } from \"@/utils/FilterBuilder\";\nimport {\n Location,\n LocationsRequest,\n LocationsFilter,\n InventoryStatus,\n InventoryStatusRequest,\n InventoryStatusesFilter,\n Packing,\n PackingRequest,\n PackingsFilter,\n Material,\n MaterialRequest,\n MaterialsFilter,\n InventoryProvider,\n InventoryProviderRequest,\n InventoryProvidersFilter\n} from \"@/interfaces/Inventory\";\n\n/**\n * Servicio para gestionar inventario: ubicaciones, estatus, empaques y materiales.\n */\nexport class InventoryService {\n private api: API;\n private readonly BASE_PATH = 'inventory';\n\n constructor(api: API) {\n this.api = api;\n }\n\n // #region LOCATIONS\n\n /**\n * Obtiene todas las ubicaciones con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getLocations(filter?: LocationsFilter): Promise<ResponseModel<Location[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/locations`, filter);\n return this.api.executeGET<Location[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para ubicaciones.\n */\n async getLocationFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/locations/filters`, true);\n }\n\n /**\n * Obtiene una ubicación por su ID.\n * @param id - ID de la ubicación\n */\n async getLocationById(id: number): Promise<ResponseModel<Location>> {\n return this.api.executeGET<Location>(`${this.BASE_PATH}/locations/${id}`, true);\n }\n\n /**\n * Crea una nueva ubicación.\n * @param request - Datos de la ubicación a crear\n */\n async createLocation(request: LocationsRequest): Promise<ResponseModel<Location>> {\n return this.api.executePOST<Location>(`${this.BASE_PATH}/locations`, request);\n }\n\n /**\n * Actualiza una ubicación existente.\n * @param id - ID de la ubicación a actualizar\n * @param request - Nuevos datos de la ubicación\n */\n async updateLocation(id: number, request: LocationsRequest): Promise<ResponseModel<Location>> {\n return this.api.executePUT<Location>(`${this.BASE_PATH}/locations/${id}`, request);\n }\n\n /**\n * Activa o desactiva una ubicación.\n * @param id - ID de la ubicación\n */\n async toggleLocationStatus(id: number): Promise<ResponseModel<Location>> {\n return this.api.executePUT<Location>(`${this.BASE_PATH}/locations/${id}/toggle-status`);\n }\n\n /**\n * Elimina una ubicación.\n * @param id - ID de la ubicación a eliminar\n */\n async deleteLocation(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/locations/${id}`);\n }\n\n // #endregion\n\n // #region STATUSES\n\n /**\n * Obtiene todos los estatus de inventario con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getStatuses(filter?: InventoryStatusesFilter): Promise<ResponseModel<InventoryStatus[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/catalogs/inventory-statuses`, filter);\n return this.api.executeGET<InventoryStatus[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para estatus de inventario.\n */\n async getStatusFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/catalogs/inventory-statuses/filters`, true);\n }\n\n /**\n * Obtiene un estatus de inventario por su ID.\n * @param id - ID del estatus\n */\n async getStatusById(id: number): Promise<ResponseModel<InventoryStatus>> {\n return this.api.executeGET<InventoryStatus>(`${this.BASE_PATH}/catalogs/inventory-statuses/${id}`, true);\n }\n\n /**\n * Crea un nuevo estatus de inventario.\n * @param request - Datos del estatus a crear\n */\n async createStatus(request: InventoryStatusRequest): Promise<ResponseModel<InventoryStatus>> {\n return this.api.executePOST<InventoryStatus>(`${this.BASE_PATH}/catalogs/inventory-statuses`, request);\n }\n\n /**\n * Actualiza un estatus de inventario existente.\n * @param id - ID del estatus a actualizar\n * @param request - Nuevos datos del estatus\n */\n async updateStatus(id: number, request: InventoryStatusRequest): Promise<ResponseModel<InventoryStatus>> {\n return this.api.executePUT<InventoryStatus>(`${this.BASE_PATH}/catalogs/inventory-statuses/${id}`, request);\n }\n\n /**\n * Elimina un estatus de inventario.\n * @param id - ID del estatus a eliminar\n */\n async deleteStatus(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/catalogs/inventory-statuses/${id}`);\n }\n\n // #endregion\n\n // #region PACKINGS\n\n /**\n * Obtiene todos los empaques con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getPackings(filter?: PackingsFilter): Promise<ResponseModel<Packing[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/catalogs/packings`, filter);\n return this.api.executeGET<Packing[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para empaques.\n */\n async getPackingFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/catalogs/packings/filters`, true);\n }\n\n /**\n * Obtiene un empaque por su ID.\n * @param id - ID del empaque\n */\n async getPackingById(id: number): Promise<ResponseModel<Packing>> {\n return this.api.executeGET<Packing>(`${this.BASE_PATH}/catalogs/packings/${id}`, true);\n }\n\n /**\n * Crea un nuevo empaque.\n * @param request - Datos del empaque a crear\n */\n async createPacking(request: PackingRequest): Promise<ResponseModel<Packing>> {\n return this.api.executePOST<Packing>(`${this.BASE_PATH}/catalogs/packings`, request);\n }\n\n /**\n * Actualiza un empaque existente.\n * @param id - ID del empaque a actualizar\n * @param request - Nuevos datos del empaque\n */\n async updatePacking(id: number, request: PackingRequest): Promise<ResponseModel<Packing>> {\n return this.api.executePUT<Packing>(`${this.BASE_PATH}/catalogs/packings/${id}`, request);\n }\n\n /**\n * Activa o desactiva un empaque.\n * @param id - ID del empaque\n */\n async togglePackingStatus(id: number): Promise<ResponseModel<Packing>> {\n return this.api.executePUT<Packing>(`${this.BASE_PATH}/catalogs/packings/${id}/toggle-status`);\n }\n\n /**\n * Elimina un empaque.\n * @param id - ID del empaque a eliminar\n */\n async deletePacking(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/catalogs/packings/${id}`);\n }\n\n // #endregion\n\n // #region MATERIALS\n\n /**\n * Obtiene todos los materiales con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getMaterials(filter?: MaterialsFilter): Promise<ResponseModel<Material[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/catalogs/materials`, filter);\n return this.api.executeGET<Material[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para materiales.\n */\n async getMaterialFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/catalogs/materials/filters`, true);\n }\n\n /**\n * Obtiene un material por su ID.\n * @param id - ID del material\n */\n async getMaterialById(id: number): Promise<ResponseModel<Material>> {\n return this.api.executeGET<Material>(`${this.BASE_PATH}/catalogs/materials/${id}`, true);\n }\n\n /**\n * Crea un nuevo material.\n * @param request - Datos del material a crear\n */\n async createMaterial(request: MaterialRequest): Promise<ResponseModel<Material>> {\n return this.api.executePOST<Material>(`${this.BASE_PATH}/catalogs/materials`, request);\n }\n\n /**\n * Actualiza un material existente.\n * @param id - ID del material a actualizar\n * @param request - Nuevos datos del material\n */\n async updateMaterial(id: number, request: MaterialRequest): Promise<ResponseModel<Material>> {\n return this.api.executePUT<Material>(`${this.BASE_PATH}/catalogs/materials/${id}`, request);\n }\n\n /**\n * Elimina un material.\n * @param id - ID del material a eliminar\n */\n async deleteMaterial(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/catalogs/materials/${id}`);\n }\n\n // #endregion\n\n // #region PROVIDERS\n\n /**\n * Obtiene todos los proveedores con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getProviders(filter?: InventoryProvidersFilter): Promise<ResponseModel<InventoryProvider[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/catalogs/providers`, filter);\n return this.api.executeGET<InventoryProvider[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para proveedores.\n */\n async getProviderFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/catalogs/providers/filters`, true);\n }\n\n /**\n * Obtiene un proveedor por su ID.\n * @param id - ID del proveedor\n */\n async getProviderById(id: number): Promise<ResponseModel<InventoryProvider>> {\n return this.api.executeGET<InventoryProvider>(`${this.BASE_PATH}/catalogs/providers/${id}`, true);\n }\n\n /**\n * Crea un nuevo proveedor.\n * @param request - Datos del proveedor a crear\n */\n async createProvider(request: InventoryProviderRequest): Promise<ResponseModel<InventoryProvider>> {\n return this.api.executePOST<InventoryProvider>(`${this.BASE_PATH}/catalogs/providers`, request);\n }\n\n /**\n * Actualiza un proveedor existente.\n * @param id - ID del proveedor a actualizar\n * @param request - Nuevos datos del proveedor\n */\n async updateProvider(id: number, request: InventoryProviderRequest): Promise<ResponseModel<InventoryProvider>> {\n return this.api.executePUT<InventoryProvider>(`${this.BASE_PATH}/catalogs/providers/${id}`, request);\n }\n\n /**\n * Activa o desactiva un proveedor.\n * @param id - ID del proveedor\n */\n async toggleProviderStatus(id: number): Promise<ResponseModel<InventoryProvider>> {\n return this.api.executePUT<InventoryProvider>(`${this.BASE_PATH}/catalogs/providers/${id}/toggle-status`);\n }\n\n /**\n * Elimina un proveedor.\n * @param id - ID del proveedor a eliminar\n */\n async deleteProvider(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/catalogs/providers/${id}`);\n }\n\n // #endregion\n}\n","import { API } from \"@/core/API\";\nimport { ResponseModel } from \"@/types/ResponseModel\";\nimport { FilterBuilder, type FilterGroupsModel } from \"@/utils/FilterBuilder\";\nimport {\n ProductImage,\n ProductImageRequest,\n ProductImagesFilter,\n ProductBullet,\n ProductBulletRequest,\n ProductBulletsFilter,\n ProductKeyword,\n ProductKeywordRequest,\n ProductKeywordsFilter,\n ProductPrice,\n ProductPriceRequest,\n ProductPricesFilter,\n BlankProduct,\n BlankProductRequest,\n BlankProductsFilter,\n DetailProductPOD,\n DetailProductPODRequest,\n DetailProductPODFilter,\n Size,\n SizeRequest,\n SizesFilter,\n SizeGroup,\n SizeGroupRequest,\n SizeGroupsFilter,\n ProductType,\n ProductTypeRequest,\n ProductTypesFilter,\n ProductCategory,\n ProductCategoryRequest,\n ProductCategoriesFilter,\n ProductStatus,\n ProductStatusRequest,\n ProductStatusesFilter,\n Studio,\n StudioRequest,\n StudiosFilter,\n License,\n LicenseRequest,\n LicensesFilter,\n Provider,\n ProviderRequest,\n ProvidersFilter\n} from \"@/interfaces/Products\";\n\n/**\n * Servicio para gestionar productos y catálogos de productos.\n */\nexport class ProductService {\n private api: API;\n private readonly BASE_PATH = 'products';\n\n constructor(api: API) {\n this.api = api;\n }\n\n // #region PRODUCT IMAGES\n\n /**\n * Obtiene todas las imágenes de producto con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getImages(filter?: ProductImagesFilter): Promise<ResponseModel<ProductImage[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/images`, filter);\n return this.api.executeGET<ProductImage[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para imágenes de producto.\n */\n async getImageFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/images/filters`, true);\n }\n\n /**\n * Obtiene una imagen de producto por su ID.\n * @param id - ID de la imagen\n */\n async getImageById(id: number): Promise<ResponseModel<ProductImage>> {\n return this.api.executeGET<ProductImage>(`${this.BASE_PATH}/images/${id}`, true);\n }\n\n /**\n * Crea una nueva imagen de producto.\n * @param request - Datos de la imagen a crear\n */\n async createImage(request: ProductImageRequest): Promise<ResponseModel<ProductImage>> {\n return this.api.executePOST<ProductImage>(`${this.BASE_PATH}/images`, request);\n }\n\n /**\n * Actualiza una imagen de producto existente.\n * @param id - ID de la imagen a actualizar\n * @param request - Nuevos datos de la imagen\n */\n async updateImage(id: number, request: ProductImageRequest): Promise<ResponseModel<ProductImage>> {\n return this.api.executePUT<ProductImage>(`${this.BASE_PATH}/images/${id}`, request);\n }\n\n /**\n * Elimina una imagen de producto.\n * @param id - ID de la imagen a eliminar\n */\n async deleteImage(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/images/${id}`);\n }\n\n // #endregion\n\n // #region PRODUCT BULLETS\n\n /**\n * Obtiene todos los bullets de producto con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getBullets(filter?: ProductBulletsFilter): Promise<ResponseModel<ProductBullet[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/bullets`, filter);\n return this.api.executeGET<ProductBullet[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para bullets de producto.\n */\n async getBulletFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/bullets/filters`, true);\n }\n\n /**\n * Obtiene un bullet de producto por su ID.\n * @param id - ID del bullet\n */\n async getBulletById(id: number): Promise<ResponseModel<ProductBullet>> {\n return this.api.executeGET<ProductBullet>(`${this.BASE_PATH}/bullets/${id}`, true);\n }\n\n /**\n * Crea un nuevo bullet de producto.\n * @param request - Datos del bullet a crear\n */\n async createBullet(request: ProductBulletRequest): Promise<ResponseModel<ProductBullet>> {\n return this.api.executePOST<ProductBullet>(`${this.BASE_PATH}/bullets`, request);\n }\n\n /**\n * Actualiza un bullet de producto existente.\n * @param id - ID del bullet a actualizar\n * @param request - Nuevos datos del bullet\n */\n async updateBullet(id: number, request: ProductBulletRequest): Promise<ResponseModel<ProductBullet>> {\n return this.api.executePUT<ProductBullet>(`${this.BASE_PATH}/bullets/${id}`, request);\n }\n\n /**\n * Elimina un bullet de producto.\n * @param id - ID del bullet a eliminar\n */\n async deleteBullet(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/bullets/${id}`);\n }\n\n // #endregion\n\n // #region PRODUCT KEYWORDS\n\n /**\n * Obtiene todos los keywords de producto con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getKeywords(filter?: ProductKeywordsFilter): Promise<ResponseModel<ProductKeyword[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/keywords`, filter);\n return this.api.executeGET<ProductKeyword[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para keywords de producto.\n */\n async getKeywordFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/keywords/filters`, true);\n }\n\n /**\n * Obtiene un keyword de producto por su ID.\n * @param id - ID del keyword\n */\n async getKeywordById(id: number): Promise<ResponseModel<ProductKeyword>> {\n return this.api.executeGET<ProductKeyword>(`${this.BASE_PATH}/keywords/${id}`, true);\n }\n\n /**\n * Crea un nuevo keyword de producto.\n * @param request - Datos del keyword a crear\n */\n async createKeyword(request: ProductKeywordRequest): Promise<ResponseModel<ProductKeyword>> {\n return this.api.executePOST<ProductKeyword>(`${this.BASE_PATH}/keywords`, request);\n }\n\n /**\n * Actualiza un keyword de producto existente.\n * @param id - ID del keyword a actualizar\n * @param request - Nuevos datos del keyword\n */\n async updateKeyword(id: number, request: ProductKeywordRequest): Promise<ResponseModel<ProductKeyword>> {\n return this.api.executePUT<ProductKeyword>(`${this.BASE_PATH}/keywords/${id}`, request);\n }\n\n /**\n * Elimina un keyword de producto.\n * @param id - ID del keyword a eliminar\n */\n async deleteKeyword(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/keywords/${id}`);\n }\n\n // #endregion\n\n // #region PRODUCT PRICES\n\n /**\n * Obtiene todos los precios de producto con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getPrices(filter?: ProductPricesFilter): Promise<ResponseModel<ProductPrice[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/prices`, filter);\n return this.api.executeGET<ProductPrice[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para precios de producto.\n */\n async getPriceFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/prices/filters`, true);\n }\n\n /**\n * Obtiene un precio de producto por su ID.\n * @param id - ID del precio\n */\n async getPriceById(id: number): Promise<ResponseModel<ProductPrice>> {\n return this.api.executeGET<ProductPrice>(`${this.BASE_PATH}/prices/${id}`, true);\n }\n\n /**\n * Crea un nuevo precio de producto.\n * @param request - Datos del precio a crear\n */\n async createPrice(request: ProductPriceRequest): Promise<ResponseModel<ProductPrice>> {\n return this.api.executePOST<ProductPrice>(`${this.BASE_PATH}/prices`, request);\n }\n\n /**\n * Actualiza un precio de producto existente.\n * @param id - ID del precio a actualizar\n * @param request - Nuevos datos del precio\n */\n async updatePrice(id: number, request: ProductPriceRequest): Promise<ResponseModel<ProductPrice>> {\n return this.api.executePUT<ProductPrice>(`${this.BASE_PATH}/prices/${id}`, request);\n }\n\n /**\n * Elimina un precio de producto.\n * @param id - ID del precio a eliminar\n */\n async deletePrice(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/prices/${id}`);\n }\n\n // #endregion\n\n // #region BLANK PRODUCTS\n\n /**\n * Obtiene todos los productos en blanco con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getBlankProducts(filter?: BlankProductsFilter): Promise<ResponseModel<BlankProduct[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/blanks`, filter);\n return this.api.executeGET<BlankProduct[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para productos en blanco.\n */\n async getBlankProductFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/blanks/filters`, true);\n }\n\n /**\n * Obtiene un producto en blanco por su ID.\n * @param id - ID del producto en blanco\n */\n async getBlankProductById(id: number): Promise<ResponseModel<BlankProduct>> {\n return this.api.executeGET<BlankProduct>(`${this.BASE_PATH}/blanks/${id}`, true);\n }\n\n /**\n * Crea un nuevo producto en blanco.\n * @param request - Datos del producto en blanco a crear\n */\n async createBlankProduct(request: BlankProductRequest): Promise<ResponseModel<BlankProduct>> {\n return this.api.executePOST<BlankProduct>(`${this.BASE_PATH}/blanks`, request);\n }\n\n /**\n * Actualiza un producto en blanco existente.\n * @param id - ID del producto en blanco a actualizar\n * @param request - Nuevos datos del producto en blanco\n */\n async updateBlankProduct(id: number, request: BlankProductRequest): Promise<ResponseModel<BlankProduct>> {\n return this.api.executePUT<BlankProduct>(`${this.BASE_PATH}/blanks/${id}`, request);\n }\n\n /**\n * Elimina un producto en blanco.\n * @param id - ID del producto en blanco a eliminar\n */\n async deleteBlankProduct(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/blanks/${id}`);\n }\n\n // #endregion\n\n // #region DETAIL PRODUCT POD\n\n /**\n * Obtiene todos los detalles de producto POD con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getPODDetails(filter?: DetailProductPODFilter): Promise<ResponseModel<DetailProductPOD[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/pod-details`, filter);\n return this.api.executeGET<DetailProductPOD[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para detalles de producto POD.\n */\n async getPODDetailFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/pod-details/filters`, true);\n }\n\n /**\n * Obtiene un detalle de producto POD por su ID.\n * @param id - ID del detalle POD\n */\n async getPODDetailById(id: number): Promise<ResponseModel<DetailProductPOD>> {\n return this.api.executeGET<DetailProductPOD>(`${this.BASE_PATH}/pod-details/${id}`, true);\n }\n\n /**\n * Crea un nuevo detalle de producto POD.\n * @param request - Datos del detalle POD a crear\n */\n async createPODDetail(request: DetailProductPODRequest): Promise<ResponseModel<DetailProductPOD>> {\n return this.api.executePOST<DetailProductPOD>(`${this.BASE_PATH}/pod-details`, request);\n }\n\n /**\n * Actualiza un detalle de producto POD existente.\n * @param id - ID del detalle POD a actualizar\n * @param request - Nuevos datos del detalle POD\n */\n async updatePODDetail(id: number, request: DetailProductPODRequest): Promise<ResponseModel<DetailProductPOD>> {\n return this.api.executePUT<DetailProductPOD>(`${this.BASE_PATH}/pod-details/${id}`, request);\n }\n\n /**\n * Elimina un detalle de producto POD.\n * @param id - ID del detalle POD a eliminar\n */\n async deletePODDetail(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/pod-details/${id}`);\n }\n\n // #endregion\n\n // #region CATALOG - SIZES\n\n /**\n * Obtiene todas las tallas con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getSizes(filter?: SizesFilter): Promise<ResponseModel<Size[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/catalog/sizes`, filter);\n return this.api.executeGET<Size[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para tallas.\n */\n async getSizeFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/catalog/sizes/filters`, true);\n }\n\n /**\n * Obtiene una talla por su ID.\n * @param id - ID de la talla\n */\n async getSizeById(id: number): Promise<ResponseModel<Size>> {\n return this.api.executeGET<Size>(`${this.BASE_PATH}/catalog/sizes/${id}`, true);\n }\n\n /**\n * Crea una nueva talla.\n * @param request - Datos de la talla a crear\n */\n async createSize(request: SizeRequest): Promise<ResponseModel<Size>> {\n return this.api.executePOST<Size>(`${this.BASE_PATH}/catalog/sizes`, request);\n }\n\n /**\n * Actualiza una talla existente.\n * @param id - ID de la talla a actualizar\n * @param request - Nuevos datos de la talla\n */\n async updateSize(id: number, request: SizeRequest): Promise<ResponseModel<Size>> {\n return this.api.executePUT<Size>(`${this.BASE_PATH}/catalog/sizes/${id}`, request);\n }\n\n /**\n * Elimina una talla.\n * @param id - ID de la talla a eliminar\n */\n async deleteSize(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/catalog/sizes/${id}`);\n }\n\n // #endregion\n\n // #region CATALOG - SIZE GROUPS\n\n /**\n * Obtiene todos los grupos de tallas con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getSizeGroups(filter?: SizeGroupsFilter): Promise<ResponseModel<SizeGroup[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/catalog/size-groups`, filter);\n return this.api.executeGET<SizeGroup[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para grupos de tallas.\n */\n async getSizeGroupFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/catalog/size-groups/filters`, true);\n }\n\n /**\n * Obtiene un grupo de tallas por su ID.\n * @param id - ID del grupo de tallas\n */\n async getSizeGroupById(id: number): Promise<ResponseModel<SizeGroup>> {\n return this.api.executeGET<SizeGroup>(`${this.BASE_PATH}/catalog/size-groups/${id}`, true);\n }\n\n /**\n * Crea un nuevo grupo de tallas.\n * @param request - Datos del grupo de tallas a crear\n */\n async createSizeGroup(request: SizeGroupRequest): Promise<ResponseModel<SizeGroup>> {\n return this.api.executePOST<SizeGroup>(`${this.BASE_PATH}/catalog/size-groups`, request);\n }\n\n /**\n * Actualiza un grupo de tallas existente.\n * @param id - ID del grupo de tallas a actualizar\n * @param request - Nuevos datos del grupo de tallas\n */\n async updateSizeGroup(id: number, request: SizeGroupRequest): Promise<ResponseModel<SizeGroup>> {\n return this.api.executePUT<SizeGroup>(`${this.BASE_PATH}/catalog/size-groups/${id}`, request);\n }\n\n /**\n * Elimina un grupo de tallas.\n * @param id - ID del grupo de tallas a eliminar\n */\n async deleteSizeGroup(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/catalog/size-groups/${id}`);\n }\n\n // #endregion\n\n // #region CATALOG - PRODUCT TYPES\n\n /**\n * Obtiene todos los tipos de producto con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getProductTypes(filter?: ProductTypesFilter): Promise<ResponseModel<ProductType[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/catalog/product-types`, filter);\n return this.api.executeGET<ProductType[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para tipos de producto.\n */\n async getProductTypeFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/catalog/product-types/filters`, true);\n }\n\n /**\n * Obtiene un tipo de producto por su ID.\n * @param id - ID del tipo de producto\n */\n async getProductTypeById(id: number): Promise<ResponseModel<ProductType>> {\n return this.api.executeGET<ProductType>(`${this.BASE_PATH}/catalog/product-types/${id}`, true);\n }\n\n /**\n * Crea un nuevo tipo de producto.\n * @param request - Datos del tipo de producto a crear\n */\n async createProductType(request: ProductTypeRequest): Promise<ResponseModel<ProductType>> {\n return this.api.executePOST<ProductType>(`${this.BASE_PATH}/catalog/product-types`, request);\n }\n\n /**\n * Actualiza un tipo de producto existente.\n * @param id - ID del tipo de producto a actualizar\n * @param request - Nuevos datos del tipo de producto\n */\n async updateProductType(id: number, request: ProductTypeRequest): Promise<ResponseModel<ProductType>> {\n return this.api.executePUT<ProductType>(`${this.BASE_PATH}/catalog/product-types/${id}`, request);\n }\n\n /**\n * Elimina un tipo de producto.\n * @param id - ID del tipo de producto a eliminar\n */\n async deleteProductType(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/catalog/product-types/${id}`);\n }\n\n // #endregion\n\n // #region CATALOG - PRODUCT CATEGORIES\n\n /**\n * Obtiene todas las categorías de producto con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getProductCategories(filter?: ProductCategoriesFilter): Promise<ResponseModel<ProductCategory[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/catalog/product-categories`, filter);\n return this.api.executeGET<ProductCategory[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para categorías de producto.\n */\n async getProductCategoryFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/catalog/product-categories/filters`, true);\n }\n\n /**\n * Obtiene una categoría de producto por su ID.\n * @param id - ID de la categoría\n */\n async getProductCategoryById(id: number): Promise<ResponseModel<ProductCategory>> {\n return this.api.executeGET<ProductCategory>(`${this.BASE_PATH}/catalog/product-categories/${id}`, true);\n }\n\n /**\n * Crea una nueva categoría de producto.\n * @param request - Datos de la categoría a crear\n */\n async createProductCategory(request: ProductCategoryRequest): Promise<ResponseModel<ProductCategory>> {\n return this.api.executePOST<ProductCategory>(`${this.BASE_PATH}/catalog/product-categories`, request);\n }\n\n /**\n * Actualiza una categoría de producto existente.\n * @param id - ID de la categoría a actualizar\n * @param request - Nuevos datos de la categoría\n */\n async updateProductCategory(id: number, request: ProductCategoryRequest): Promise<ResponseModel<ProductCategory>> {\n return this.api.executePUT<ProductCategory>(`${this.BASE_PATH}/catalog/product-categories/${id}`, request);\n }\n\n /**\n * Activa o desactiva una categoría de producto.\n * @param id - ID de la categoría\n */\n async toggleProductCategoryStatus(id: number): Promise<ResponseModel<ProductCategory>> {\n return this.api.executePUT<ProductCategory>(`${this.BASE_PATH}/catalog/product-categories/${id}/toggle-status`);\n }\n\n /**\n * Elimina una categoría de producto.\n * @param id - ID de la categoría a eliminar\n */\n async deleteProductCategory(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/catalog/product-categories/${id}`);\n }\n\n // #endregion\n\n // #region CATALOG - PRODUCT STATUSES\n\n /**\n * Obtiene todos los estatus de producto con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getProductStatuses(filter?: ProductStatusesFilter): Promise<ResponseModel<ProductStatus[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/catalog/product-statuses`, filter);\n return this.api.executeGET<ProductStatus[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para estatus de producto.\n */\n async getProductStatusFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/catalog/product-statuses/filters`, true);\n }\n\n /**\n * Obtiene un estatus de producto por su ID.\n * @param id - ID del estatus\n */\n async getProductStatusById(id: number): Promise<ResponseModel<ProductStatus>> {\n return this.api.executeGET<ProductStatus>(`${this.BASE_PATH}/catalog/product-statuses/${id}`, true);\n }\n\n /**\n * Crea un nuevo estatus de producto.\n * @param request - Datos del estatus a crear\n */\n async createProductStatus(request: ProductStatusRequest): Promise<ResponseModel<ProductStatus>> {\n return this.api.executePOST<ProductStatus>(`${this.BASE_PATH}/catalog/product-statuses`, request);\n }\n\n /**\n * Actualiza un estatus de producto existente.\n * @param id - ID del estatus a actualizar\n * @param request - Nuevos datos del estatus\n */\n async updateProductStatus(id: number, request: ProductStatusRequest): Promise<ResponseModel<ProductStatus>> {\n return this.api.executePUT<ProductStatus>(`${this.BASE_PATH}/catalog/product-statuses/${id}`, request);\n }\n\n /**\n * Elimina un estatus de producto.\n * @param id - ID del estatus a eliminar\n */\n async deleteProductStatus(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/catalog/product-statuses/${id}`);\n }\n\n // #endregion\n\n // #region CATALOG - STUDIOS\n\n /**\n * Obtiene todos los estudios con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getStudios(filter?: StudiosFilter): Promise<ResponseModel<Studio[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/catalog/studios`, filter);\n return this.api.executeGET<Studio[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para estudios.\n */\n async getStudioFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/catalog/studios/filters`, true);\n }\n\n /**\n * Obtiene un estudio por su ID.\n * @param id - ID del estudio\n */\n async getStudioById(id: number): Promise<ResponseModel<Studio>> {\n return this.api.executeGET<Studio>(`${this.BASE_PATH}/catalog/studios/${id}`, true);\n }\n\n /**\n * Crea un nuevo estudio.\n * @param request - Datos del estudio a crear\n */\n async createStudio(request: StudioRequest): Promise<ResponseModel<Studio>> {\n return this.api.executePOST<Studio>(`${this.BASE_PATH}/catalog/studios`, request);\n }\n\n /**\n * Actualiza un estudio existente.\n * @param id - ID del estudio a actualizar\n * @param request - Nuevos datos del estudio\n */\n async updateStudio(id: number, request: StudioRequest): Promise<ResponseModel<Studio>> {\n return this.api.executePUT<Studio>(`${this.BASE_PATH}/catalog/studios/${id}`, request);\n }\n\n /**\n * Activa o desactiva un estudio.\n * @param id - ID del estudio\n */\n async toggleStudioStatus(id: number): Promise<ResponseModel<Studio>> {\n return this.api.executePUT<Studio>(`${this.BASE_PATH}/catalog/studios/${id}/toggle-status`);\n }\n\n /**\n * Elimina un estudio.\n * @param id - ID del estudio a eliminar\n */\n async deleteStudio(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/catalog/studios/${id}`);\n }\n\n // #endregion\n\n // #region CATALOG - LICENSES\n\n /**\n * Obtiene todas las licencias con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getLicenses(filter?: LicensesFilter): Promise<ResponseModel<License[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/catalog/licenses`, filter);\n return this.api.executeGET<License[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para licencias.\n */\n async getLicenseFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/catalog/licenses/filters`, true);\n }\n\n /**\n * Obtiene una licencia por su ID.\n * @param id - ID de la licencia\n */\n async getLicenseById(id: number): Promise<ResponseModel<License>> {\n return this.api.executeGET<License>(`${this.BASE_PATH}/catalog/licenses/${id}`, true);\n }\n\n /**\n * Crea una nueva licencia.\n * @param request - Datos de la licencia a crear\n */\n async createLicense(request: LicenseRequest): Promise<ResponseModel<License>> {\n return this.api.executePOST<License>(`${this.BASE_PATH}/catalog/licenses`, request);\n }\n\n /**\n * Actualiza una licencia existente.\n * @param id - ID de la licencia a actualizar\n * @param request - Nuevos datos de la licencia\n */\n async updateLicense(id: number, request: LicenseRequest): Promise<ResponseModel<License>> {\n return this.api.executePUT<License>(`${this.BASE_PATH}/catalog/licenses/${id}`, request);\n }\n\n /**\n * Activa o desactiva una licencia.\n * @param id - ID de la licencia\n */\n async toggleLicenseStatus(id: number): Promise<ResponseModel<License>> {\n return this.api.executePUT<License>(`${this.BASE_PATH}/catalog/licenses/${id}/toggle-status`);\n }\n\n /**\n * Elimina una licencia.\n * @param id - ID de la licencia a eliminar\n */\n async deleteLicense(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/catalog/licenses/${id}`);\n }\n\n // #endregion\n\n // #region CATALOG - PROVIDERS\n\n /**\n * Obtiene todos los proveedores con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getProviders(filter?: ProvidersFilter): Promise<ResponseModel<Provider[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/catalog/providers`, filter);\n return this.api.executeGET<Provider[]>(endpoint, true);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para proveedores.\n */\n async getProviderFiltersModel(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/catalog/providers/filters`, true);\n }\n\n /**\n * Obtiene un proveedor por su ID.\n * @param id - ID del proveedor\n */\n async getProviderById(id: number): Promise<ResponseModel<Provider>> {\n return this.api.executeGET<Provider>(`${this.BASE_PATH}/catalog/providers/${id}`, true);\n }\n\n /**\n * Crea un nuevo proveedor.\n * @param request - Datos del proveedor a crear\n */\n async createProvider(request: ProviderRequest): Promise<ResponseModel<Provider>> {\n return this.api.executePOST<Provider>(`${this.BASE_PATH}/catalog/providers`, request);\n }\n\n /**\n * Actualiza un proveedor existente.\n * @param id - ID del proveedor a actualizar\n * @param request - Nuevos datos del proveedor\n */\n async updateProvider(id: number, request: ProviderRequest): Promise<ResponseModel<Provider>> {\n return this.api.executePUT<Provider>(`${this.BASE_PATH}/catalog/providers/${id}`, request);\n }\n\n /**\n * Activa o desactiva un proveedor.\n * @param id - ID del proveedor\n */\n async toggleProviderStatus(id: number): Promise<ResponseModel<Provider>> {\n return this.api.executePUT<Provider>(`${this.BASE_PATH}/catalog/providers/${id}/toggle-status`);\n }\n\n /**\n * Elimina un proveedor.\n * @param id - ID del proveedor a eliminar\n */\n async deleteProvider(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/catalog/providers/${id}`);\n }\n\n // #endregion\n}\n","import { API } from \"@/core/API\";\nimport { ResponseModel } from \"@/types/ResponseModel\";\nimport { FilterBuilder, type FilterGroupsModel } from \"@/utils/FilterBuilder\";\nimport {\n Gender,\n GenderRequest,\n GendersFilter,\n AreaCode,\n AreaCodeRequest,\n AreaCodesFilter\n} from \"@/interfaces/Catalogs\";\n\n/**\n * Servicio para gestionar catálogos públicos.\n * No requiere autenticación.\n */\nexport class CatalogService {\n private api: API;\n private readonly BASE_PATH = 'catalogs';\n\n constructor(api: API) {\n this.api = api;\n }\n\n // #region GENDERS\n\n /**\n * Obtiene todos los géneros con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getGenders(filter?: GendersFilter): Promise<ResponseModel<Gender[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/genders`, filter);\n return this.api.executeGET<Gender[]>(endpoint, false);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para géneros.\n */\n async getGendersFilters(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/genders/filters`, false);\n }\n\n /**\n * Obtiene un género por su ID.\n * @param id - ID del género\n */\n async getGenderById(id: number): Promise<ResponseModel<Gender>> {\n return this.api.executeGET<Gender>(`${this.BASE_PATH}/genders/${id}`, false);\n }\n\n /**\n * Crea un nuevo género.\n * @param request - Datos del género a crear\n */\n async createGender(request: GenderRequest): Promise<ResponseModel<Gender>> {\n return this.api.executePOST<Gender>(`${this.BASE_PATH}/genders`, request);\n }\n\n /**\n * Actualiza un género existente.\n * @param id - ID del género a actualizar\n * @param request - Nuevos datos del género\n */\n async updateGender(id: number, request: GenderRequest): Promise<ResponseModel<Gender>> {\n return this.api.executePUT<Gender>(`${this.BASE_PATH}/genders/${id}`, request);\n }\n\n /**\n * Elimina un género.\n * @param id - ID del género a eliminar\n */\n async deleteGender(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/genders/${id}`);\n }\n\n // #endregion\n\n // #region AREA CODES\n\n /**\n * Obtiene todos los códigos de área con filtros opcionales.\n * @param filter - Filtros opcionales para la búsqueda\n */\n async getAreaCodes(filter?: AreaCodesFilter): Promise<ResponseModel<AreaCode[]>> {\n const endpoint = FilterBuilder.buildEndpoint(`${this.BASE_PATH}/area-codes`, filter);\n return this.api.executeGET<AreaCode[]>(endpoint, false);\n }\n\n /**\n * Obtiene el modelo de filtros disponibles para códigos de área.\n */\n async getAreaCodesFilters(): Promise<ResponseModel<FilterGroupsModel>> {\n return this.api.executeGET<FilterGroupsModel>(`${this.BASE_PATH}/area-codes/filters`, false);\n }\n\n /**\n * Obtiene un código de área por su ID.\n * @param id - ID del código de área\n */\n async getAreaCodeById(id: number): Promise<ResponseModel<AreaCode>> {\n return this.api.executeGET<AreaCode>(`${this.BASE_PATH}/area-codes/${id}`, false);\n }\n\n /**\n * Crea un nuevo código de área.\n * @param request - Datos del código de área a crear\n */\n async createAreaCode(request: AreaCodeRequest): Promise<ResponseModel<AreaCode>> {\n return this.api.executePOST<AreaCode>(`${this.BASE_PATH}/area-codes`, request);\n }\n\n /**\n * Actualiza un código de área existente.\n * @param id - ID del código de área a actualizar\n * @param request - Nuevos datos del código de área\n */\n async updateAreaCode(id: number, request: AreaCodeRequest): Promise<ResponseModel<AreaCode>> {\n return this.api.executePUT<AreaCode>(`${this.BASE_PATH}/area-codes/${id}`, request);\n }\n\n /**\n * Activa o desactiva un código de área.\n * @param id - ID del código de área\n */\n async toggleAreaCodeStatus(id: number): Promise<ResponseModel<AreaCode>> {\n return this.api.executePUT<AreaCode>(`${this.BASE_PATH}/area-codes/${id}/toggle-status`);\n }\n\n /**\n * Elimina un código de área.\n * @param id - ID del código de área a eliminar\n */\n async deleteAreaCode(id: number): Promise<ResponseModel<void>> {\n return this.api.executeDELETE<void>(`${this.BASE_PATH}/area-codes/${id}`);\n }\n\n // #endregion\n}\n","import { API } from \"./core/API\";\nimport { CryptoService } from \"./core/CryptoService\";\nimport { TokenManager } from \"./core/TokenManager\";\nimport { AuthInterceptor } from \"./core/interceptors/AuthInterceptor\";\nimport { ServiceProperties } from \"./types/ServiceProperties\";\nimport { TokenData } from \"./types/TokenData\";\nimport { AuthService } from \"./services/AuthService\";\nimport { UserService } from \"./services/UserService\";\nimport { SystemService } from \"./services/SystemService\";\nimport { InventoryService } from \"./services/InventoryService\";\nimport { ProductService } from \"./services/ProductService\";\nimport { CatalogService } from \"./services/CatalogService\";\n\n/**\n * SDK principal de FalconHUB\n */\nexport class FalconHUBSDK {\n public auth: AuthService;\n public user: UserService;\n public system: SystemService;\n public inventory: InventoryService;\n public product: ProductService;\n public catalog: CatalogService;\n\n private serviceProperties: ServiceProperties;\n private cryptoService: CryptoService;\n private tokenManager: TokenManager;\n private authInterceptor: AuthInterceptor | null;\n private api: API;\n\n constructor(serviceProperties: ServiceProperties) {\n this.serviceProperties = serviceProperties;\n\n this.cryptoService = new CryptoService();\n\n const autoRefreshConfig = this.normalizeAutoRefreshConfig(this.serviceProperties.autoRefresh);\n\n this.tokenManager = new TokenManager(\n this.serviceProperties.onTokensUpdated,\n this.serviceProperties.onSessionExpiring,\n async () => {\n await this.auth.logout();\n },\n async () => {\n const currentTokens = this.tokenManager.getTokens();\n if (!currentTokens?.refreshToken) return false;\n\n try {\n const response = await this.auth.refreshTokens({\n refreshToken: currentTokens.refreshToken,\n rememberMe: currentTokens.rememberMe\n });\n return response.success === true;\n } catch {\n return false;\n }\n },\n autoRefreshConfig.enabled ? autoRefreshConfig.thresholdMinutes : undefined\n );\n\n if (autoRefreshConfig.enabled) {\n this.authInterceptor = new AuthInterceptor({\n enabled: true,\n thresholdMinutes: autoRefreshConfig.thresholdMinutes,\n isTokenExpiringSoon: () => this.tokenManager.isTokenExpiringSoon(autoRefreshConfig.thresholdMinutes),\n hasValidTokens: () => this.tokenManager.hasValidTokens(),\n shouldAutoRefresh: () => this.tokenManager.shouldAutoRefresh(),\n refreshSession: async () => {\n await this.auth.validateSession();\n }\n });\n } else {\n this.authInterceptor = null;\n }\n\n this.api = new API(\n this.serviceProperties,\n this.cryptoService,\n this.authInterceptor,\n () => this.tokenManager.getAccessToken(),\n () => this.tokenManager.getRefreshToken()\n );\n\n this.auth = new AuthService(\n this.serviceProperties,\n this.tokenManager,\n this.cryptoService,\n this.api\n );\n\n this.user = new UserService(\n this.api\n );\n\n this.system = new SystemService(\n this.api\n );\n\n this.inventory = new InventoryService(\n this.api\n );\n\n this.product = new ProductService(\n this.api\n );\n\n this.catalog = new CatalogService(\n this.api\n );\n }\n\n private normalizeAutoRefreshConfig(\n config: ServiceProperties[\"autoRefresh\"]\n ): { enabled: boolean; thresholdMinutes: number } {\n if (typeof config === \"boolean\") {\n return { enabled: config, thresholdMinutes: 5 };\n }\n if (typeof config === \"object\" && config !== null) {\n return {\n enabled: config.enabled,\n thresholdMinutes: config.thresholdMinutes ?? 5\n };\n }\n return { enabled: true, thresholdMinutes: 5 };\n }\n\n /**\n * Inyecta tokens desde storage externo (cookies/localStorage/etc)\n * @param expiresAt - Timestamp en milisegundos\n */\n setTokensFromExternal(\n accessToken: string,\n refreshToken: string,\n expiresAt: number,\n rememberMe: boolean = false\n ): void {\n const tokens: TokenData = {\n accessToken,\n refreshToken,\n expiresAt,\n rememberMe\n };\n\n this.tokenManager.setTokensSilent(tokens);\n }\n\n /**\n * Obtiene los tokens actuales\n */\n getTokens(): TokenData | null {\n return this.tokenManager.getTokens();\n }\n\n /**\n * Verifica si el usuario está autenticado\n */\n isAuthenticated(): boolean {\n return this.tokenManager.hasValidTokens();\n }\n\n /**\n * Verifica si la sesión está por expirar\n */\n isSessionExpiringSoon(thresholdMinutes: number = 5): boolean {\n return this.tokenManager.isTokenExpiringSoon(thresholdMinutes);\n }\n\n /**\n * Obtiene el tiempo restante hasta la expiración en milisegundos\n */\n getTimeUntilExpiry(): number | null {\n return this.tokenManager.getTimeUntilExpiry();\n }\n}\n","import CryptoJS from 'crypto-js';\n\nexport function decrypt(encryptedBase64: string, secret: string, timestamp: string): string {\n const fullKey = `${secret}:${timestamp}`;\n // Generate key using SHA256\n const key = CryptoJS.SHA256(fullKey);\n\n // Parse total encrypted data from Base64\n const allData = CryptoJS.enc.Base64.parse(encryptedBase64);\n\n // Extract IV (first 16 bytes = 4 words)\n const iv = CryptoJS.lib.WordArray.create(allData.words.slice(0, 4), 16);\n\n // Extract ciphertext (remaining bytes)\n const ciphertext = CryptoJS.lib.WordArray.create(allData.words.slice(4), allData.sigBytes - 16);\n\n // Decrypt using AES-256-CBC\n // We use PKCS7 padding as it's the default in Node.js createDecipheriv for aes-256-cbc\n const decrypted = CryptoJS.AES.decrypt(\n { ciphertext: ciphertext } as any,\n key,\n {\n iv: iv,\n mode: CryptoJS.mode.CBC,\n padding: CryptoJS.pad.Pkcs7\n }\n );\n\n return decrypted.toString(CryptoJS.enc.Utf8);\n}\n"],"mappings":"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","names":["CryptoJS"]}
|