@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.
- 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/assets/http-exception.filter.d.ts +4 -0
- package/assets/http-exception.filter.js +37 -0
- package/assets/tokens.d.ts +1 -0
- package/assets/tokens.js +4 -0
- package/conexion.d.ts +25 -0
- package/conexion.js +25 -32
- package/index.d.ts +5 -0
- package/index.js +5 -0
- package/package.json +3 -2
- package/prototipos/baseResolver.js +4 -3
- package/prototipos/baseService.js +2 -1
- 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;
|
|
@@ -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;
|
package/assets/tokens.js
ADDED
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,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.
|
|
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
|
|
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
|
|
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(
|
|
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) =>
|
|
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):
|
|
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,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);
|