@arcaelas/dynamite 1.0.18 → 1.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +11 -42
- package/src/scripts/load_seed.d.ts +5 -0
- package/src/scripts/load_seed.js +54 -0
- package/src/src/@types/index.d.ts +188 -0
- package/src/src/@types/index.js +9 -0
- package/src/{core → src/core}/client.d.ts +4 -16
- package/src/{core → src/core}/client.js +115 -38
- package/src/{core → src/core}/decorator.d.ts +0 -15
- package/src/{core → src/core}/decorator.js +5 -35
- package/src/src/core/table.d.ts +81 -0
- package/src/src/core/table.js +892 -0
- package/src/{decorators → src/decorators}/indexes.d.ts +1 -1
- package/src/{decorators → src/decorators}/indexes.js +12 -20
- package/src/{decorators → src/decorators}/relations.d.ts +20 -1
- package/src/{decorators → src/decorators}/relations.js +32 -2
- package/src/{decorators → src/decorators}/timestamps.d.ts +4 -4
- package/src/{decorators → src/decorators}/timestamps.js +11 -6
- package/src/{decorators → src/decorators}/transforms.d.ts +17 -4
- package/src/{decorators → src/decorators}/transforms.js +40 -28
- package/src/{index.d.ts → src/index.d.ts} +4 -4
- package/src/{index.js → src/index.js} +3 -2
- package/src/src/index.test.d.ts +6 -0
- package/src/src/index.test.js +789 -0
- package/src/{utils → src/utils}/relations.d.ts +5 -3
- package/src/src/utils/relations.js +216 -0
- package/src/@types/index.d.ts +0 -102
- package/src/@types/index.js +0 -9
- package/src/core/method.d.ts +0 -73
- package/src/core/method.js +0 -140
- package/src/core/table.d.ts +0 -56
- package/src/core/table.js +0 -659
- package/src/index.test.d.ts +0 -13
- package/src/index.test.js +0 -1992
- package/src/utils/relations.js +0 -141
package/src/utils/relations.js
DELETED
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* @file relations.ts
|
|
4
|
-
* @description Sistema de carga de relaciones con batch loading
|
|
5
|
-
* @autor Miguel Alejandro
|
|
6
|
-
* @fecha 2025-01-28
|
|
7
|
-
*/
|
|
8
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.processIncludes = void 0;
|
|
10
|
-
const decorator_1 = require("../core/decorator");
|
|
11
|
-
/**
|
|
12
|
-
* @description Batch load para HasMany/HasOne
|
|
13
|
-
* Obtiene items relacionados donde foreignKey IN parent_ids
|
|
14
|
-
*/
|
|
15
|
-
const batchLoadHasMany = async (items, relation, options = {}) => {
|
|
16
|
-
const parent_ids = items.map(i => i[relation.localKey]).filter(Boolean);
|
|
17
|
-
if (!parent_ids.length)
|
|
18
|
-
return new Map();
|
|
19
|
-
// Obtener clase del modelo relacionado
|
|
20
|
-
const RelatedModel = relation.model();
|
|
21
|
-
// Query básico
|
|
22
|
-
let related = await RelatedModel.where(relation.foreignKey, 'in', parent_ids);
|
|
23
|
-
// Aplicar filtros adicionales
|
|
24
|
-
if (options.where) {
|
|
25
|
-
related = related.filter((item) => Object.entries(options.where).every(([k, v]) => item[k] === v));
|
|
26
|
-
}
|
|
27
|
-
// Ordenar
|
|
28
|
-
if (options.order) {
|
|
29
|
-
related.sort((a, b) => {
|
|
30
|
-
const aId = String(a.id ?? '');
|
|
31
|
-
const bId = String(b.id ?? '');
|
|
32
|
-
return options.order === 'asc' ? aId.localeCompare(bId) : bId.localeCompare(aId);
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
// Agrupar por foreignKey
|
|
36
|
-
const grouped = new Map();
|
|
37
|
-
for (const item of related) {
|
|
38
|
-
const key = String(item[relation.foreignKey]);
|
|
39
|
-
if (!grouped.has(key))
|
|
40
|
-
grouped.set(key, []);
|
|
41
|
-
grouped.get(key).push(item);
|
|
42
|
-
}
|
|
43
|
-
// Aplicar limit por grupo
|
|
44
|
-
if (options.limit) {
|
|
45
|
-
for (const [key, groupItems] of grouped) {
|
|
46
|
-
grouped.set(key, groupItems.slice(options.offset ?? 0, (options.offset ?? 0) + options.limit));
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
return grouped;
|
|
50
|
-
};
|
|
51
|
-
/**
|
|
52
|
-
* @description Batch load para BelongsTo
|
|
53
|
-
* Obtiene items donde id IN local_keys
|
|
54
|
-
*/
|
|
55
|
-
const batchLoadBelongsTo = async (items, relation, _options = {}) => {
|
|
56
|
-
const local_keys = items.map(i => i[relation.localKey]).filter(Boolean);
|
|
57
|
-
if (!local_keys.length)
|
|
58
|
-
return new Map();
|
|
59
|
-
const RelatedModel = relation.model();
|
|
60
|
-
const related = await RelatedModel.where(relation.foreignKey, 'in', local_keys);
|
|
61
|
-
const result = new Map();
|
|
62
|
-
for (const item of related) {
|
|
63
|
-
result.set(String(item[relation.foreignKey]), item);
|
|
64
|
-
}
|
|
65
|
-
return result;
|
|
66
|
-
};
|
|
67
|
-
/**
|
|
68
|
-
* @description Procesa includes recursivamente para cargar relaciones
|
|
69
|
-
* @param items Array de instancias a poblar
|
|
70
|
-
* @param include Objeto con relaciones a incluir
|
|
71
|
-
* @param TableClass Clase de la tabla actual
|
|
72
|
-
* @param depth Profundidad actual (máximo 10)
|
|
73
|
-
* @returns Items con relaciones pobladas
|
|
74
|
-
* @example
|
|
75
|
-
* ```typescript
|
|
76
|
-
* // Uso interno en Table.where()
|
|
77
|
-
* await processIncludes(users, {
|
|
78
|
-
* posts: {
|
|
79
|
-
* where: { published: true },
|
|
80
|
-
* limit: 5,
|
|
81
|
-
* include: {
|
|
82
|
-
* comments: true
|
|
83
|
-
* }
|
|
84
|
-
* }
|
|
85
|
-
* }, User);
|
|
86
|
-
* ```
|
|
87
|
-
*/
|
|
88
|
-
const processIncludes = async (items, include, TableClass, depth = 0) => {
|
|
89
|
-
if (!include || depth > 10 || !items.length)
|
|
90
|
-
return items;
|
|
91
|
-
const schema = TableClass[decorator_1.SCHEMA];
|
|
92
|
-
if (!schema)
|
|
93
|
-
return items;
|
|
94
|
-
const promises = Object.entries(include).map(async ([relation_key, options]) => {
|
|
95
|
-
const column = schema.columns[relation_key];
|
|
96
|
-
if (!column?.store?.relation)
|
|
97
|
-
return;
|
|
98
|
-
const relation = column.store.relation;
|
|
99
|
-
const opts = typeof options === 'boolean' ? {} : options;
|
|
100
|
-
// Batch load según tipo
|
|
101
|
-
let data;
|
|
102
|
-
if (relation.type === 'HasMany') {
|
|
103
|
-
data = await batchLoadHasMany(items, relation, opts);
|
|
104
|
-
}
|
|
105
|
-
else if (relation.type === 'HasOne') {
|
|
106
|
-
const hasMany = await batchLoadHasMany(items, relation, { ...opts, limit: 1 });
|
|
107
|
-
data = new Map();
|
|
108
|
-
for (const [k, v] of hasMany) {
|
|
109
|
-
data.set(k, v[0] ?? null);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
else {
|
|
113
|
-
// BelongsTo
|
|
114
|
-
data = await batchLoadBelongsTo(items, relation, opts);
|
|
115
|
-
}
|
|
116
|
-
// Asignar datos relacionados a cada item
|
|
117
|
-
for (const item of items) {
|
|
118
|
-
const key = String(item[relation.localKey]);
|
|
119
|
-
const value = relation.type === 'HasMany'
|
|
120
|
-
? data.get(key) ?? []
|
|
121
|
-
: data.get(key) ?? null;
|
|
122
|
-
Object.defineProperty(item, relation_key, {
|
|
123
|
-
value,
|
|
124
|
-
writable: true,
|
|
125
|
-
enumerable: true,
|
|
126
|
-
configurable: true
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
// Recursión para includes anidados
|
|
130
|
-
if (opts.include && data.size) {
|
|
131
|
-
const all_related = Array.from(data.values()).flat().filter(Boolean);
|
|
132
|
-
if (all_related.length) {
|
|
133
|
-
await (0, exports.processIncludes)(all_related, opts.include, relation.model(), depth + 1);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
});
|
|
137
|
-
await Promise.all(promises);
|
|
138
|
-
return items;
|
|
139
|
-
};
|
|
140
|
-
exports.processIncludes = processIncludes;
|
|
141
|
-
//# sourceMappingURL=relations.js.map
|