fpavon-ee-shared 1.0.0
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/dependency-injection/dependency-injection.ts +56 -0
- package/digitalSignature/application/digitalSignature.useCase.ts +171 -0
- package/digitalSignature/domain/PDFArrayCustom.ts +60 -0
- package/digitalSignature/domain/SignPDF.ts +112 -0
- package/digitalSignature/infrastructure/routes/digitalSignature.routes.ts +3 -0
- package/digitalSignature/infrastructure/template/marco.pdf +0 -0
- package/dist/dependency-injection/dependency-injection.js +46 -0
- package/dist/digitalSignature/application/digitalSignature.useCase.js +180 -0
- package/dist/digitalSignature/domain/PDFArrayCustom.js +59 -0
- package/dist/digitalSignature/domain/SignPDF.js +100 -0
- package/dist/digitalSignature/infrastructure/routes/digitalSignature.routes.js +1 -0
- package/dist/documentos/application/documentos.useCase.js +49 -0
- package/dist/documentos/application/streamConversor.js +14 -0
- package/dist/documentos/domain/documento.class.js +60 -0
- package/dist/documentos/domain/documento.interface.js +2 -0
- package/dist/documentos/domain/documento.repository.js +2 -0
- package/dist/documentos/domain/documentoFTP.js +11 -0
- package/dist/documentos/domain/value-object/uuid.js +21 -0
- package/dist/documentos/infrastructure/repository/documentos.ftp.repository.js +172 -0
- package/dist/estados/application/flujos.useCase.js +21 -0
- package/dist/estados/domain/estado.class.js +150 -0
- package/dist/estados/domain/flujos.repository.js +2 -0
- package/dist/estados/infrastructure/controller/flujos.controller.js +34 -0
- package/dist/estados/infrastructure/repositories/flujos.sql.repository.js +36 -0
- package/dist/estados/infrastructure/routes/flujo.route.js +50 -0
- package/dist/expediente-electronico/application/expediente-electronico.useCase.js +171 -0
- package/dist/expediente-electronico/domain/expediente-electronico.class.js +190 -0
- package/dist/expediente-electronico/domain/expediente-electronico.interface.js +2 -0
- package/dist/expediente-electronico/domain/expediente-electronico.repository.js +2 -0
- package/dist/expediente-electronico/domain/value-object/limited-string.class.js +19 -0
- package/dist/expediente-electronico/domain/value-object/notas.class.js +41 -0
- package/dist/expediente-electronico/infrastructure/controller/expediente-electronico.controller.js +306 -0
- package/dist/expediente-electronico/infrastructure/repositories/expediente-electronico.sql.repository.js +775 -0
- package/dist/expediente-electronico/infrastructure/routes/expediente-electronico.route.js +46 -0
- package/dist/infrastructure/bd/connection.sql.js +64 -0
- package/dist/infrastructure/bd/pagination.sql.js +15 -0
- package/dist/infrastructure/docs/swagger.js +37 -0
- package/dist/infrastructure/fileServer/fileServer.basic-ftp.js +220 -0
- package/dist/infrastructure/fileServer/fileServer.connection.js +94 -0
- package/dist/infrastructure/middlewares/middleware.apikey.js +15 -0
- package/dist/infrastructure/middlewares/middleware.auth.js +372 -0
- package/dist/infrastructure/middlewares/middleware.deslogueo.js +1 -0
- package/dist/infrastructure/middlewares/middleware.validarCampos.js +15 -0
- package/dist/infrastructure/middlewares/middleware.validarRol.js +19 -0
- package/dist/infrastructure/middlewares/validarNivel.js +37 -0
- package/dist/infrastructure/server/httpsServer.class.js +59 -0
- package/dist/infrastructure/server/server.class.js +54 -0
- package/dist/infrastructure/socket/socketIO.js +23 -0
- package/dist/infrastructure/stream-handler/stream-handler.js +137 -0
- package/dist/notificaciones/domain/datosNotificacion.class.js +11 -0
- package/dist/notificaciones/domain/datosNotificacion.interface.js +2 -0
- package/dist/notificaciones/domain/notificacion.class.js +19 -0
- package/dist/notificaciones/domain/notificacion.interface.js +2 -0
- package/dist/notificaciones/domain/notificacion.repository.js +2 -0
- package/dist/notificaciones/infrastructure/notificacion.controller.js +31 -0
- package/dist/usuarios/application/usuarios.useCase.js +22 -0
- package/dist/usuarios/domain/usuario.class.js +24 -0
- package/dist/usuarios/domain/usuario.interface.js +2 -0
- package/dist/usuarios/domain/usuarios.repository.js +2 -0
- package/dist/usuarios/infrastructure/controller/usuarios.controller.js +28 -0
- package/dist/usuarios/infrastructure/repository/usuarios.sql.repository.js +17 -0
- package/dist/usuarios/infrastructure/routes/usuarios.routes.js +19 -0
- package/documentos/application/documentos.useCase.ts +41 -0
- package/documentos/domain/documento.class.ts +101 -0
- package/documentos/domain/documento.interface.ts +9 -0
- package/documentos/domain/documento.repository.ts +12 -0
- package/documentos/domain/documentoFTP.ts +17 -0
- package/documentos/domain/value-object/uuid.ts +23 -0
- package/documentos/infrastructure/repository/documentos.ftp.repository.ts +169 -0
- package/estados/application/flujos.useCase.ts +13 -0
- package/estados/domain/estado.class.ts +213 -0
- package/estados/domain/flujos.repository.ts +8 -0
- package/estados/infrastructure/controller/flujos.controller.ts +21 -0
- package/estados/infrastructure/repositories/flujos.sql.repository.ts +29 -0
- package/estados/infrastructure/routes/flujo.route.ts +56 -0
- package/expediente-electronico/application/expediente-electronico.useCase.ts +154 -0
- package/expediente-electronico/domain/expediente-electronico.class.ts +223 -0
- package/expediente-electronico/domain/expediente-electronico.interface.ts +19 -0
- package/expediente-electronico/domain/expediente-electronico.repository.ts +22 -0
- package/expediente-electronico/domain/value-object/limited-string.class.ts +19 -0
- package/expediente-electronico/domain/value-object/notas.class.ts +51 -0
- package/expediente-electronico/infrastructure/controller/expediente-electronico.controller.ts +308 -0
- package/expediente-electronico/infrastructure/repositories/expediente-electronico.sql.repository.ts +799 -0
- package/expediente-electronico/infrastructure/routes/expediente-electronico.route.ts +64 -0
- package/infrastructure/bd/connection.sql.ts +49 -0
- package/infrastructure/bd/pagination.sql.ts +11 -0
- package/infrastructure/docs/swagger.ts +38 -0
- package/infrastructure/fileServer/fileServer.basic-ftp.ts +196 -0
- package/infrastructure/fileServer/fileServer.connection.ts +78 -0
- package/infrastructure/middlewares/middleware.apikey.ts +17 -0
- package/infrastructure/middlewares/middleware.auth.ts +409 -0
- package/infrastructure/middlewares/middleware.deslogueo.ts +0 -0
- package/infrastructure/middlewares/middleware.validarCampos.ts +15 -0
- package/infrastructure/middlewares/middleware.validarRol.ts +15 -0
- package/infrastructure/middlewares/validarNivel.ts +37 -0
- package/infrastructure/server/httpsServer.class.ts +69 -0
- package/infrastructure/server/server.class.ts +66 -0
- package/infrastructure/socket/socketIO.ts +22 -0
- package/infrastructure/stream-handler/stream-handler.ts +161 -0
- package/jest.config.js +8 -0
- package/notificaciones/domain/datosNotificacion.class.ts +13 -0
- package/notificaciones/domain/datosNotificacion.interface.ts +5 -0
- package/notificaciones/domain/notificacion.class.ts +23 -0
- package/notificaciones/domain/notificacion.interface.ts +15 -0
- package/notificaciones/domain/notificacion.repository.ts +8 -0
- package/notificaciones/infrastructure/notificacion.controller.ts +16 -0
- package/package.json +42 -0
- package/script.js +135 -0
- package/test/expediente-electronico/domain/expediente-electronico.class.test.ts +186 -0
- package/tsconfig.json +73 -0
- package/usuarios/application/usuarios.useCase.ts +12 -0
- package/usuarios/domain/usuario.class.ts +40 -0
- package/usuarios/domain/usuario.interface.ts +18 -0
- package/usuarios/domain/usuarios.repository.ts +3 -0
- package/usuarios/infrastructure/controller/usuarios.controller.ts +19 -0
- package/usuarios/infrastructure/repository/usuarios.sql.repository.ts +19 -0
- package/usuarios/infrastructure/routes/usuarios.routes.ts +20 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { Request, Response } from "express";
|
|
2
|
+
import { Readable } from "stream";
|
|
3
|
+
import { Documento } from "../../documentos/domain/documento.class";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
export class DocumentStreamHandler {
|
|
7
|
+
static async sendDocumentStream(
|
|
8
|
+
req: Request,
|
|
9
|
+
res: Response,
|
|
10
|
+
archivoStream: Readable,
|
|
11
|
+
documento: Documento
|
|
12
|
+
) {
|
|
13
|
+
console.log(`[CONTROLLER] Stream obtenido, configurando headers: ${documento.uuid}`);
|
|
14
|
+
|
|
15
|
+
// Detectar MIME type y filename desde el objeto Documento
|
|
16
|
+
const mimeType = this.getMimeTypeFromDocumento(documento);
|
|
17
|
+
const filename = this.getFilenameFromDocumento(documento);
|
|
18
|
+
|
|
19
|
+
console.log(`[CONTROLLER] MIME Type detectado: ${mimeType}`);
|
|
20
|
+
console.log(`[CONTROLLER] Filename: ${filename}`);
|
|
21
|
+
|
|
22
|
+
// Codificamos el nombre UTF-8 para evitar los caracteres especiales
|
|
23
|
+
const safeName = encodeURIComponent(filename);
|
|
24
|
+
|
|
25
|
+
// Headers para visualización correcta
|
|
26
|
+
res.setHeader('Content-Type', mimeType);
|
|
27
|
+
res.setHeader('Content-Disposition', `inline; filename*=UTF-8''${safeName}`);
|
|
28
|
+
|
|
29
|
+
// Headers de cache más permisivos para visualización
|
|
30
|
+
res.setHeader('Cache-Control', 'public, max-age=3600'); // 1 hora de cache
|
|
31
|
+
res.setHeader('Accept-Ranges', 'bytes');
|
|
32
|
+
|
|
33
|
+
// Timeouts
|
|
34
|
+
req.setTimeout(600000);
|
|
35
|
+
res.setTimeout(600000);
|
|
36
|
+
|
|
37
|
+
console.log(`[CONTROLLER] Headers configurados para visualización`);
|
|
38
|
+
|
|
39
|
+
// Debugging
|
|
40
|
+
let bytesTransmitted = 0;
|
|
41
|
+
let chunkCount = 0;
|
|
42
|
+
|
|
43
|
+
archivoStream.on('data', (chunk: Buffer) => {
|
|
44
|
+
bytesTransmitted += chunk.length;
|
|
45
|
+
chunkCount++;
|
|
46
|
+
|
|
47
|
+
if (chunkCount % 100 === 0) {
|
|
48
|
+
console.log(`[CONTROLLER] Chunk ${chunkCount}: ${chunk.length} bytes (Total: ${bytesTransmitted} bytes)`);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
archivoStream.on('end', () => {
|
|
53
|
+
console.log(`[CONTROLLER] Stream completado exitosamente!`);
|
|
54
|
+
console.log(`[CONTROLLER] Total chunks: ${chunkCount}, Total bytes: ${bytesTransmitted}`);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
archivoStream.on('error', (error) => {
|
|
58
|
+
console.error(`[CONTROLLER] Error en stream:`, error);
|
|
59
|
+
if (!res.headersSent) {
|
|
60
|
+
res.status(500).json({ message: 'Error al transmitir archivo' });
|
|
61
|
+
} else {
|
|
62
|
+
res.end();
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Manejo de desconexión
|
|
67
|
+
req.on('close', () => {
|
|
68
|
+
console.log(`[CONTROLLER] Cliente desconectado: ${documento.uuid}`);
|
|
69
|
+
if (archivoStream && typeof archivoStream.destroy === 'function') {
|
|
70
|
+
archivoStream.destroy();
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
req.on('aborted', () => {
|
|
75
|
+
console.log(`[CONTROLLER] Request abortado: ${documento.uuid}`);
|
|
76
|
+
if (archivoStream && typeof archivoStream.destroy === 'function') {
|
|
77
|
+
archivoStream.destroy();
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
console.log(`[CONTROLLER] Iniciando transmisión: ${documento.uuid}`);
|
|
82
|
+
archivoStream.pipe(res);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private static getMimeTypeFromDocumento(documento: Documento): string {
|
|
86
|
+
// Extraer extensión del nombre del documento
|
|
87
|
+
const extension = documento.nombre ? documento.nombre.split('.').pop()?.toLowerCase() : 'pdf';
|
|
88
|
+
|
|
89
|
+
const mimeTypes: Record<string, string> = {
|
|
90
|
+
// Documentos
|
|
91
|
+
'pdf': 'application/pdf',
|
|
92
|
+
'doc': 'application/msword',
|
|
93
|
+
'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
94
|
+
'xls': 'application/vnd.ms-excel',
|
|
95
|
+
'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
96
|
+
'ppt': 'application/vnd.ms-powerpoint',
|
|
97
|
+
'pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
|
98
|
+
|
|
99
|
+
// Imágenes
|
|
100
|
+
'jpg': 'image/jpeg',
|
|
101
|
+
'jpeg': 'image/jpeg',
|
|
102
|
+
'png': 'image/png',
|
|
103
|
+
'gif': 'image/gif',
|
|
104
|
+
'bmp': 'image/bmp',
|
|
105
|
+
'webp': 'image/webp',
|
|
106
|
+
|
|
107
|
+
// Texto
|
|
108
|
+
'txt': 'text/plain',
|
|
109
|
+
'csv': 'text/csv',
|
|
110
|
+
'xml': 'application/xml',
|
|
111
|
+
'json': 'application/json',
|
|
112
|
+
|
|
113
|
+
// Comprimidos
|
|
114
|
+
'zip': 'application/zip',
|
|
115
|
+
'rar': 'application/x-rar-compressed',
|
|
116
|
+
'7z': 'application/x-7z-compressed',
|
|
117
|
+
|
|
118
|
+
// Audio/Video
|
|
119
|
+
'mp3': 'audio/mpeg',
|
|
120
|
+
'mp4': 'video/mp4',
|
|
121
|
+
'avi': 'video/x-msvideo'
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
return mimeTypes[extension || ''] || 'application/octet-stream';
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
private static getFilenameFromDocumento(documento: Documento): string {
|
|
128
|
+
// Si el nombre ya tiene extensión, usarlo directamente
|
|
129
|
+
if(!documento.nombre){
|
|
130
|
+
return documento.uuid;
|
|
131
|
+
}
|
|
132
|
+
if (documento.nombre.includes('.')) {
|
|
133
|
+
return documento.nombre;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Fallback: asumir que es PDF
|
|
137
|
+
return `${documento.nombre}.pdf`;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Método alternativo si quieres forzar descarga en lugar de visualización
|
|
141
|
+
static async downloadDocumentStream(
|
|
142
|
+
req: Request,
|
|
143
|
+
res: Response,
|
|
144
|
+
archivoStream: Readable,
|
|
145
|
+
documento: Documento
|
|
146
|
+
) {
|
|
147
|
+
const mimeType = this.getMimeTypeFromDocumento(documento);
|
|
148
|
+
const filename = this.getFilenameFromDocumento(documento);
|
|
149
|
+
|
|
150
|
+
// Codificamos el nombre UTF-8 para evitar los caracteres especiales
|
|
151
|
+
const safeName = encodeURIComponent(filename);
|
|
152
|
+
|
|
153
|
+
// Cambiar disposition a attachment para forzar descarga
|
|
154
|
+
res.setHeader('Content-Type', mimeType);
|
|
155
|
+
res.setHeader('Content-Disposition', `attachment; filename*=UTF-8''${safeName}`);
|
|
156
|
+
res.setHeader('Cache-Control', 'no-cache');
|
|
157
|
+
|
|
158
|
+
// Resto igual...
|
|
159
|
+
archivoStream.pipe(res);
|
|
160
|
+
}
|
|
161
|
+
}
|
package/jest.config.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { IDatosNotificacion } from "./datosNotificacion.interface";
|
|
2
|
+
|
|
3
|
+
export class DatosNotificacion implements IDatosNotificacion{
|
|
4
|
+
info?: string;
|
|
5
|
+
usuarioResponsable?: string;
|
|
6
|
+
icono?: string;
|
|
7
|
+
|
|
8
|
+
constructor(info?:string, usuario?:string, icono?:string){
|
|
9
|
+
this.info=info;
|
|
10
|
+
this.usuarioResponsable=usuario;
|
|
11
|
+
this.icono=icono;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import moment from "moment-timezone";
|
|
2
|
+
import { DatosNotificacion } from "./datosNotificacion.class";
|
|
3
|
+
import { IDatosNotificacion } from "./datosNotificacion.interface";
|
|
4
|
+
import { INotificacion } from "./notificacion.interface";
|
|
5
|
+
|
|
6
|
+
export class Notificacion implements INotificacion{
|
|
7
|
+
idNotificacion: string | undefined;
|
|
8
|
+
fecha: string;
|
|
9
|
+
unidadEmisora: string;
|
|
10
|
+
unidadReceptora: string;
|
|
11
|
+
descripcion: IDatosNotificacion;
|
|
12
|
+
lectores: string[];
|
|
13
|
+
idSolicitud?: string
|
|
14
|
+
|
|
15
|
+
constructor(unidadEmisora:string,unidadReceptora:string, info:string, usuario:string, icono:string, idSolicitud?:string){
|
|
16
|
+
const fecha = moment().tz('America/Argentina/Buenos_Aires').locale('es').toISOString();
|
|
17
|
+
this.unidadEmisora=unidadEmisora;
|
|
18
|
+
this.unidadReceptora=unidadReceptora;
|
|
19
|
+
this.descripcion=new DatosNotificacion(info, usuario, icono);
|
|
20
|
+
this.lectores=[];
|
|
21
|
+
this.idSolicitud = idSolicitud
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { IDatosNotificacion } from "./datosNotificacion.interface";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export interface INotificacion{
|
|
5
|
+
idNotificacion:string | undefined;
|
|
6
|
+
fecha: string;
|
|
7
|
+
unidadEmisora: string;
|
|
8
|
+
unidadReceptora: string;
|
|
9
|
+
descripcion: IDatosNotificacion;
|
|
10
|
+
/**
|
|
11
|
+
* @param lectores arreglo de usuarios que leyeron la notificacion.
|
|
12
|
+
*/
|
|
13
|
+
lectores: string[];
|
|
14
|
+
idSolicitud?: string;
|
|
15
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { INotificacion } from "./notificacion.interface";
|
|
2
|
+
|
|
3
|
+
export interface INotificacionRepository{
|
|
4
|
+
insert(notificacion:INotificacion):Promise<any>;
|
|
5
|
+
seleinsertctByUnidad(unidades:string[]):Promise<any>;
|
|
6
|
+
updateLectores(idNotificacion: string, notificacion:INotificacion):Promise<INotificacion>;
|
|
7
|
+
selectNotificacionById(idNotificacion:string):Promise<INotificacion>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
import { Notificacion } from "../domain/notificacion.class"
|
|
3
|
+
|
|
4
|
+
export class NotificacionController{
|
|
5
|
+
|
|
6
|
+
constructor(){}
|
|
7
|
+
|
|
8
|
+
guardarNotificacion = async(unidadEmisora,unidadReceptora, info, usuario, icono, codigoInterno?) => {
|
|
9
|
+
try {
|
|
10
|
+
let notificacion = new Notificacion(unidadEmisora,unidadReceptora, info, usuario, icono, codigoInterno);
|
|
11
|
+
await axios.post(`${process.env.URL_SERVE}/notificaciones/guardar`, notificacion);
|
|
12
|
+
} catch (error:any) {
|
|
13
|
+
console.error("Error NotificacionesController.guardarNotificacion=>", error);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "fpavon-ee-shared",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Carpeta compartida entre servicios de Expediente Electronio",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "tsc"
|
|
8
|
+
},
|
|
9
|
+
"author": "",
|
|
10
|
+
"license": "ISC",
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"axios": "^1.6.7",
|
|
13
|
+
"basic-ftp": "^5.0.5",
|
|
14
|
+
"cors": "^2.8.5",
|
|
15
|
+
"express": "^4.18.2",
|
|
16
|
+
"express-validator": "^7.0.1",
|
|
17
|
+
"form-data": "^4.0.0",
|
|
18
|
+
"fs-extra": "^11.2.0",
|
|
19
|
+
"http": "^0.0.1-security",
|
|
20
|
+
"jsonwebtoken": "^9.0.2",
|
|
21
|
+
"moment": "^2.30.1",
|
|
22
|
+
"morgan-body": "^2.6.9",
|
|
23
|
+
"mssql": "^10.0.2",
|
|
24
|
+
"multiparty": "^4.2.3",
|
|
25
|
+
"node-cron": "^3.0.3",
|
|
26
|
+
"node-dependency-injection": "^3.1.2",
|
|
27
|
+
"node-schedule": "^2.1.1",
|
|
28
|
+
"node-signpdf": "^3.0.0",
|
|
29
|
+
"pdf-lib": "^1.17.1",
|
|
30
|
+
"pdf-merger-js": "^5.1.1",
|
|
31
|
+
"socket.io-client": "^4.7.4",
|
|
32
|
+
"stream-buffers": "^3.0.3",
|
|
33
|
+
"swagger-jsdoc": "^6.2.8",
|
|
34
|
+
"swagger-ui-express": "^5.0.0",
|
|
35
|
+
"ts-jest": "^29.1.2",
|
|
36
|
+
"typescript": "^5.3.3"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@types/jest": "^29.5.12",
|
|
40
|
+
"jest": "^29.7.0"
|
|
41
|
+
}
|
|
42
|
+
}
|
package/script.js
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
const [param1] = process.argv.slice(2);
|
|
5
|
+
|
|
6
|
+
if (param1) {
|
|
7
|
+
const mainFolderPath = path.join(param1);
|
|
8
|
+
|
|
9
|
+
if (!fs.existsSync(mainFolderPath)) {
|
|
10
|
+
// Crear la carpeta principal
|
|
11
|
+
fs.mkdirSync(mainFolderPath, { recursive: true });
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
// Crear subcarpetas dentro de la carpeta principal
|
|
16
|
+
const subfolders = [
|
|
17
|
+
"application",
|
|
18
|
+
"domain",
|
|
19
|
+
"infrastructure",
|
|
20
|
+
"infrastructure/controller",
|
|
21
|
+
"infrastructure/routes",
|
|
22
|
+
"infrastructure/repositories"
|
|
23
|
+
];
|
|
24
|
+
subfolders.forEach(folder => {
|
|
25
|
+
fs.mkdirSync(path.join(mainFolderPath, folder));
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
prepararDomain(mainFolderPath);
|
|
29
|
+
prepararApplication(mainFolderPath);
|
|
30
|
+
prepararInfrastructure(mainFolderPath);
|
|
31
|
+
printDependencyInjection();
|
|
32
|
+
console.log(`Se creo correctamente la carpeta ${param1}`);
|
|
33
|
+
} else {
|
|
34
|
+
console.log(`The folder ${mainFolderPath} already exists. No changes made.`);
|
|
35
|
+
}
|
|
36
|
+
} else {
|
|
37
|
+
console.log("Invalid command. Usage: node createProject.js <param1>");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
function prepararDomain(mainFolderPath){
|
|
42
|
+
// Crear la clase dentro de la carpeta domain
|
|
43
|
+
const classFilePath = path.join(mainFolderPath, 'domain', `${param1}.class.ts`);
|
|
44
|
+
const className = `${param1.charAt(0).toUpperCase() + param1.slice(1)}`;
|
|
45
|
+
const classContent = `import { I${className} } from './${param1}.interface'
|
|
46
|
+
export class ${className} implements I${className} {
|
|
47
|
+
constructor() {
|
|
48
|
+
// Constructor
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Methods
|
|
52
|
+
}
|
|
53
|
+
`;
|
|
54
|
+
|
|
55
|
+
fs.writeFileSync(classFilePath, classContent);
|
|
56
|
+
|
|
57
|
+
// Crear la interfaz dentro de la carpeta domain
|
|
58
|
+
const interfaceFilePath = path.join(mainFolderPath, 'domain', `${param1}.interface.ts`);
|
|
59
|
+
const interfaceName = `I${className}`;
|
|
60
|
+
const interfaceContent = `export interface ${interfaceName} {
|
|
61
|
+
// Interface properties
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
`;
|
|
65
|
+
|
|
66
|
+
fs.writeFileSync(interfaceFilePath, interfaceContent);
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
// Crear la interfaz dentro de la carpeta domain
|
|
70
|
+
const repoFilePath = path.join(mainFolderPath, 'domain', `${param1}.repository.ts`);
|
|
71
|
+
const repoName = `I${className}Repository`;
|
|
72
|
+
const repoContent = `export interface ${repoName} {
|
|
73
|
+
// Interface properties
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
`;
|
|
77
|
+
|
|
78
|
+
fs.writeFileSync(repoFilePath, repoContent);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function prepararInfrastructure(mainFolderPath){
|
|
82
|
+
|
|
83
|
+
const classFilePath = path.join(mainFolderPath, 'infrastructure/controller', `${param1}.controller.ts`);
|
|
84
|
+
const className = `${param1.charAt(0).toUpperCase() + param1.slice(1)}`;
|
|
85
|
+
const classContent = `import { ${className}UseCase } from '../../application/${param1}.useCase'
|
|
86
|
+
export class ${className}Controller {
|
|
87
|
+
constructor(private readonly ${param1}UseCase: ${className}UseCase) {
|
|
88
|
+
// Constructor
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Methods
|
|
92
|
+
}
|
|
93
|
+
`;
|
|
94
|
+
fs.writeFileSync(classFilePath, classContent);
|
|
95
|
+
|
|
96
|
+
const sqlRepositoryFilePath = path.join(mainFolderPath, 'infrastructure/repositories', `${param1}.sql.repository.ts`);
|
|
97
|
+
const sqlRepositoryContent = `import { I${className}Repository } from '../../domain/${param1}.repository'
|
|
98
|
+
export class ${className}SqlRepository implements I${className}Repository{
|
|
99
|
+
//debe implementar la interfaz de repository
|
|
100
|
+
}
|
|
101
|
+
`;
|
|
102
|
+
fs.writeFileSync(sqlRepositoryFilePath, sqlRepositoryContent);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function prepararApplication(mainFolderPath){
|
|
106
|
+
|
|
107
|
+
const classFilePath = path.join(mainFolderPath, 'application', `${param1}.useCase.ts`);
|
|
108
|
+
const className = `${param1.charAt(0).toUpperCase() + param1.slice(1)}`;
|
|
109
|
+
const classContent = `import { I${className}Repository } from '../domain/${param1}.repository';
|
|
110
|
+
export class ${className}UseCase {
|
|
111
|
+
constructor(private readonly ${param1}Repository: I${className}Repository) {
|
|
112
|
+
// Constructor
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Methods
|
|
116
|
+
}
|
|
117
|
+
`;
|
|
118
|
+
|
|
119
|
+
fs.writeFileSync(classFilePath, classContent);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
function printDependencyInjection(){
|
|
124
|
+
const name = `${param1.charAt(0).toUpperCase() + param1.slice(1)}`;
|
|
125
|
+
const content = `
|
|
126
|
+
container.register('EE.${name}.infrastructure.${name}Repository', ${name}Repository);
|
|
127
|
+
const ${name}Repo = container.get('EE.${name}.infrastructure.${name}Repository');
|
|
128
|
+
container.register('EE.${name}.application.${name}UseCase', ${name}UseCase).addArgument(${name}Repo);
|
|
129
|
+
const ${name}UseCase = container.get('EE.${name}.application.${name}UseCase');
|
|
130
|
+
container.register('EE.${name}.infrastructure.${name}Controller', ${name}Controller).addArgument(${name}UseCase);
|
|
131
|
+
const ${name}Controller = container.get('EE.${name}.infrastructure.${name}Controller');
|
|
132
|
+
`;
|
|
133
|
+
console.log("Dependency injection: ", content);
|
|
134
|
+
|
|
135
|
+
}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { Documento } from '../../../documentos/domain/documento.class';
|
|
2
|
+
import { UUID } from '../../../documentos/domain/value-object/uuid';
|
|
3
|
+
import { Estado } from '../../../estados/domain/estado.class';
|
|
4
|
+
import { ExpedienteElectronico } from '../../../expediente-electronico/domain/expediente-electronico.class';
|
|
5
|
+
import { expect, jest, test, describe, beforeEach, afterEach } from '@jest/globals';
|
|
6
|
+
|
|
7
|
+
describe('class ExpedienteElectronico', () => {
|
|
8
|
+
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
test('Debe crear correctamente un ExpedienteElectronico', async () => {
|
|
14
|
+
const params = {
|
|
15
|
+
id: 1,
|
|
16
|
+
fechaAlta: new Date(),
|
|
17
|
+
fechaCierre: new Date(),
|
|
18
|
+
usuarioResponsable: {
|
|
19
|
+
uid: 'p001101',
|
|
20
|
+
nivel: ['NIVEL1', 'operador_REQ'],
|
|
21
|
+
nivelNumero: 1,
|
|
22
|
+
nombreCompleto: 'Fabian, Peralta',
|
|
23
|
+
cargo: 'ANALISTA',
|
|
24
|
+
unidad: '1238',
|
|
25
|
+
unidadSuperior: '1200',
|
|
26
|
+
gerencia: '1187',
|
|
27
|
+
nombreUnidad: 'Proyectos de desarrollo interno - 1238',
|
|
28
|
+
nombreGerencia: 'DESARROLLO DE SISTEMAS',
|
|
29
|
+
roles: ['consultar', 'crear'],
|
|
30
|
+
grupos: ['REQ']
|
|
31
|
+
},
|
|
32
|
+
titulo: 'Ejemplo de título',
|
|
33
|
+
descripcion: 'Ejemplo de descripción',
|
|
34
|
+
tipo: 'Ejemplo de tipo',
|
|
35
|
+
bitacora: [],
|
|
36
|
+
documentos: [new Documento(new UUID().getValue(),'nombreDoc', 'descripcion', '10')],
|
|
37
|
+
origen: '1234',
|
|
38
|
+
destino: '5678',
|
|
39
|
+
estado: Estado.estadoPorDefault()
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
const ee = new ExpedienteElectronico(params)
|
|
44
|
+
expect(ee).toBeInstanceOf(ExpedienteElectronico);
|
|
45
|
+
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('Debe intentar crear un Expediente sin parametros y fallar', async () => {
|
|
49
|
+
const params = {};
|
|
50
|
+
expect(() => new ExpedienteElectronico(params)).toThrow();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test('Debe intentar crear un Expediente con documentos = string y fallar', async () => {
|
|
54
|
+
const params = {
|
|
55
|
+
id: 1,
|
|
56
|
+
fechaAlta: new Date(),
|
|
57
|
+
fechaCierre: new Date(),
|
|
58
|
+
usuarioResponsable: {
|
|
59
|
+
uid: 'p001101',
|
|
60
|
+
nivel: ['NIVEL1', 'operador_REQ'],
|
|
61
|
+
nivelNumero: 1,
|
|
62
|
+
nombreCompleto: 'Fabian, Peralta',
|
|
63
|
+
cargo: 'ANALISTA',
|
|
64
|
+
unidad: '1238',
|
|
65
|
+
unidadSuperior: '1200',
|
|
66
|
+
gerencia: '1187',
|
|
67
|
+
nombreUnidad: 'Proyectos de desarrollo interno - 1238',
|
|
68
|
+
nombreGerencia: 'DESARROLLO DE SISTEMAS',
|
|
69
|
+
roles: ['consultar', 'crear'],
|
|
70
|
+
grupos: ['REQ']
|
|
71
|
+
},
|
|
72
|
+
titulo: 'Ejemplo de título',
|
|
73
|
+
descripcion: 'Ejemplo de descripción',
|
|
74
|
+
tipo: 'Ejemplo de tipo',
|
|
75
|
+
bitacora: [],
|
|
76
|
+
documentos: 'documentos',
|
|
77
|
+
origen: '1234',
|
|
78
|
+
destino: '5678',
|
|
79
|
+
estado: Estado.estadoPorDefault()
|
|
80
|
+
};
|
|
81
|
+
expect(() => new ExpedienteElectronico(params)).toThrow(new Error('El atributo documentos debe ser un array'));
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test('Debe intentar crear un Expediente con documentos = string[] y fallar', async () => {
|
|
85
|
+
const params = {
|
|
86
|
+
id: 1,
|
|
87
|
+
fechaAlta: new Date(),
|
|
88
|
+
fechaCierre: new Date(),
|
|
89
|
+
usuarioResponsable: {
|
|
90
|
+
uid: 'p001101',
|
|
91
|
+
nivel: ['NIVEL1', 'operador_REQ'],
|
|
92
|
+
nivelNumero: 1,
|
|
93
|
+
nombreCompleto: 'Fabian, Peralta',
|
|
94
|
+
cargo: 'ANALISTA',
|
|
95
|
+
unidad: '1238',
|
|
96
|
+
unidadSuperior: '1200',
|
|
97
|
+
gerencia: '1187',
|
|
98
|
+
nombreUnidad: 'Proyectos de desarrollo interno - 1238',
|
|
99
|
+
nombreGerencia: 'DESARROLLO DE SISTEMAS',
|
|
100
|
+
roles: ['consultar', 'crear'],
|
|
101
|
+
grupos: ['REQ']
|
|
102
|
+
},
|
|
103
|
+
titulo: 'Ejemplo de título',
|
|
104
|
+
descripcion: 'Ejemplo de descripción',
|
|
105
|
+
tipo: 'Ejemplo de tipo',
|
|
106
|
+
bitacora: [],
|
|
107
|
+
documentos: ['documentos'],
|
|
108
|
+
origen: '1234',
|
|
109
|
+
destino: '5678',
|
|
110
|
+
estado: Estado.estadoPorDefault()
|
|
111
|
+
};
|
|
112
|
+
expect(() => new ExpedienteElectronico(params)).toThrow(new Error('El atributo documentos debe ser un array de objetos de tipo Documento'));
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test('Debe intentar crear un Expediente con documentos = []', async () => {
|
|
116
|
+
const params = {
|
|
117
|
+
id: 1,
|
|
118
|
+
fechaAlta: new Date(),
|
|
119
|
+
fechaCierre: new Date(),
|
|
120
|
+
usuarioResponsable: {
|
|
121
|
+
uid: 'p001101',
|
|
122
|
+
nivel: ['NIVEL1', 'operador_REQ'],
|
|
123
|
+
nivelNumero: 1,
|
|
124
|
+
nombreCompleto: 'Fabian, Peralta',
|
|
125
|
+
cargo: 'ANALISTA',
|
|
126
|
+
unidad: '1238',
|
|
127
|
+
unidadSuperior: '1200',
|
|
128
|
+
gerencia: '1187',
|
|
129
|
+
nombreUnidad: 'Proyectos de desarrollo interno - 1238',
|
|
130
|
+
nombreGerencia: 'DESARROLLO DE SISTEMAS',
|
|
131
|
+
roles: ['consultar', 'crear'],
|
|
132
|
+
grupos: ['REQ']
|
|
133
|
+
},
|
|
134
|
+
titulo: 'Ejemplo de título',
|
|
135
|
+
descripcion: 'Ejemplo de descripción',
|
|
136
|
+
tipo: 'Ejemplo de tipo',
|
|
137
|
+
bitacora: [],
|
|
138
|
+
documentos: [],
|
|
139
|
+
origen: '1234',
|
|
140
|
+
destino: '5678',
|
|
141
|
+
estado: Estado.estadoPorDefault()
|
|
142
|
+
};
|
|
143
|
+
const ee = new ExpedienteElectronico(params);
|
|
144
|
+
expect(ee).toBeInstanceOf(ExpedienteElectronico);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
test('Debe crear un Expediente con documentos vacios y luego asignarle uno valido con el setter', async () => {
|
|
148
|
+
const params = {
|
|
149
|
+
id: 1,
|
|
150
|
+
fechaAlta: new Date(),
|
|
151
|
+
fechaCierre: new Date(),
|
|
152
|
+
usuarioResponsable: {
|
|
153
|
+
uid: 'p001101',
|
|
154
|
+
nivel: ['NIVEL1', 'operador_REQ'],
|
|
155
|
+
nivelNumero: 1,
|
|
156
|
+
nombreCompleto: 'Fabian, Peralta',
|
|
157
|
+
cargo: 'ANALISTA',
|
|
158
|
+
unidad: '1238',
|
|
159
|
+
unidadSuperior: '1200',
|
|
160
|
+
gerencia: '1187',
|
|
161
|
+
nombreUnidad: 'Proyectos de desarrollo interno - 1238',
|
|
162
|
+
nombreGerencia: 'DESARROLLO DE SISTEMAS',
|
|
163
|
+
roles: ['consultar', 'crear'],
|
|
164
|
+
grupos: ['REQ']
|
|
165
|
+
},
|
|
166
|
+
titulo: 'Ejemplo de título',
|
|
167
|
+
descripcion: 'Ejemplo de descripción',
|
|
168
|
+
tipo: 'Ejemplo de tipo',
|
|
169
|
+
bitacora: [],
|
|
170
|
+
documentos: [],
|
|
171
|
+
origen: '1234',
|
|
172
|
+
destino: '5678',
|
|
173
|
+
estado: Estado.estadoPorDefault()
|
|
174
|
+
};
|
|
175
|
+
const ee = new ExpedienteElectronico(params);
|
|
176
|
+
const doc = new Documento('','nombreDoc', 'descripcion', '10')
|
|
177
|
+
const docs:Documento[] = [new Documento('','nombreDoc', 'descripcion', '10')];
|
|
178
|
+
ee.setDocumentos(docs);
|
|
179
|
+
const a = ee.getDocumentos();
|
|
180
|
+
const uuid = new UUID().getValue();
|
|
181
|
+
console.log("uuid: ", uuid);
|
|
182
|
+
UUID.validate(uuid)
|
|
183
|
+
|
|
184
|
+
expect(a).toEqual(docs);
|
|
185
|
+
});
|
|
186
|
+
});
|