@obisey/nest 0.1.21 → 0.1.23
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/adapters/index.d.ts +11 -0
- package/adapters/index.js +27 -0
- package/adapters/sequelize/index.d.ts +5 -0
- package/adapters/sequelize/index.js +9 -0
- package/adapters/sequelize/property.adapter.d.ts +79 -0
- package/adapters/sequelize/property.adapter.js +134 -0
- package/conexion.d.ts +25 -0
- package/conexion.js +25 -32
- package/index.d.ts +3 -0
- package/index.js +3 -0
- package/package.json +6 -3
- package/prototipos/baseService.js +16 -2
- package/prototipos/utils/activarRedis.d.ts +1 -1
- package/prototipos/utils/formarInclude.d.ts +1 -1
- package/prototipos/utils/formarwhere.d.ts +1 -1
- package/prototipos/utils/getModelId.d.ts +5 -0
- package/prototipos/utils/getModelId.js +17 -0
- package/receptor.service.d.ts +38 -0
- package/receptor.service.js +113 -0
|
@@ -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,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;
|
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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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,7 +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';
|
|
12
13
|
export * from './assets/http-exception.filter';
|
|
13
14
|
export * from './assets/tokens';
|
|
14
15
|
export * from './types';
|
|
15
16
|
export * from './fecha';
|
|
17
|
+
export * from './conexion';
|
|
18
|
+
export * from './receptor.service';
|
package/index.js
CHANGED
|
@@ -26,7 +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);
|
|
29
30
|
__exportStar(require("./assets/http-exception.filter"), exports);
|
|
30
31
|
__exportStar(require("./assets/tokens"), exports);
|
|
31
32
|
__exportStar(require("./types"), exports);
|
|
32
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.
|
|
3
|
+
"version": "0.1.23",
|
|
4
4
|
"description": "NestJS utilities and base classes by Obisey",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -35,12 +35,15 @@
|
|
|
35
35
|
"@types/sequelize": "^4.28.20",
|
|
36
36
|
"cache-manager": "^7.0.0",
|
|
37
37
|
"cache-manager-redis-store": "^3.0.1",
|
|
38
|
+
"express": "^5.0.0",
|
|
38
39
|
"graphql": "^16.0.0",
|
|
39
40
|
"ioredis": "^5.6.1",
|
|
40
41
|
"reflect-metadata": "^0.2.2",
|
|
41
42
|
"sequelize": "^6.37.7",
|
|
42
43
|
"sequelize-typescript": "^2.1.6",
|
|
43
|
-
"typescript": "^5.8.3"
|
|
44
|
-
|
|
44
|
+
"typescript": "^5.8.3"
|
|
45
|
+
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"dayjs": "^1.11.19"
|
|
45
48
|
}
|
|
46
49
|
}
|
|
@@ -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]) => {
|
|
@@ -127,7 +128,19 @@ function BaseService(modelo) {
|
|
|
127
128
|
...key,
|
|
128
129
|
include,
|
|
129
130
|
where,
|
|
130
|
-
}), (cache) => Promise.resolve(cache.map((n) =>
|
|
131
|
+
}), (cache) => Promise.resolve(cache.map((n) => {
|
|
132
|
+
const parsed = JSON.parse(n);
|
|
133
|
+
console.log(`[OBISEY-NEST CACHE HIT] ${modelo}:`, {
|
|
134
|
+
cached: parsed,
|
|
135
|
+
modelName: (0, lodash_1.capitalize)(modelo),
|
|
136
|
+
});
|
|
137
|
+
const instance = new repository.sequelize.models[(0, lodash_1.capitalize)(modelo)](parsed);
|
|
138
|
+
console.log(`[OBISEY-NEST DESERIALIZED] ${modelo}:`, {
|
|
139
|
+
id: instance.id,
|
|
140
|
+
hasId: 'id' in instance,
|
|
141
|
+
});
|
|
142
|
+
return instance;
|
|
143
|
+
})), //Revisar
|
|
131
144
|
(resultado) => Promise.resolve(resultado.map((n) => n.get({ plain: true }))), //transformar
|
|
132
145
|
() => new Promise((resolve) => {
|
|
133
146
|
resolve(repository.findAll(value)); //Pedir
|
|
@@ -151,7 +164,7 @@ function BaseService(modelo) {
|
|
|
151
164
|
resolve(undefined);
|
|
152
165
|
}), //observar
|
|
153
166
|
(__, resultado) => {
|
|
154
|
-
return this.redis.hSet(nkey, peticion, JSON.stringify(resultado.map((n) =>
|
|
167
|
+
return this.redis.hSet(nkey, peticion, JSON.stringify(resultado.map((n) => (0, getModelId_1.getModelId)(n))));
|
|
155
168
|
});
|
|
156
169
|
await (0, paginar_1.paginar)(this.cacheManager, key.IdEmpresa, pagina, modelo, resultado.map((n) => n.get({ plain: true })));
|
|
157
170
|
// if (isDev)
|
|
@@ -160,6 +173,7 @@ function BaseService(modelo) {
|
|
|
160
173
|
// 'paginacion',
|
|
161
174
|
// cache,
|
|
162
175
|
// );
|
|
176
|
+
console.log(`[BUSCAR-TODOS-RESULT] modelo=${modelo} items=${resultado.length} cache=${cache}`);
|
|
163
177
|
resolve(resultado ? resultado : []);
|
|
164
178
|
}
|
|
165
179
|
catch (err) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function onRedis(datos: any, si?: boolean):
|
|
1
|
+
export declare function onRedis(datos: any, si?: boolean): boolean;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const formarInclude: (include: any, mapa: any, tipo: any, conexion: any, required?: boolean) =>
|
|
1
|
+
export declare const formarInclude: (include: any, mapa: any, tipo: any, conexion: any, required?: boolean) => 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) => {};
|
|
@@ -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);
|