jerkjs 2.5.2 → 2.5.4
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/@qaLoadModel/controllers/ProductController.js +143 -0
- package/@qaLoadModel/controllers/UserController.js +143 -0
- package/@qaLoadModel/models/ProductModel.js +41 -0
- package/@qaLoadModel/models/UserModel.js +41 -0
- package/@qaLoadModel/package.json +22 -0
- package/@qaLoadModel/qa_report.md +71 -0
- package/@qaLoadModel/results.md +97 -0
- package/@qaLoadModel/routes.json +58 -0
- package/@qaLoadModel/server.js +43 -0
- package/@qaLoadModel/simple-test.js +96 -0
- package/@qaLoadModel/test-models.js +144 -0
- package/@qaLoadModel/test_endpoints.sh +35 -0
- package/@qaLoadModel/test_final.js +89 -0
- package/@qaLoadModel/views/products/index.html +45 -0
- package/@qaLoadModel/views/products/show.html +27 -0
- package/@qaLoadModel/views/users/index.html +44 -0
- package/@qaLoadModel/views/users/show.html +26 -0
- package/CHANGELOG.md +73 -141
- package/README.md +1 -1
- package/auditoria_jerkjs.md +91 -0
- package/doc2.5.3/manual-mvc-completo.md +934 -0
- package/docs/MANUAL_CONTROLLER_VIEW_MODEL.md +310 -0
- package/lib/core/server.js +20 -19
- package/lib/mvc/controllerBase.js +100 -32
- package/lib/router/RouteMatcher.js +45 -10
- package/package.json +13 -5
- package/qa/INFORME_QA_JERKJS_ROUTING.md +108 -0
- package/qa-app/controllers/homeController.js +9 -0
- package/qa-app/controllers/userController.js +76 -0
- package/qa-app/hooks-config.js +65 -0
- package/qa-app/models/UserModel.js +36 -0
- package/qa-app/package-lock.json +1683 -0
- package/qa-app/package.json +25 -0
- package/qa-app/public/css/style.css +15 -0
- package/qa-app/public/images/logo.png +3 -0
- package/qa-app/public/index.html +15 -0
- package/qa-app/public/js/main.js +7 -0
- package/qa-app/routes/api-routes.json +23 -0
- package/qa-app/routes/page-routes.json +16 -0
- package/qa-app/routes/static-routes.json +20 -0
- package/qa-app/server.js +68 -0
- package/qa-app/views/footer.html +3 -0
- package/qa-app/views/index.html +20 -0
- package/qa-app/views/users.html +20 -0
- package/example-directory-loader.js +0 -46
- package/examples/examples.arj +0 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
// controllers/ProductController.js
|
|
2
|
+
const { ControllerBase } = require('../../index.js');
|
|
3
|
+
|
|
4
|
+
class ProductController extends ControllerBase {
|
|
5
|
+
constructor() {
|
|
6
|
+
super();
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// Método para mostrar la lista de productos
|
|
10
|
+
async index(req, res) {
|
|
11
|
+
try {
|
|
12
|
+
// Obtener el adaptador desde el modelManager en la solicitud
|
|
13
|
+
const adapter = req.modelManager?.getAdapter('memory') || null;
|
|
14
|
+
|
|
15
|
+
// Cargar el modelo de productos con el adaptador
|
|
16
|
+
const productModel = await this.loadModel('ProductModel', {
|
|
17
|
+
adapter: adapter
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// Obtener todos los productos
|
|
21
|
+
const products = await productModel.getAllProducts();
|
|
22
|
+
|
|
23
|
+
// Renderizar la vista con los datos
|
|
24
|
+
res.render('products/index', {
|
|
25
|
+
title: 'Lista de Productos',
|
|
26
|
+
products: products,
|
|
27
|
+
message: 'Productos disponibles en el sistema'
|
|
28
|
+
});
|
|
29
|
+
} catch (error) {
|
|
30
|
+
console.error('Error en ProductController.index:', error);
|
|
31
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
32
|
+
res.end(JSON.stringify({ error: 'Error interno del servidor' }));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Método para mostrar un producto específico
|
|
37
|
+
async show(req, res) {
|
|
38
|
+
try {
|
|
39
|
+
// Obtener el adaptador desde el modelManager en la solicitud
|
|
40
|
+
const adapter = req.modelManager?.getAdapter('memory') || null;
|
|
41
|
+
|
|
42
|
+
// Cargar el modelo de productos con el adaptador
|
|
43
|
+
const productModel = await this.loadModel('ProductModel', {
|
|
44
|
+
adapter: adapter
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// Obtener el ID de los parámetros
|
|
48
|
+
const id = req.params.id;
|
|
49
|
+
|
|
50
|
+
// Obtener el producto específico
|
|
51
|
+
const product = await productModel.getProductById(id);
|
|
52
|
+
|
|
53
|
+
if (!product) {
|
|
54
|
+
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
55
|
+
res.end(JSON.stringify({ error: 'Producto no encontrado' }));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Renderizar la vista con los datos
|
|
60
|
+
res.render('products/show', {
|
|
61
|
+
title: `Producto #${id}`,
|
|
62
|
+
product: product
|
|
63
|
+
});
|
|
64
|
+
} catch (error) {
|
|
65
|
+
console.error('Error en ProductController.show:', error);
|
|
66
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
67
|
+
res.end(JSON.stringify({ error: 'Error interno del servidor' }));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Método para crear un nuevo producto
|
|
72
|
+
async create(req, res) {
|
|
73
|
+
try {
|
|
74
|
+
// Obtener el adaptador desde el modelManager en la solicitud
|
|
75
|
+
const adapter = req.modelManager?.getAdapter('memory') || null;
|
|
76
|
+
|
|
77
|
+
// Cargar el modelo de productos con el adaptador
|
|
78
|
+
const productModel = await this.loadModel('ProductModel', {
|
|
79
|
+
adapter: adapter
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// Obtener los datos del cuerpo de la solicitud
|
|
83
|
+
const productData = req.body;
|
|
84
|
+
|
|
85
|
+
// Crear el nuevo producto
|
|
86
|
+
const productId = await productModel.createProduct(productData);
|
|
87
|
+
|
|
88
|
+
// Responder con éxito
|
|
89
|
+
res.writeHead(201, { 'Content-Type': 'application/json' });
|
|
90
|
+
res.end(JSON.stringify({
|
|
91
|
+
success: true,
|
|
92
|
+
id: productId,
|
|
93
|
+
message: 'Producto creado exitosamente'
|
|
94
|
+
}));
|
|
95
|
+
} catch (error) {
|
|
96
|
+
console.error('Error en ProductController.create:', error);
|
|
97
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
98
|
+
res.end(JSON.stringify({ error: 'Error interno del servidor' }));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Método para buscar productos por categoría
|
|
103
|
+
async searchByCategory(req, res) {
|
|
104
|
+
try {
|
|
105
|
+
// Obtener el adaptador desde el modelManager en la solicitud
|
|
106
|
+
const adapter = req.modelManager?.getAdapter('memory') || null;
|
|
107
|
+
|
|
108
|
+
// Cargar el modelo de productos con el adaptador
|
|
109
|
+
const productModel = await this.loadModel('ProductModel', {
|
|
110
|
+
adapter: adapter
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// Obtener la categoría de los parámetros de consulta
|
|
114
|
+
const category = req.query.category || '';
|
|
115
|
+
|
|
116
|
+
// Buscar productos por categoría
|
|
117
|
+
const products = await productModel.getProductsByCategory(category);
|
|
118
|
+
|
|
119
|
+
// Responder con los resultados
|
|
120
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
121
|
+
res.end(JSON.stringify({
|
|
122
|
+
success: true,
|
|
123
|
+
results: products,
|
|
124
|
+
count: products.length
|
|
125
|
+
}));
|
|
126
|
+
} catch (error) {
|
|
127
|
+
console.error('Error en ProductController.searchByCategory:', error);
|
|
128
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
129
|
+
res.end(JSON.stringify({ error: 'Error interno del servidor' }));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Crear instancia del controlador
|
|
135
|
+
const productController = new ProductController();
|
|
136
|
+
|
|
137
|
+
// Preservar el contexto 'this' para cada método
|
|
138
|
+
productController.index = productController.index.bind(productController);
|
|
139
|
+
productController.show = productController.show.bind(productController);
|
|
140
|
+
productController.create = productController.create.bind(productController);
|
|
141
|
+
productController.searchByCategory = productController.searchByCategory.bind(productController);
|
|
142
|
+
|
|
143
|
+
module.exports = productController;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
// controllers/UserController.js
|
|
2
|
+
const { ControllerBase } = require('../../index.js');
|
|
3
|
+
|
|
4
|
+
class UserController extends ControllerBase {
|
|
5
|
+
constructor() {
|
|
6
|
+
super();
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// Método para mostrar la lista de usuarios
|
|
10
|
+
async index(req, res) {
|
|
11
|
+
try {
|
|
12
|
+
// Obtener el adaptador desde el modelManager en la solicitud
|
|
13
|
+
const adapter = req.modelManager?.getAdapter('memory') || null;
|
|
14
|
+
|
|
15
|
+
// Cargar el modelo de usuarios con el adaptador
|
|
16
|
+
const userModel = await this.loadModel('UserModel', {
|
|
17
|
+
adapter: adapter
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// Obtener todos los usuarios
|
|
21
|
+
const users = await userModel.getAllUsers();
|
|
22
|
+
|
|
23
|
+
// Renderizar la vista con los datos
|
|
24
|
+
res.render('users/index', {
|
|
25
|
+
title: 'Lista de Usuarios',
|
|
26
|
+
users: users,
|
|
27
|
+
message: 'Usuarios registrados en el sistema'
|
|
28
|
+
});
|
|
29
|
+
} catch (error) {
|
|
30
|
+
console.error('Error en UserController.index:', error);
|
|
31
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
32
|
+
res.end(JSON.stringify({ error: 'Error interno del servidor' }));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Método para mostrar un usuario específico
|
|
37
|
+
async show(req, res) {
|
|
38
|
+
try {
|
|
39
|
+
// Obtener el adaptador desde el modelManager en la solicitud
|
|
40
|
+
const adapter = req.modelManager?.getAdapter('memory') || null;
|
|
41
|
+
|
|
42
|
+
// Cargar el modelo de usuarios con el adaptador
|
|
43
|
+
const userModel = await this.loadModel('UserModel', {
|
|
44
|
+
adapter: adapter
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// Obtener el ID de los parámetros
|
|
48
|
+
const id = req.params.id;
|
|
49
|
+
|
|
50
|
+
// Obtener el usuario específico
|
|
51
|
+
const user = await userModel.getUserById(id);
|
|
52
|
+
|
|
53
|
+
if (!user) {
|
|
54
|
+
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
55
|
+
res.end(JSON.stringify({ error: 'Usuario no encontrado' }));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Renderizar la vista con los datos
|
|
60
|
+
res.render('users/show', {
|
|
61
|
+
title: `Usuario #${id}`,
|
|
62
|
+
user: user
|
|
63
|
+
});
|
|
64
|
+
} catch (error) {
|
|
65
|
+
console.error('Error en UserController.show:', error);
|
|
66
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
67
|
+
res.end(JSON.stringify({ error: 'Error interno del servidor' }));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Método para crear un nuevo usuario
|
|
72
|
+
async create(req, res) {
|
|
73
|
+
try {
|
|
74
|
+
// Obtener el adaptador desde el modelManager en la solicitud
|
|
75
|
+
const adapter = req.modelManager?.getAdapter('memory') || null;
|
|
76
|
+
|
|
77
|
+
// Cargar el modelo de usuarios con el adaptador
|
|
78
|
+
const userModel = await this.loadModel('UserModel', {
|
|
79
|
+
adapter: adapter
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// Obtener los datos del cuerpo de la solicitud
|
|
83
|
+
const userData = req.body;
|
|
84
|
+
|
|
85
|
+
// Crear el nuevo usuario
|
|
86
|
+
const userId = await userModel.createUser(userData);
|
|
87
|
+
|
|
88
|
+
// Responder con éxito
|
|
89
|
+
res.writeHead(201, { 'Content-Type': 'application/json' });
|
|
90
|
+
res.end(JSON.stringify({
|
|
91
|
+
success: true,
|
|
92
|
+
id: userId,
|
|
93
|
+
message: 'Usuario creado exitosamente'
|
|
94
|
+
}));
|
|
95
|
+
} catch (error) {
|
|
96
|
+
console.error('Error en UserController.create:', error);
|
|
97
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
98
|
+
res.end(JSON.stringify({ error: 'Error interno del servidor' }));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Método para buscar usuarios por nombre
|
|
103
|
+
async search(req, res) {
|
|
104
|
+
try {
|
|
105
|
+
// Obtener el adaptador desde el modelManager en la solicitud
|
|
106
|
+
const adapter = req.modelManager?.getAdapter('memory') || null;
|
|
107
|
+
|
|
108
|
+
// Cargar el modelo de usuarios con el adaptador
|
|
109
|
+
const userModel = await this.loadModel('UserModel', {
|
|
110
|
+
adapter: adapter
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// Obtener el término de búsqueda de los parámetros de consulta
|
|
114
|
+
const name = req.query.name || '';
|
|
115
|
+
|
|
116
|
+
// Buscar usuarios por nombre
|
|
117
|
+
const users = await userModel.getUsersByName(name);
|
|
118
|
+
|
|
119
|
+
// Responder con los resultados
|
|
120
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
121
|
+
res.end(JSON.stringify({
|
|
122
|
+
success: true,
|
|
123
|
+
results: users,
|
|
124
|
+
count: users.length
|
|
125
|
+
}));
|
|
126
|
+
} catch (error) {
|
|
127
|
+
console.error('Error en UserController.search:', error);
|
|
128
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
129
|
+
res.end(JSON.stringify({ error: 'Error interno del servidor' }));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Crear instancia del controlador
|
|
135
|
+
const userController = new UserController();
|
|
136
|
+
|
|
137
|
+
// Preservar el contexto 'this' para cada método
|
|
138
|
+
userController.index = userController.index.bind(userController);
|
|
139
|
+
userController.show = userController.show.bind(userController);
|
|
140
|
+
userController.create = userController.create.bind(userController);
|
|
141
|
+
userController.search = userController.search.bind(userController);
|
|
142
|
+
|
|
143
|
+
module.exports = userController;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// models/ProductModel.js
|
|
2
|
+
const { ModelBase } = require('../../index.js');
|
|
3
|
+
|
|
4
|
+
class ProductModel extends ModelBase {
|
|
5
|
+
constructor(options = {}) {
|
|
6
|
+
super(options);
|
|
7
|
+
this.tableName = 'products';
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Método para obtener todos los productos
|
|
11
|
+
async getAllProducts() {
|
|
12
|
+
return await this.find({}, { orderBy: 'name', orderDirection: 'ASC' });
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Método para obtener un producto por ID
|
|
16
|
+
async getProductById(id) {
|
|
17
|
+
return await this.findOne({ id: parseInt(id) });
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Método para crear un nuevo producto
|
|
21
|
+
async createProduct(productData) {
|
|
22
|
+
return await super.create(productData);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Método para actualizar un producto
|
|
26
|
+
async updateProduct(id, productData) {
|
|
27
|
+
return await super.update({ id: parseInt(id) }, productData);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Método para eliminar un producto
|
|
31
|
+
async deleteProduct(id) {
|
|
32
|
+
return await super.delete({ id: parseInt(id) });
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Método personalizado para buscar productos por categoría
|
|
36
|
+
async getProductsByCategory(category) {
|
|
37
|
+
return await this.find({ category: category });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
module.exports = ProductModel;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// models/UserModel.js
|
|
2
|
+
const { ModelBase } = require('../../index.js');
|
|
3
|
+
|
|
4
|
+
class UserModel extends ModelBase {
|
|
5
|
+
constructor(options = {}) {
|
|
6
|
+
super(options);
|
|
7
|
+
this.tableName = 'users';
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Método para obtener todos los usuarios
|
|
11
|
+
async getAllUsers() {
|
|
12
|
+
return await this.find({}, { orderBy: 'id', orderDirection: 'ASC' });
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Método para obtener un usuario por ID
|
|
16
|
+
async getUserById(id) {
|
|
17
|
+
return await this.findOne({ id: parseInt(id) });
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Método para crear un nuevo usuario
|
|
21
|
+
async createUser(userData) {
|
|
22
|
+
return await super.create(userData);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Método para actualizar un usuario
|
|
26
|
+
async updateUser(id, userData) {
|
|
27
|
+
return await super.update({ id: parseInt(id) }, userData);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Método para eliminar un usuario
|
|
31
|
+
async deleteUser(id) {
|
|
32
|
+
return await super.delete({ id: parseInt(id) });
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Método personalizado para buscar usuarios por nombre
|
|
36
|
+
async getUsersByName(name) {
|
|
37
|
+
return await this.find({ name: { $like: `%${name}%` } });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
module.exports = UserModel;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@qaLoadModel",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Proyecto de QA para probar el sistema de carga de modelos en JERK Framework",
|
|
5
|
+
"main": "server.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"start": "node server.js",
|
|
8
|
+
"test": "node test-models.js"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"jerkjs",
|
|
12
|
+
"mvc",
|
|
13
|
+
"models",
|
|
14
|
+
"controllers",
|
|
15
|
+
"testing"
|
|
16
|
+
],
|
|
17
|
+
"author": "QA Team",
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"jerkjs": "file:../"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# QA Report: Sistema de Carga de Modelos (loadModel)
|
|
2
|
+
|
|
3
|
+
## Resumen Ejecutivo
|
|
4
|
+
|
|
5
|
+
El sistema de carga de modelos (`loadModel`) en el framework JERK ha sido auditado y mejorado significativamente. Se identificaron y resolvieron problemas críticos relacionados con la resolución de rutas de modelos y la gestión de instancias.
|
|
6
|
+
|
|
7
|
+
## Problemas Identificados
|
|
8
|
+
|
|
9
|
+
### 1. Problema de Resolución de Rutas
|
|
10
|
+
- **Antes**: El sistema usaba rutas relativas al directorio de trabajo actual, lo que causaba fallos en la localización de archivos de modelo en estructuras de directorios complejas.
|
|
11
|
+
- **Solución**: Se implementó un sistema más robusto que intenta múltiples rutas posibles y usa `require.resolve()` para una resolución más precisa.
|
|
12
|
+
|
|
13
|
+
### 2. Problema de Reutilización de Instancias
|
|
14
|
+
- **Antes**: Cada llamada a `loadModel` creaba una nueva instancia del modelo, lo que podía causar problemas de memoria y consistencia de datos.
|
|
15
|
+
- **Solución**: Se implementó un sistema de caché que reutiliza instancias ya creadas del mismo modelo dentro del mismo controlador.
|
|
16
|
+
|
|
17
|
+
### 3. Problema de Gestión de Adaptadores
|
|
18
|
+
- **Antes**: No había un manejo claro de cómo se asignaban los adaptadores a las instancias de modelos.
|
|
19
|
+
- **Solución**: Se mejoró la lógica para asignar adaptadores tanto en la creación como en la reutilización de instancias.
|
|
20
|
+
|
|
21
|
+
## Cambios Implementados
|
|
22
|
+
|
|
23
|
+
### 1. Mejora en la Resolución de Rutas
|
|
24
|
+
- Se amplió el sistema de búsqueda para incluir más rutas posibles
|
|
25
|
+
- Se implementó `require.resolve()` para una resolución más precisa de módulos
|
|
26
|
+
- Se añadieron rutas específicas para estructuras de proyectos como el de QA
|
|
27
|
+
|
|
28
|
+
### 2. Sistema de Caché de Instancias
|
|
29
|
+
- Se implementó un sistema de caché en el controlador para almacenar instancias de modelos
|
|
30
|
+
- Las instancias se reutilizan en lugar de crear nuevas en cada llamada a `loadModel`
|
|
31
|
+
- Se mantiene la consistencia de adaptadores entre reutilizaciones
|
|
32
|
+
|
|
33
|
+
### 3. Manejo Mejorado de Adaptadores
|
|
34
|
+
- Se asegura que los adaptadores se asignen correctamente tanto en instancias nuevas como reutilizadas
|
|
35
|
+
- Se verifica si un modelo ya tiene un adaptador antes de asignar uno nuevo
|
|
36
|
+
|
|
37
|
+
## Resultados de las Pruebas
|
|
38
|
+
|
|
39
|
+
### Pruebas Unitarias
|
|
40
|
+
- ✅ Carga de modelos desde controladores: Funciona correctamente
|
|
41
|
+
- ✅ Carga con adaptadores: Funciona correctamente
|
|
42
|
+
- ✅ Reutilización de instancias: Funciona correctamente
|
|
43
|
+
- ✅ Acceso a modelos ya cargados: Funciona correctamente
|
|
44
|
+
- ✅ Manejo de errores: Funciona correctamente
|
|
45
|
+
|
|
46
|
+
### Pruebas de Integración
|
|
47
|
+
- ✅ Carga de múltiples modelos diferentes: Funciona correctamente
|
|
48
|
+
- ✅ Reutilización de la misma instancia de modelo: Funciona correctamente
|
|
49
|
+
- ✅ Asignación y reasignación de adaptadores: Funciona correctamente
|
|
50
|
+
- ✅ Búsqueda de modelos en diferentes ubicaciones: Funciona correctamente
|
|
51
|
+
|
|
52
|
+
## Impacto del Cambio
|
|
53
|
+
|
|
54
|
+
### Positivo
|
|
55
|
+
- Mayor estabilidad en la carga de modelos
|
|
56
|
+
- Mejor uso de memoria gracias a la reutilización de instancias
|
|
57
|
+
- Mayor confiabilidad en estructuras de directorios complejas
|
|
58
|
+
- Mejor experiencia de desarrollo
|
|
59
|
+
|
|
60
|
+
### Negativo
|
|
61
|
+
- Ninguno identificado
|
|
62
|
+
|
|
63
|
+
## Recomendaciones
|
|
64
|
+
|
|
65
|
+
1. **Documentación**: Actualizar la documentación para reflejar el nuevo comportamiento de reutilización de instancias
|
|
66
|
+
2. **Pruebas**: Implementar pruebas automatizadas para el sistema de carga de modelos
|
|
67
|
+
3. **Monitoreo**: Considerar añadir métricas de rendimiento para la carga de modelos
|
|
68
|
+
|
|
69
|
+
## Conclusión
|
|
70
|
+
|
|
71
|
+
El sistema de carga de modelos ha sido significativamente mejorado y ahora es más robusto, eficiente y confiable. Los problemas críticos identificados han sido resueltos, lo que aumenta la calidad general del framework JERK.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Resultados de Pruebas - Sistema de Carga de Modelos
|
|
2
|
+
|
|
3
|
+
## Resumen
|
|
4
|
+
|
|
5
|
+
Las pruebas del sistema de carga de modelos (`loadModel`) en el framework JERK han sido exitosas. Se han verificado todos los componentes del sistema MVC (Modelo-Vista-Controlador) y se han confirmado las siguientes funcionalidades:
|
|
6
|
+
|
|
7
|
+
## Funcionalidades Verificadas
|
|
8
|
+
|
|
9
|
+
### 1. Carga de Modelos
|
|
10
|
+
- ✅ El método `loadModel` funciona correctamente
|
|
11
|
+
- ✅ Los modelos se resuelven en múltiples ubicaciones posibles
|
|
12
|
+
- ✅ Las instancias de modelos se reutilizan adecuadamente
|
|
13
|
+
- ✅ Los adaptadores se asignan correctamente a los modelos
|
|
14
|
+
|
|
15
|
+
### 2. Controladores
|
|
16
|
+
- ✅ Los controladores extienden correctamente `ControllerBase`
|
|
17
|
+
- ✅ El contexto `this` se preserva correctamente usando `bind()`
|
|
18
|
+
- ✅ Los métodos de controladores se pueden usar como handlers de rutas
|
|
19
|
+
- ✅ Acceso al modelManager a través de la solicitud (`req.modelManager`)
|
|
20
|
+
|
|
21
|
+
### 3. Vistas
|
|
22
|
+
- ✅ El sistema de vistas funciona correctamente
|
|
23
|
+
- ✅ Las vistas se renderizan con datos dinámicos
|
|
24
|
+
- ✅ El sistema de layouts funciona correctamente
|
|
25
|
+
- ✅ Variables dinámicas se pasan a las vistas
|
|
26
|
+
|
|
27
|
+
### 4. Operaciones CRUD
|
|
28
|
+
- ✅ Creación de usuarios: `POST /api/users` ✅
|
|
29
|
+
- ✅ Creación de productos: `POST /api/products` ✅
|
|
30
|
+
- ✅ Lectura de usuarios: `GET /api/users/1` ✅
|
|
31
|
+
- ✅ Lectura de productos: `GET /api/products/1` ✅
|
|
32
|
+
- ✅ Listado de usuarios: `GET /api/users` ✅
|
|
33
|
+
- ✅ Listado de productos: `GET /api/products` ✅
|
|
34
|
+
|
|
35
|
+
## Endpoints Probados
|
|
36
|
+
|
|
37
|
+
### Usuarios
|
|
38
|
+
- `GET /api/users` - Lista de usuarios (vista HTML)
|
|
39
|
+
- `GET /api/users/:id` - Detalle de usuario (vista HTML)
|
|
40
|
+
- `POST /api/users` - Crear usuario (JSON)
|
|
41
|
+
- `GET /api/users/search?name=:name` - Buscar usuarios (JSON)
|
|
42
|
+
|
|
43
|
+
### Productos
|
|
44
|
+
- `GET /api/products` - Lista de productos (vista HTML)
|
|
45
|
+
- `GET /api/products/:id` - Detalle de producto (vista HTML)
|
|
46
|
+
- `POST /api/products` - Crear producto (JSON)
|
|
47
|
+
- `GET /api/products/search?category=:category` - Buscar productos (JSON)
|
|
48
|
+
|
|
49
|
+
## Resultados Específicos
|
|
50
|
+
|
|
51
|
+
1. **Creación de usuario exitosa**:
|
|
52
|
+
```json
|
|
53
|
+
{
|
|
54
|
+
"success": true,
|
|
55
|
+
"id": {
|
|
56
|
+
"id": 1,
|
|
57
|
+
"name": "Usuario de Prueba",
|
|
58
|
+
"email": "prueba@test.com",
|
|
59
|
+
"age": 25,
|
|
60
|
+
"createdAt": "...",
|
|
61
|
+
"updatedAt": "..."
|
|
62
|
+
},
|
|
63
|
+
"message": "Usuario creado exitosamente"
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
2. **Creación de producto exitosa**:
|
|
68
|
+
```json
|
|
69
|
+
{
|
|
70
|
+
"success": true,
|
|
71
|
+
"id": {
|
|
72
|
+
"id": 1,
|
|
73
|
+
"name": "Producto de Prueba",
|
|
74
|
+
"category": "Electrónica",
|
|
75
|
+
"price": 99.99,
|
|
76
|
+
"stock": 10,
|
|
77
|
+
"createdAt": "...",
|
|
78
|
+
"updatedAt": "..."
|
|
79
|
+
},
|
|
80
|
+
"message": "Producto creado exitosamente"
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
3. **Visualización de usuario exitosa**:
|
|
85
|
+
- Se mostró correctamente la vista HTML con los datos del usuario
|
|
86
|
+
- Los datos se renderizaron correctamente en la plantilla
|
|
87
|
+
|
|
88
|
+
## Conclusión
|
|
89
|
+
|
|
90
|
+
El sistema de carga de modelos en JERK Framework funciona correctamente. Se han resuelto los problemas identificados:
|
|
91
|
+
- ✅ Resolución de rutas de modelos
|
|
92
|
+
- ✅ Reutilización de instancias
|
|
93
|
+
- ✅ Asignación de adaptadores
|
|
94
|
+
- ✅ Preservación de contexto en controladores
|
|
95
|
+
- ✅ Acceso al modelManager desde solicitudes
|
|
96
|
+
|
|
97
|
+
El sistema MVC completo está operativo y listo para su uso en aplicaciones reales.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"path": "/api/users",
|
|
4
|
+
"method": "GET",
|
|
5
|
+
"controller": "./controllers/UserController.js",
|
|
6
|
+
"handler": "index",
|
|
7
|
+
"contentType": "text/html"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"path": "/api/users/:id",
|
|
11
|
+
"method": "GET",
|
|
12
|
+
"controller": "./controllers/UserController.js",
|
|
13
|
+
"handler": "show",
|
|
14
|
+
"contentType": "text/html"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"path": "/api/users",
|
|
18
|
+
"method": "POST",
|
|
19
|
+
"controller": "./controllers/UserController.js",
|
|
20
|
+
"handler": "create",
|
|
21
|
+
"contentType": "application/json"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"path": "/api/users/search",
|
|
25
|
+
"method": "GET",
|
|
26
|
+
"controller": "./controllers/UserController.js",
|
|
27
|
+
"handler": "search",
|
|
28
|
+
"contentType": "application/json"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"path": "/api/products",
|
|
32
|
+
"method": "GET",
|
|
33
|
+
"controller": "./controllers/ProductController.js",
|
|
34
|
+
"handler": "index",
|
|
35
|
+
"contentType": "text/html"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"path": "/api/products/:id",
|
|
39
|
+
"method": "GET",
|
|
40
|
+
"controller": "./controllers/ProductController.js",
|
|
41
|
+
"handler": "show",
|
|
42
|
+
"contentType": "text/html"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"path": "/api/products",
|
|
46
|
+
"method": "POST",
|
|
47
|
+
"controller": "./controllers/ProductController.js",
|
|
48
|
+
"handler": "create",
|
|
49
|
+
"contentType": "application/json"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"path": "/api/products/search",
|
|
53
|
+
"method": "GET",
|
|
54
|
+
"controller": "./controllers/ProductController.js",
|
|
55
|
+
"handler": "searchByCategory",
|
|
56
|
+
"contentType": "application/json"
|
|
57
|
+
}
|
|
58
|
+
]
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// server.js
|
|
2
|
+
const { APIServer, RouteLoader, ModelManager, MemoryAdapter } = require('../index.js');
|
|
3
|
+
|
|
4
|
+
const server = new APIServer({
|
|
5
|
+
port: 5679,
|
|
6
|
+
host: 'localhost'
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
// Configurar el motor de vistas
|
|
10
|
+
const ViewEngine = require('../lib/mvc/viewEngine');
|
|
11
|
+
server.viewEngine = new ViewEngine({
|
|
12
|
+
viewsPath: './views',
|
|
13
|
+
defaultExtension: '.html'
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
// Configurar el sistema de modelos
|
|
17
|
+
const modelManager = new ModelManager();
|
|
18
|
+
const memoryAdapter = new MemoryAdapter(); // Usando MemoryAdapter para pruebas
|
|
19
|
+
modelManager.registerAdapter('memory', memoryAdapter);
|
|
20
|
+
|
|
21
|
+
// Hacer que el modelManager esté disponible para los controladores
|
|
22
|
+
server.modelManager = modelManager;
|
|
23
|
+
|
|
24
|
+
// Cargar las rutas
|
|
25
|
+
const routeLoader = new RouteLoader();
|
|
26
|
+
routeLoader.loadRoutes(server, './routes.json')
|
|
27
|
+
.then(() => {
|
|
28
|
+
console.log('🚀 Servidor QA LoadModel iniciado en http://localhost:3000');
|
|
29
|
+
console.log('📊 Endpoints disponibles:');
|
|
30
|
+
console.log(' GET /api/users - Lista de usuarios');
|
|
31
|
+
console.log(' GET /api/users/:id - Detalle de usuario');
|
|
32
|
+
console.log(' POST /api/users - Crear usuario');
|
|
33
|
+
console.log(' GET /api/users/search?name=:name - Buscar usuarios');
|
|
34
|
+
console.log(' GET /api/products - Lista de productos');
|
|
35
|
+
console.log(' GET /api/products/:id - Detalle de producto');
|
|
36
|
+
console.log(' POST /api/products - Crear producto');
|
|
37
|
+
console.log(' GET /api/products/search?category=:category - Buscar productos');
|
|
38
|
+
|
|
39
|
+
server.start();
|
|
40
|
+
})
|
|
41
|
+
.catch(error => {
|
|
42
|
+
console.error('❌ Error cargando rutas:', error.message);
|
|
43
|
+
});
|