@obisey/nest 0.1.20 → 0.1.22

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.
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Adapters - Agnóstico de BD
3
+ *
4
+ * Patrón: Cada BD tiene su carpeta con adapters específicos
5
+ * - sequelize/ → Adapters para Sequelize ORM
6
+ * - drizzle/ → Adapters para Drizzle (futuro)
7
+ * - prisma/ → Adapters para Prisma (futuro)
8
+ *
9
+ * Cada adapter transforma PropertyDTO/RelationDTO → BD-specific config
10
+ */
11
+ export * from './sequelize';
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ /**
3
+ * Adapters - Agnóstico de BD
4
+ *
5
+ * Patrón: Cada BD tiene su carpeta con adapters específicos
6
+ * - sequelize/ → Adapters para Sequelize ORM
7
+ * - drizzle/ → Adapters para Drizzle (futuro)
8
+ * - prisma/ → Adapters para Prisma (futuro)
9
+ *
10
+ * Cada adapter transforma PropertyDTO/RelationDTO → BD-specific config
11
+ */
12
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ var desc = Object.getOwnPropertyDescriptor(m, k);
15
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
16
+ desc = { enumerable: true, get: function() { return m[k]; } };
17
+ }
18
+ Object.defineProperty(o, k2, desc);
19
+ }) : (function(o, m, k, k2) {
20
+ if (k2 === undefined) k2 = k;
21
+ o[k2] = m[k];
22
+ }));
23
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
24
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
25
+ };
26
+ Object.defineProperty(exports, "__esModule", { value: true });
27
+ __exportStar(require("./sequelize"), exports);
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Sequelize Adapters
3
+ * Agnósticos de BD, específicos para Sequelize
4
+ */
5
+ export { PropertyAdapter, type PropertyDTO, type SequelizeColumnConfig } from './property.adapter';
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ /**
3
+ * Sequelize Adapters
4
+ * Agnósticos de BD, específicos para Sequelize
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.PropertyAdapter = void 0;
8
+ var property_adapter_1 = require("./property.adapter");
9
+ Object.defineProperty(exports, "PropertyAdapter", { enumerable: true, get: function () { return property_adapter_1.PropertyAdapter; } });
@@ -0,0 +1,79 @@
1
+ /**
2
+ * PropertyAdapter para Sequelize
3
+ * Maneja tipado de propiedades agnósticamente
4
+ *
5
+ * RESPUESTA BAJO:
6
+ * - Convertir PropertyDTO → ColumnConfig (Sequelize)
7
+ * - Convertir PropertyDTO → TypeScriptType
8
+ * - Manejar types especiales (JSON, ENUM, ARRAY)
9
+ *
10
+ * @example
11
+ * const prop = { name: 'email', type: 'STRING', nullable: true }
12
+ * const column = PropertyAdapter.column(prop)
13
+ * // Returns: "@Column({ type: DataType.STRING, allowNull: true, field: 'email' })"
14
+ */
15
+ /**
16
+ * DTO que recibe el adapter (estructura de API)
17
+ */
18
+ export interface PropertyDTO {
19
+ name: string;
20
+ type: 'STRING' | 'INTEGER' | 'FLOAT' | 'DECIMAL' | 'DATE' | 'BOOLEAN' | 'JSON' | 'TEXT' | 'ENUM' | 'ARRAY';
21
+ nullable?: boolean;
22
+ primaryKey?: boolean;
23
+ autoIncrement?: boolean;
24
+ unique?: boolean;
25
+ defaultValue?: string | number | boolean;
26
+ enumValues?: string[];
27
+ decimals?: number;
28
+ precision?: number;
29
+ length?: number;
30
+ }
31
+ /**
32
+ * Config que devuelve el adapter (para usar en template)
33
+ */
34
+ export interface SequelizeColumnConfig {
35
+ decorator: string;
36
+ tsType: string;
37
+ tsFieldType: string;
38
+ }
39
+ /**
40
+ * PropertyAdapter - Transforma PropertyDTO → SequelizeColumnConfig
41
+ */
42
+ export declare class PropertyAdapter {
43
+ /**
44
+ * Convierte tipo de dato API → DataType de Sequelize (string)
45
+ * @example 'STRING' → 'DataType.STRING'
46
+ */
47
+ private static mapToSequelizeType;
48
+ /**
49
+ * Convierte tipo de dato API → Tipo TypeScript
50
+ * @example 'STRING' → 'string', 'INTEGER' → 'number'
51
+ */
52
+ private static mapToTypeScriptType;
53
+ /**
54
+ * Genera el decorador @Column con todas las opciones
55
+ */
56
+ private static generateColumnDecorator;
57
+ /**
58
+ * Método principal: Convierte PropertyDTO → SequelizeColumnConfig
59
+ * Esto es lo que usan los templates
60
+ */
61
+ static column(prop: PropertyDTO): SequelizeColumnConfig;
62
+ /**
63
+ * Getter para solo el decorador (para templates simples)
64
+ */
65
+ static getDecorator(prop: PropertyDTO): string;
66
+ /**
67
+ * Getter para solo el tipo TypeScript
68
+ */
69
+ static getTsType(prop: PropertyDTO): string;
70
+ /**
71
+ * Getter para solo el tipo TypeScript con ?
72
+ */
73
+ static getTsFieldType(prop: PropertyDTO): string;
74
+ }
75
+ /**
76
+ * Export default para facilitar uso en templates
77
+ * @example <%= adapter.column(property) %>
78
+ */
79
+ export default PropertyAdapter;
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ /**
3
+ * PropertyAdapter para Sequelize
4
+ * Maneja tipado de propiedades agnósticamente
5
+ *
6
+ * RESPUESTA BAJO:
7
+ * - Convertir PropertyDTO → ColumnConfig (Sequelize)
8
+ * - Convertir PropertyDTO → TypeScriptType
9
+ * - Manejar types especiales (JSON, ENUM, ARRAY)
10
+ *
11
+ * @example
12
+ * const prop = { name: 'email', type: 'STRING', nullable: true }
13
+ * const column = PropertyAdapter.column(prop)
14
+ * // Returns: "@Column({ type: DataType.STRING, allowNull: true, field: 'email' })"
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.PropertyAdapter = void 0;
18
+ /**
19
+ * PropertyAdapter - Transforma PropertyDTO → SequelizeColumnConfig
20
+ */
21
+ class PropertyAdapter {
22
+ /**
23
+ * Convierte tipo de dato API → DataType de Sequelize (string)
24
+ * @example 'STRING' → 'DataType.STRING'
25
+ */
26
+ static mapToSequelizeType(type, prop) {
27
+ const typeMap = {
28
+ STRING: 'DataType.STRING',
29
+ INTEGER: 'DataType.INTEGER',
30
+ FLOAT: 'DataType.FLOAT',
31
+ DECIMAL: `DataType.DECIMAL(${prop.precision || 10}, ${prop.decimals || 2})`,
32
+ DATE: 'DataType.DATE',
33
+ BOOLEAN: 'DataType.BOOLEAN',
34
+ JSON: 'DataType.JSON',
35
+ TEXT: 'DataType.TEXT',
36
+ ENUM: `DataType.ENUM(${prop.enumValues?.map((e) => `'${e}'`).join(', ') || ''})`,
37
+ ARRAY: 'DataType.ARRAY(DataType.STRING)', // Default array de strings
38
+ };
39
+ return typeMap[type] || 'DataType.STRING';
40
+ }
41
+ /**
42
+ * Convierte tipo de dato API → Tipo TypeScript
43
+ * @example 'STRING' → 'string', 'INTEGER' → 'number'
44
+ */
45
+ static mapToTypeScriptType(type) {
46
+ const typeMap = {
47
+ STRING: 'string',
48
+ INTEGER: 'number',
49
+ FLOAT: 'number',
50
+ DECIMAL: 'number',
51
+ DATE: 'Date',
52
+ BOOLEAN: 'boolean',
53
+ JSON: 'any',
54
+ TEXT: 'string',
55
+ ENUM: 'string',
56
+ ARRAY: 'string[]',
57
+ };
58
+ return typeMap[type] || 'string';
59
+ }
60
+ /**
61
+ * Genera el decorador @Column con todas las opciones
62
+ */
63
+ static generateColumnDecorator(prop, sequelizeType) {
64
+ const options = [`type: ${sequelizeType}`];
65
+ // Field mapping (si es distinto al nombre)
66
+ options.push(`field: '${prop.name}'`);
67
+ // Nullable
68
+ if (prop.nullable) {
69
+ options.push('allowNull: true');
70
+ }
71
+ else {
72
+ options.push('allowNull: false');
73
+ }
74
+ // Primary key
75
+ if (prop.primaryKey) {
76
+ options.push('primaryKey: true');
77
+ }
78
+ // Auto increment
79
+ if (prop.autoIncrement) {
80
+ options.push('autoIncrement: true');
81
+ }
82
+ // Unique
83
+ if (prop.unique) {
84
+ options.push('unique: true');
85
+ }
86
+ // Default value
87
+ if (prop.defaultValue !== undefined && prop.defaultValue !== null) {
88
+ const defaultValue = typeof prop.defaultValue === 'string' ? `'${prop.defaultValue}'` : prop.defaultValue;
89
+ options.push(`defaultValue: ${defaultValue}`);
90
+ }
91
+ return `@Column({ ${options.join(', ')} })`;
92
+ }
93
+ /**
94
+ * Método principal: Convierte PropertyDTO → SequelizeColumnConfig
95
+ * Esto es lo que usan los templates
96
+ */
97
+ static column(prop) {
98
+ const sequelizeType = this.mapToSequelizeType(prop.type, prop);
99
+ const tsType = this.mapToTypeScriptType(prop.type);
100
+ // Campo TypeScript con ? si es nullable
101
+ const tsFieldType = prop.nullable ? `${tsType}?` : tsType;
102
+ return {
103
+ decorator: this.generateColumnDecorator(prop, sequelizeType),
104
+ tsType,
105
+ tsFieldType,
106
+ };
107
+ }
108
+ /**
109
+ * Getter para solo el decorador (para templates simples)
110
+ */
111
+ static getDecorator(prop) {
112
+ const sequelizeType = this.mapToSequelizeType(prop.type, prop);
113
+ return this.generateColumnDecorator(prop, sequelizeType);
114
+ }
115
+ /**
116
+ * Getter para solo el tipo TypeScript
117
+ */
118
+ static getTsType(prop) {
119
+ return this.mapToTypeScriptType(prop.type);
120
+ }
121
+ /**
122
+ * Getter para solo el tipo TypeScript con ?
123
+ */
124
+ static getTsFieldType(prop) {
125
+ const tsType = this.mapToTypeScriptType(prop.type);
126
+ return prop.nullable ? `${tsType}?` : tsType;
127
+ }
128
+ }
129
+ exports.PropertyAdapter = PropertyAdapter;
130
+ /**
131
+ * Export default para facilitar uso en templates
132
+ * @example <%= adapter.column(property) %>
133
+ */
134
+ exports.default = PropertyAdapter;
@@ -0,0 +1,4 @@
1
+ import { ExceptionFilter, ArgumentsHost, HttpException } from '@nestjs/common';
2
+ export declare class HttpExceptionFilter implements ExceptionFilter {
3
+ catch(exception: HttpException, host: ArgumentsHost): void;
4
+ }
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.HttpExceptionFilter = void 0;
10
+ const common_1 = require("@nestjs/common");
11
+ let HttpExceptionFilter = class HttpExceptionFilter {
12
+ catch(exception, host) {
13
+ const ctx = host.switchToHttp();
14
+ const response = ctx.getResponse();
15
+ const request = ctx.getRequest();
16
+ const status = exception instanceof common_1.HttpException
17
+ ? exception.getStatus()
18
+ : common_1.HttpStatus.INTERNAL_SERVER_ERROR;
19
+ const err = exception.message;
20
+ console.log(exception, response, request, status, err);
21
+ try {
22
+ response.status(status).json({
23
+ statusCode: status,
24
+ timestamp: new Date().toISOString(),
25
+ path: request.url,
26
+ err: err,
27
+ });
28
+ }
29
+ catch (err) {
30
+ console.log(err);
31
+ }
32
+ }
33
+ };
34
+ exports.HttpExceptionFilter = HttpExceptionFilter;
35
+ exports.HttpExceptionFilter = HttpExceptionFilter = __decorate([
36
+ (0, common_1.Catch)(common_1.HttpException)
37
+ ], HttpExceptionFilter);
@@ -0,0 +1 @@
1
+ export declare const REDIS_CLIENT: unique symbol;
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.REDIS_CLIENT = void 0;
4
+ exports.REDIS_CLIENT = Symbol('Starconsole_REDIS');
package/conexion.d.ts CHANGED
@@ -0,0 +1,25 @@
1
+ import { Sequelize } from 'sequelize-typescript';
2
+ /**
3
+ * Configuración de conexión a BD por tenant (emisor/receptor).
4
+ * El emisor (Global/Nucleus) expone un mapa IdEmpresa → ConexionProps.
5
+ */
6
+ export interface ConexionProps {
7
+ nombre: string;
8
+ id: string | number;
9
+ database: string;
10
+ username: string;
11
+ password: string;
12
+ host: string;
13
+ port: number;
14
+ dominios?: Array<{
15
+ nombre: string;
16
+ }>;
17
+ }
18
+ /**
19
+ * Clase de conexión por tenant. El app la usa vía CONEXION_FACTORY:
20
+ * { provide: CONEXION_FACTORY, useValue: (config) => new Conexion(config, [Model1, Model2, ...]) }
21
+ * Los providers generados (X_REPOSITORY) inyectan CONEXION_FACTORY y ReceptorService.
22
+ */
23
+ export declare class Conexion extends Sequelize {
24
+ constructor(config: ConexionProps, models?: any[]);
25
+ }
package/conexion.js CHANGED
@@ -1,32 +1,25 @@
1
- // import { Sequelize } from 'sequelize-typescript';
2
- // interface Dominio {
3
- // nombre: string;
4
- // }
5
- // export interface ConexionProps {
6
- // nombre: string;
7
- // id: string | number;
8
- // database: string;
9
- // username: string;
10
- // password: string;
11
- // host: string;
12
- // port: number;
13
- // dominios: Dominio[];
14
- // }
15
- // export class Conexion extends Sequelize {
16
- // constructor({ host, port, username, password, database }) {
17
- // super({
18
- // dialect: 'mysql',
19
- // host,
20
- // port,
21
- // username,
22
- // password,
23
- // database,
24
- // // logging : true,
25
- // logging: false,
26
- // sync: {
27
- // force: true,
28
- // alter: true,
29
- // },
30
- // });
31
- // }
32
- // }
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Conexion = void 0;
4
+ const sequelize_typescript_1 = require("sequelize-typescript");
5
+ /**
6
+ * Clase de conexión por tenant. El app la usa vía CONEXION_FACTORY:
7
+ * { provide: CONEXION_FACTORY, useValue: (config) => new Conexion(config, [Model1, Model2, ...]) }
8
+ * Los providers generados (X_REPOSITORY) inyectan CONEXION_FACTORY y ReceptorService.
9
+ */
10
+ class Conexion extends sequelize_typescript_1.Sequelize {
11
+ constructor(config, models = []) {
12
+ super({
13
+ dialect: 'mysql',
14
+ host: config.host,
15
+ port: config.port,
16
+ username: config.username,
17
+ password: config.password,
18
+ database: config.database,
19
+ repositoryMode: true,
20
+ models: models.length ? models : undefined,
21
+ logging: false,
22
+ });
23
+ }
24
+ }
25
+ exports.Conexion = Conexion;
package/index.d.ts CHANGED
@@ -9,5 +9,10 @@ export * from './prototipos/utils/activarRedis';
9
9
  export * from './prototipos/utils/formarInclude';
10
10
  export * from './prototipos/utils/formarorder';
11
11
  export * from './prototipos/utils/formarwhere';
12
+ export * from './prototipos/utils/getModelId';
13
+ export * from './assets/http-exception.filter';
14
+ export * from './assets/tokens';
12
15
  export * from './types';
13
16
  export * from './fecha';
17
+ export * from './conexion';
18
+ export * from './receptor.service';
package/index.js CHANGED
@@ -26,5 +26,10 @@ __exportStar(require("./prototipos/utils/activarRedis"), exports);
26
26
  __exportStar(require("./prototipos/utils/formarInclude"), exports);
27
27
  __exportStar(require("./prototipos/utils/formarorder"), exports);
28
28
  __exportStar(require("./prototipos/utils/formarwhere"), exports);
29
+ __exportStar(require("./prototipos/utils/getModelId"), exports);
30
+ __exportStar(require("./assets/http-exception.filter"), exports);
31
+ __exportStar(require("./assets/tokens"), exports);
29
32
  __exportStar(require("./types"), exports);
30
33
  __exportStar(require("./fecha"), exports);
34
+ __exportStar(require("./conexion"), exports);
35
+ __exportStar(require("./receptor.service"), exports);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@obisey/nest",
3
- "version": "0.1.20",
3
+ "version": "0.1.22",
4
4
  "description": "NestJS utilities and base classes by Obisey",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -40,6 +40,7 @@
40
40
  "reflect-metadata": "^0.2.2",
41
41
  "sequelize": "^6.37.7",
42
42
  "sequelize-typescript": "^2.1.6",
43
- "typescript": "^5.8.3"
43
+ "typescript": "^5.8.3",
44
+ "express": "^5.0.0"
44
45
  }
45
46
  }
@@ -41,6 +41,7 @@ var tiempo = 86400000;
41
41
  var isDev = false;
42
42
  const cachear_1 = require("./utils/cachear");
43
43
  const paginar_1 = require("./utils/paginar");
44
+ const getModelId_1 = require("./utils/getModelId");
44
45
  const _ = __importStar(require("lodash"));
45
46
  function BaseResolver(modelo) {
46
47
  return class BaseResolver {
@@ -468,14 +469,14 @@ function BaseResolver(modelo) {
468
469
  // ) {
469
470
  // IdEmpresa = await this.receptor.buscarEmpresa();
470
471
  // }
471
- let nkey = `${universo ? universo : 'pro'}:${IdEmpresa}:${modelo}:${item.id}`;
472
+ let nkey = `${universo ? universo : 'pro'}:${IdEmpresa}:${modelo}:${(0, getModelId_1.getModelId)(item)}`;
472
473
  let pkey = (id) => `${universo ? universo : 'pro'}:${IdEmpresa}:${planeta}:${id}`;
473
474
  const { resultado, cache } = await (0, cachear_1.cachear)(cacheable, this.cacheManager, (0, keyInterface_1.transformarKey)({
474
475
  universo,
475
476
  IdEmpresa,
476
477
  tipo,
477
478
  fragmentos: [
478
- { nombre: modelo, id: item.id },
479
+ { nombre: modelo, id: (0, getModelId_1.getModelId)(item) },
479
480
  { nombre: planeta },
480
481
  ],
481
482
  }), (cache) => Promise.resolve(cache.map((n) => new Clase(JSON.parse(n)))), //Revisar
@@ -506,7 +507,7 @@ function BaseResolver(modelo) {
506
507
  }
507
508
  }), //observar
508
509
  (__, resultado) => {
509
- return Promise.all(resultado.map((n) => this.redis.hSet(pkey(n.id), 'item', JSON.stringify(n)))).then(() => this.redis.hSet(nkey, planeta, JSON.stringify(resultado.map((n) => n.id))));
510
+ return Promise.all(resultado.map((n) => this.redis.hSet(pkey((0, getModelId_1.getModelId)(n)), 'item', JSON.stringify(n)))).then(() => this.redis.hSet(nkey, planeta, JSON.stringify(resultado.map((n) => (0, getModelId_1.getModelId)(n)))));
510
511
  });
511
512
  await (0, paginar_1.paginar)(this.cacheManager, IdEmpresa, pagina, planeta, resultado.map((n) => n.get({ plain: true })));
512
513
  // if (isDev)
@@ -10,6 +10,7 @@ const cifrado_1 = require("./utils/cifrado");
10
10
  const keyInterface_1 = require("./utils/keyInterface");
11
11
  exports.redis_on = true;
12
12
  const paginar_1 = require("./utils/paginar");
13
+ const getModelId_1 = require("./utils/getModelId");
13
14
  var isDev = false;
14
15
  var stringifWhere = (where) => (0, lodash_1.isObject)(where)
15
16
  ? JSON.stringify(Object.entries(where).reduce((ac, [a, v]) => {
@@ -151,7 +152,7 @@ function BaseService(modelo) {
151
152
  resolve(undefined);
152
153
  }), //observar
153
154
  (__, resultado) => {
154
- return this.redis.hSet(nkey, peticion, JSON.stringify(resultado.map((n) => n.id)));
155
+ return this.redis.hSet(nkey, peticion, JSON.stringify(resultado.map((n) => (0, getModelId_1.getModelId)(n))));
155
156
  });
156
157
  await (0, paginar_1.paginar)(this.cacheManager, key.IdEmpresa, pagina, modelo, resultado.map((n) => n.get({ plain: true })));
157
158
  // if (isDev)
@@ -1 +1 @@
1
- export declare function onRedis(datos: any, si?: boolean): boolean;
1
+ export declare function onRedis(datos: any, si?: boolean): any;
@@ -1,4 +1,4 @@
1
- export declare const formarInclude: (include: any, mapa: any, tipo: any, conexion: any, required?: boolean) => any;
1
+ export declare const formarInclude: (include: any, mapa: any, tipo: any, conexion: any, required?: boolean) => Promise<any>;
2
2
  declare class FilterBasic {
3
3
  is: string;
4
4
  }
@@ -1 +1 @@
1
- export declare const formarWhere: (where: any) => {};
1
+ export declare const formarWhere: (where: any) => any;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Obtiene el id de una instancia Sequelize o de un objeto plano.
3
+ * Usa get({ plain: true }) en modelos para evitar shadowing (ej. field: 'Id').
4
+ */
5
+ export declare function getModelId(instance: any): number | undefined;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getModelId = getModelId;
4
+ /**
5
+ * Obtiene el id de una instancia Sequelize o de un objeto plano.
6
+ * Usa get({ plain: true }) en modelos para evitar shadowing (ej. field: 'Id').
7
+ */
8
+ function getModelId(instance) {
9
+ if (instance == null)
10
+ return undefined;
11
+ const plain = typeof instance.get === 'function'
12
+ ? instance.get({ plain: true })
13
+ : instance;
14
+ const id = plain?.id ?? plain?.Id ?? plain?.['ID'];
15
+ const n = Number(id);
16
+ return Number.isNaN(n) ? undefined : n;
17
+ }
@@ -0,0 +1,38 @@
1
+ import { HttpService } from '@nestjs/axios';
2
+ import type { ConexionProps } from './conexion';
3
+ export declare const RECEPTOR_OPTIONS = "RECEPTOR_OPTIONS";
4
+ /** Token para inyectar la factory (config) => Conexion. El app provee: useValue: (config) => new Conexion(config, [todos los modelos]) */
5
+ export declare const CONEXION_FACTORY = "CONEXION_FACTORY";
6
+ export interface ReceptorServiceOptions {
7
+ /** URL base del emisor (Global/Nucleus), ej. http://localhost:4302 */
8
+ globalUrl: string;
9
+ /** Ruta del endpoint emisor, ej. /global/emisor */
10
+ emisorPath?: string;
11
+ }
12
+ export declare class ReceptorService {
13
+ private readonly request;
14
+ private readonly httpService;
15
+ private readonly options?;
16
+ private conexionesActivas;
17
+ constructor(request: any, httpService: HttpService, options?: ReceptorServiceOptions);
18
+ private getGlobalUrl;
19
+ private getEmisorPath;
20
+ /**
21
+ * Obtiene el mapa de configuraciones de BD desde el emisor (Global).
22
+ */
23
+ obtenerConfiguraciones(): Promise<Record<string, ConexionProps>>;
24
+ /**
25
+ * Resuelve IdEmpresa para el request actual (session o host → dominios).
26
+ */
27
+ obtenerIdEmpresa(data?: Record<string, ConexionProps>): Promise<string | null>;
28
+ /**
29
+ * Devuelve la conexión para el request actual. Cachea por IdEmpresa.
30
+ * @param req - request (opcional si ya inyectado en el servicio)
31
+ * @param factoryOrClass - factory (config) => T o clase new (config) => T (ej. Conexion de @obisey/nest)
32
+ */
33
+ buscar<T = any>(req: {
34
+ req?: any;
35
+ headers?: Record<string, string>;
36
+ session?: any;
37
+ }, factoryOrClass: ((config: ConexionProps) => T) | (new (config: ConexionProps) => T)): Promise<T | null>;
38
+ }
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.ReceptorService = exports.CONEXION_FACTORY = exports.RECEPTOR_OPTIONS = void 0;
16
+ /**
17
+ * ReceptorService: conexión dinámica centralizada por request.
18
+ * Obtiene config de BDs desde el emisor (Global/Nucleus), resuelve IdEmpresa
19
+ * por session o host, cachea conexiones por tenant y devuelve la Conexion
20
+ * para el request actual.
21
+ *
22
+ * Uso: en el provider de cada entidad dinámica:
23
+ * useFactory: async (req, receptor: ReceptorService) => {
24
+ * const conexion = await receptor.buscar(req, Conexion);
25
+ * return { repository: conexion.getRepository(Entity), conexion };
26
+ * },
27
+ * inject: [REQUEST, ReceptorService],
28
+ */
29
+ const common_1 = require("@nestjs/common");
30
+ const core_1 = require("@nestjs/core");
31
+ const axios_1 = require("@nestjs/axios");
32
+ exports.RECEPTOR_OPTIONS = 'RECEPTOR_OPTIONS';
33
+ /** Token para inyectar la factory (config) => Conexion. El app provee: useValue: (config) => new Conexion(config, [todos los modelos]) */
34
+ exports.CONEXION_FACTORY = 'CONEXION_FACTORY';
35
+ let ReceptorService = class ReceptorService {
36
+ constructor(request, httpService, options) {
37
+ this.request = request;
38
+ this.httpService = httpService;
39
+ this.options = options;
40
+ this.conexionesActivas = new Map();
41
+ }
42
+ getGlobalUrl() {
43
+ return this.options?.globalUrl ?? process.env.GLOBAL_URL ?? 'http://localhost:4302';
44
+ }
45
+ getEmisorPath() {
46
+ return this.options?.emisorPath ?? '/global/emisor';
47
+ }
48
+ /**
49
+ * Obtiene el mapa de configuraciones de BD desde el emisor (Global).
50
+ */
51
+ async obtenerConfiguraciones() {
52
+ const url = `${this.getGlobalUrl()}${this.getEmisorPath()}`;
53
+ try {
54
+ const res = await this.httpService.get(url).toPromise();
55
+ return res?.data ?? {};
56
+ }
57
+ catch (err) {
58
+ console.error('[ReceptorService] Error obteniendo config desde emisor:', url, err);
59
+ return {};
60
+ }
61
+ }
62
+ /**
63
+ * Resuelve IdEmpresa para el request actual (session o host → dominios).
64
+ */
65
+ async obtenerIdEmpresa(data) {
66
+ const req = this.request?.req ?? this.request;
67
+ let IdEmpresa = req?.session?.IdEmpresa ?? req?.headers?.['x-empresa-id'] ?? null;
68
+ if (IdEmpresa)
69
+ return String(IdEmpresa);
70
+ const host = req?.headers?.['host'];
71
+ if (!host || !data)
72
+ return null;
73
+ const key = Object.keys(data).find((k) => data[k].dominios?.some((d) => d.nombre === host));
74
+ return key ?? null;
75
+ }
76
+ /**
77
+ * Devuelve la conexión para el request actual. Cachea por IdEmpresa.
78
+ * @param req - request (opcional si ya inyectado en el servicio)
79
+ * @param factoryOrClass - factory (config) => T o clase new (config) => T (ej. Conexion de @obisey/nest)
80
+ */
81
+ async buscar(req, factoryOrClass) {
82
+ const data = await this.obtenerConfiguraciones();
83
+ const r = req?.req ?? req ?? this.request;
84
+ let IdEmpresa = r?.session?.IdEmpresa ?? r?.headers?.['x-empresa-id'] ?? null;
85
+ if (!IdEmpresa && r?.headers?.host && data) {
86
+ IdEmpresa = Object.keys(data).find((k) => data[k].dominios?.some((d) => d.nombre === r.headers.host)) ?? null;
87
+ }
88
+ if (!IdEmpresa)
89
+ return null;
90
+ IdEmpresa = String(IdEmpresa);
91
+ const cached = this.conexionesActivas.get(IdEmpresa);
92
+ if (cached)
93
+ return cached;
94
+ const config = data[IdEmpresa];
95
+ if (!config) {
96
+ console.warn('[ReceptorService] No hay config para IdEmpresa:', IdEmpresa);
97
+ return null;
98
+ }
99
+ const conn = typeof factoryOrClass === 'function' && factoryOrClass.length === 1
100
+ ? factoryOrClass(config)
101
+ : new factoryOrClass(config);
102
+ this.conexionesActivas.set(IdEmpresa, conn);
103
+ return conn;
104
+ }
105
+ };
106
+ exports.ReceptorService = ReceptorService;
107
+ exports.ReceptorService = ReceptorService = __decorate([
108
+ (0, common_1.Injectable)(),
109
+ __param(0, (0, common_1.Inject)(core_1.REQUEST)),
110
+ __param(2, (0, common_1.Optional)()),
111
+ __param(2, (0, common_1.Inject)(exports.RECEPTOR_OPTIONS)),
112
+ __metadata("design:paramtypes", [Object, axios_1.HttpService, Object])
113
+ ], ReceptorService);