@arcaelas/dynamite 1.0.17 → 1.0.18

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.
Files changed (66) hide show
  1. package/package.json +40 -2
  2. package/src/@types/index.d.ts +27 -21
  3. package/src/core/client.d.ts +36 -0
  4. package/src/core/client.js +80 -27
  5. package/src/core/decorator.d.ts +44 -0
  6. package/src/core/decorator.js +133 -0
  7. package/src/core/method.d.ts +73 -0
  8. package/src/core/method.js +140 -0
  9. package/src/core/table.d.ts +44 -86
  10. package/src/core/table.js +510 -310
  11. package/src/decorators/indexes.d.ts +38 -0
  12. package/src/decorators/indexes.js +67 -0
  13. package/src/decorators/relations.d.ts +55 -0
  14. package/src/decorators/relations.js +84 -0
  15. package/src/decorators/timestamps.d.ts +54 -0
  16. package/src/decorators/timestamps.js +67 -0
  17. package/src/decorators/transforms.d.ts +86 -0
  18. package/src/decorators/transforms.js +154 -0
  19. package/src/index.d.ts +9 -16
  20. package/src/index.js +35 -32
  21. package/src/index.test.d.ts +13 -0
  22. package/src/index.test.js +1992 -0
  23. package/src/utils/relations.d.ts +34 -12
  24. package/src/utils/relations.js +109 -133
  25. package/src/core/wrapper.d.ts +0 -17
  26. package/src/core/wrapper.js +0 -46
  27. package/src/decorators/belongs_to.d.ts +0 -1
  28. package/src/decorators/belongs_to.js +0 -24
  29. package/src/decorators/created_at.d.ts +0 -1
  30. package/src/decorators/created_at.js +0 -11
  31. package/src/decorators/default.d.ts +0 -1
  32. package/src/decorators/default.js +0 -47
  33. package/src/decorators/has_many.d.ts +0 -1
  34. package/src/decorators/has_many.js +0 -24
  35. package/src/decorators/index.d.ts +0 -11
  36. package/src/decorators/index.js +0 -36
  37. package/src/decorators/index_sort.d.ts +0 -12
  38. package/src/decorators/index_sort.js +0 -43
  39. package/src/decorators/mutate.d.ts +0 -2
  40. package/src/decorators/mutate.js +0 -51
  41. package/src/decorators/name.d.ts +0 -1
  42. package/src/decorators/name.js +0 -28
  43. package/src/decorators/not_null.d.ts +0 -1
  44. package/src/decorators/not_null.js +0 -13
  45. package/src/decorators/primary_key.d.ts +0 -6
  46. package/src/decorators/primary_key.js +0 -30
  47. package/src/decorators/updated_at.d.ts +0 -12
  48. package/src/decorators/updated_at.js +0 -26
  49. package/src/decorators/validate.d.ts +0 -1
  50. package/src/decorators/validate.js +0 -53
  51. package/src/utils/batch-relations.d.ts +0 -14
  52. package/src/utils/batch-relations.js +0 -131
  53. package/src/utils/circular-detector.d.ts +0 -82
  54. package/src/utils/circular-detector.js +0 -212
  55. package/src/utils/memory-manager.d.ts +0 -42
  56. package/src/utils/memory-manager.js +0 -107
  57. package/src/utils/naming.d.ts +0 -8
  58. package/src/utils/naming.js +0 -18
  59. package/src/utils/projection.d.ts +0 -12
  60. package/src/utils/projection.js +0 -51
  61. package/src/utils/security-validator.d.ts +0 -49
  62. package/src/utils/security-validator.js +0 -163
  63. package/src/utils/throttle-manager.d.ts +0 -78
  64. package/src/utils/throttle-manager.js +0 -201
  65. package/src/utils/transaction-manager.d.ts +0 -88
  66. package/src/utils/transaction-manager.js +0 -300
@@ -1,42 +0,0 @@
1
- /**
2
- * @file memory-manager.ts
3
- * @description Memory management and leak prevention
4
- * @author Miguel Alejandro
5
- * @fecha 2025-08-31
6
- */
7
- declare class MemoryManager {
8
- private static instance;
9
- private cleanupTasks;
10
- private maxCacheSize;
11
- private maxCacheAge;
12
- static getInstance(): MemoryManager;
13
- /**
14
- * Registrar una tarea de limpieza
15
- */
16
- registerCleanup(id: string, cleanup: () => void, intervalMs?: number): void;
17
- /**
18
- * Desregistrar y limpiar tarea
19
- */
20
- unregisterCleanup(id: string): void;
21
- /**
22
- * Limpiar cache con límites de tamaño y edad
23
- */
24
- cleanCache<T>(cache: Map<string, {
25
- data: T;
26
- expires: number;
27
- created: number;
28
- }>, maxSize?: number): void;
29
- /**
30
- * Monitorear uso de memoria
31
- */
32
- getMemoryUsage(): NodeJS.MemoryUsage;
33
- /**
34
- * Forzar garbage collection si está disponible
35
- */
36
- forceGC(): void;
37
- /**
38
- * Cleanup completo al shutdown
39
- */
40
- shutdown(): void;
41
- }
42
- export default MemoryManager;
@@ -1,107 +0,0 @@
1
- "use strict";
2
- /**
3
- * @file memory-manager.ts
4
- * @description Memory management and leak prevention
5
- * @author Miguel Alejandro
6
- * @fecha 2025-08-31
7
- */
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- class MemoryManager {
10
- constructor() {
11
- this.cleanupTasks = new Map();
12
- this.maxCacheSize = 1000;
13
- this.maxCacheAge = 300000; // 5 minutos
14
- }
15
- static getInstance() {
16
- if (!MemoryManager.instance) {
17
- MemoryManager.instance = new MemoryManager();
18
- }
19
- return MemoryManager.instance;
20
- }
21
- /**
22
- * Registrar una tarea de limpieza
23
- */
24
- registerCleanup(id, cleanup, intervalMs) {
25
- // Limpiar tarea previa si existe
26
- this.unregisterCleanup(id);
27
- const task = { id, cleanup };
28
- if (intervalMs) {
29
- task.interval = setInterval(() => {
30
- try {
31
- cleanup();
32
- }
33
- catch (error) {
34
- console.warn(`Cleanup task ${id} failed:`, error);
35
- }
36
- }, intervalMs);
37
- }
38
- this.cleanupTasks.set(id, task);
39
- }
40
- /**
41
- * Desregistrar y limpiar tarea
42
- */
43
- unregisterCleanup(id) {
44
- const task = this.cleanupTasks.get(id);
45
- if (task) {
46
- if (task.interval) {
47
- clearInterval(task.interval);
48
- }
49
- task.cleanup();
50
- this.cleanupTasks.delete(id);
51
- }
52
- }
53
- /**
54
- * Limpiar cache con límites de tamaño y edad
55
- */
56
- cleanCache(cache, maxSize = this.maxCacheSize) {
57
- const now = Date.now();
58
- // Remover entradas expiradas
59
- for (const [key, entry] of cache.entries()) {
60
- if (entry.expires <= now || now - entry.created > this.maxCacheAge) {
61
- cache.delete(key);
62
- }
63
- }
64
- // Si aún excede el tamaño, remover las más antiguas
65
- if (cache.size > maxSize) {
66
- const entries = Array.from(cache.entries()).sort((a, b) => a[1].created - b[1].created);
67
- const toRemove = entries.slice(0, cache.size - maxSize);
68
- toRemove.forEach(([key]) => cache.delete(key));
69
- }
70
- }
71
- /**
72
- * Monitorear uso de memoria
73
- */
74
- getMemoryUsage() {
75
- return process.memoryUsage();
76
- }
77
- /**
78
- * Forzar garbage collection si está disponible
79
- */
80
- forceGC() {
81
- if (global.gc) {
82
- global.gc();
83
- }
84
- }
85
- /**
86
- * Cleanup completo al shutdown
87
- */
88
- shutdown() {
89
- console.log("MemoryManager: Iniciando cleanup completo...");
90
- for (const [id, task] of this.cleanupTasks.entries()) {
91
- try {
92
- this.unregisterCleanup(id);
93
- }
94
- catch (error) {
95
- console.warn(`Error cleaning up task ${id}:`, error);
96
- }
97
- }
98
- this.cleanupTasks.clear();
99
- this.forceGC();
100
- }
101
- }
102
- // Cleanup automático en shutdown
103
- process.on("SIGTERM", () => MemoryManager.getInstance().shutdown());
104
- process.on("SIGINT", () => MemoryManager.getInstance().shutdown());
105
- process.on("uncaughtException", () => MemoryManager.getInstance().shutdown());
106
- exports.default = MemoryManager;
107
- //# sourceMappingURL=memory-manager.js.map
@@ -1,8 +0,0 @@
1
- /**
2
- * @file naming.ts
3
- * @descripcion Utilidades de conversión de nombres
4
- * @autor Miguel Alejandro
5
- * @fecha 2025-01-27
6
- */
7
- /** Convierte nombre de clase a formato snake_case plural para tablas */
8
- export declare function toSnakePlural(input: string): string;
@@ -1,18 +0,0 @@
1
- "use strict";
2
- /**
3
- * @file naming.ts
4
- * @descripcion Utilidades de conversión de nombres
5
- * @autor Miguel Alejandro
6
- * @fecha 2025-01-27
7
- */
8
- var __importDefault = (this && this.__importDefault) || function (mod) {
9
- return (mod && mod.__esModule) ? mod : { "default": mod };
10
- };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.toSnakePlural = toSnakePlural;
13
- const pluralize_1 = __importDefault(require("pluralize"));
14
- /** Convierte nombre de clase a formato snake_case plural para tablas */
15
- function toSnakePlural(input) {
16
- return (0, pluralize_1.default)(input.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase());
17
- }
18
- //# sourceMappingURL=naming.js.map
@@ -1,12 +0,0 @@
1
- /**
2
- * @file projection.ts
3
- * @description Selective field loading and projection optimization
4
- * @autor Miguel Alejandro
5
- * @fecha 2025-01-27
6
- */
7
- /** Build DynamoDB ProjectionExpression */
8
- export declare const buildProjection: (attributes?: string[], meta?: any) => string | undefined;
9
- /** Optimize attributes loading for relations */
10
- export declare const optimizeRelationAttributes: (include: any, baseAttributes?: string[]) => string[];
11
- /** Smart attribute selection for common patterns */
12
- export declare const getSmartAttributes: (Model: any, scenario: "list" | "detail" | "minimal") => string[];
@@ -1,51 +0,0 @@
1
- "use strict";
2
- /**
3
- * @file projection.ts
4
- * @description Selective field loading and projection optimization
5
- * @autor Miguel Alejandro
6
- * @fecha 2025-01-27
7
- */
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.getSmartAttributes = exports.optimizeRelationAttributes = exports.buildProjection = void 0;
10
- const wrapper_1 = require("../core/wrapper");
11
- /** Build DynamoDB ProjectionExpression */
12
- const buildProjection = (attributes, meta) => {
13
- if (!attributes?.length || !meta)
14
- return undefined;
15
- // Validate attributes exist in model
16
- const validAttributes = attributes.filter((attr) => meta.columns.has(attr) || meta.relations.has(attr));
17
- return validAttributes.length ? validAttributes.join(", ") : undefined;
18
- };
19
- exports.buildProjection = buildProjection;
20
- /** Optimize attributes loading for relations */
21
- const optimizeRelationAttributes = (include, baseAttributes) => {
22
- const attributes = new Set(baseAttributes || []);
23
- // Add foreign keys needed for relations
24
- Object.entries(include || {}).forEach(([relationKey, options]) => {
25
- attributes.add(relationKey);
26
- // Add foreign key fields
27
- if (options?.foreignKey)
28
- attributes.add(options.foreignKey);
29
- if (options?.localKey)
30
- attributes.add(options.localKey);
31
- });
32
- return Array.from(attributes);
33
- };
34
- exports.optimizeRelationAttributes = optimizeRelationAttributes;
35
- /** Smart attribute selection for common patterns */
36
- const getSmartAttributes = (Model, scenario) => {
37
- const meta = (0, wrapper_1.mustMeta)(Model);
38
- const columns = Array.from(meta.columns.keys());
39
- switch (scenario) {
40
- case "minimal":
41
- return columns.filter((col) => meta.columns.get(col)?.primaryKey ||
42
- ["id", "name", "title", "email"].includes(col));
43
- case "list":
44
- return columns.filter((col) => !["description", "content", "body", "metadata"].includes(col));
45
- case "detail":
46
- default:
47
- return columns;
48
- }
49
- };
50
- exports.getSmartAttributes = getSmartAttributes;
51
- //# sourceMappingURL=projection.js.map
@@ -1,49 +0,0 @@
1
- /**
2
- * @file security-validator.ts
3
- * @description Security validation and NoSQL injection prevention
4
- * @author Miguel Alejandro
5
- * @fecha 2025-08-31
6
- */
7
- import { QueryOperator } from "../@types/index";
8
- interface SecurityConfig {
9
- maxStringLength: number;
10
- maxArrayLength: number;
11
- maxNestedDepth: number;
12
- allowedOperators: QueryOperator[];
13
- blockedPatterns: RegExp[];
14
- }
15
- declare class SecurityValidator {
16
- private static readonly DEFAULT_CONFIG;
17
- private config;
18
- constructor(config?: Partial<SecurityConfig>);
19
- /**
20
- * Validar nombre de atributo/tabla
21
- */
22
- validateAttributeName(name: string): void;
23
- /**
24
- * Validar operador de query
25
- */
26
- validateOperator(operator: string): QueryOperator;
27
- /**
28
- * Validar valor de campo
29
- */
30
- validateValue(value: any, depth?: number): any;
31
- /**
32
- * Validar filtros de query completos
33
- */
34
- validateQueryFilters(filters: Record<string, any>): Record<string, any>;
35
- /**
36
- * Sanitizar string para DynamoDB
37
- */
38
- sanitizeString(input: string): string;
39
- /**
40
- * Validar tamaño de item para DynamoDB (límite 400KB)
41
- */
42
- validateItemSize(item: any): void;
43
- }
44
- declare class SecurityError extends Error {
45
- constructor(message: string);
46
- }
47
- declare const securityValidator: SecurityValidator;
48
- export { SecurityError, SecurityValidator, securityValidator };
49
- export default securityValidator;
@@ -1,163 +0,0 @@
1
- "use strict";
2
- /**
3
- * @file security-validator.ts
4
- * @description Security validation and NoSQL injection prevention
5
- * @author Miguel Alejandro
6
- * @fecha 2025-08-31
7
- */
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.securityValidator = exports.SecurityValidator = exports.SecurityError = void 0;
10
- class SecurityValidator {
11
- static { this.DEFAULT_CONFIG = {
12
- maxStringLength: 10000,
13
- maxArrayLength: 1000,
14
- maxNestedDepth: 10,
15
- allowedOperators: [
16
- "=",
17
- "!=",
18
- "<",
19
- "<=",
20
- ">",
21
- ">=",
22
- "in",
23
- "not-in",
24
- "contains",
25
- "begins-with",
26
- ],
27
- blockedPatterns: [
28
- /\$\w+/g, // MongoDB operators
29
- /javascript:/gi, // JavaScript injection
30
- /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, // Script tags
31
- /eval\s*\(/gi, // eval() calls
32
- /function\s*\(/gi, // function declarations
33
- /\{\s*\$\w+/g, // NoSQL operators
34
- /\.\.\//g, // Path traversal
35
- /union\s+select/gi, // SQL injection patterns
36
- /drop\s+table/gi, // Destructive SQL
37
- ],
38
- }; }
39
- constructor(config) {
40
- this.config = { ...SecurityValidator.DEFAULT_CONFIG, ...config };
41
- }
42
- /**
43
- * Validar nombre de atributo/tabla
44
- */
45
- validateAttributeName(name) {
46
- if (!name || typeof name !== "string") {
47
- throw new SecurityError("Nombre de atributo inválido");
48
- }
49
- if (name.length > 255) {
50
- throw new SecurityError("Nombre de atributo muy largo");
51
- }
52
- // Solo permitir caracteres alfanuméricos, guiones y guiones bajos
53
- if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(name)) {
54
- throw new SecurityError("Nombre de atributo contiene caracteres inválidos");
55
- }
56
- // Verificar patrones bloqueados
57
- for (const pattern of this.config.blockedPatterns) {
58
- if (pattern.test(name)) {
59
- throw new SecurityError("Nombre de atributo contiene patrones peligrosos");
60
- }
61
- }
62
- }
63
- /**
64
- * Validar operador de query
65
- */
66
- validateOperator(operator) {
67
- if (!this.config.allowedOperators.includes(operator)) {
68
- throw new SecurityError(`Operador no permitido: ${operator}`);
69
- }
70
- return operator;
71
- }
72
- /**
73
- * Validar valor de campo
74
- */
75
- validateValue(value, depth = 0) {
76
- if (depth > this.config.maxNestedDepth) {
77
- throw new SecurityError("Estructura de datos anidada muy profunda");
78
- }
79
- // Valores null/undefined son válidos
80
- if (value === null || value === undefined) {
81
- return value;
82
- }
83
- // Validar strings
84
- if (typeof value === "string") {
85
- if (value.length > this.config.maxStringLength) {
86
- throw new SecurityError("String muy largo");
87
- }
88
- for (const pattern of this.config.blockedPatterns) {
89
- if (pattern.test(value)) {
90
- throw new SecurityError("Valor contiene patrones peligrosos");
91
- }
92
- }
93
- return value;
94
- }
95
- // Validar arrays
96
- if (Array.isArray(value)) {
97
- if (value.length > this.config.maxArrayLength) {
98
- throw new SecurityError("Array muy largo");
99
- }
100
- return value.map((item) => this.validateValue(item, depth + 1));
101
- }
102
- // Validar objetos
103
- if (typeof value === "object") {
104
- const validated = {};
105
- for (const [key, val] of Object.entries(value)) {
106
- this.validateAttributeName(key);
107
- validated[key] = this.validateValue(val, depth + 1);
108
- }
109
- return validated;
110
- }
111
- // Números, booleans son válidos
112
- if (typeof value === "number" || typeof value === "boolean") {
113
- return value;
114
- }
115
- throw new SecurityError(`Tipo de valor no permitido: ${typeof value}`);
116
- }
117
- /**
118
- * Validar filtros de query completos
119
- */
120
- validateQueryFilters(filters) {
121
- const validated = {};
122
- for (const [key, value] of Object.entries(filters)) {
123
- this.validateAttributeName(key);
124
- validated[key] = this.validateValue(value);
125
- }
126
- return validated;
127
- }
128
- /**
129
- * Sanitizar string para DynamoDB
130
- */
131
- sanitizeString(input) {
132
- if (typeof input !== "string") {
133
- return String(input);
134
- }
135
- return input
136
- .replace(/[\x00-\x1F\x7F]/g, "") // Remover caracteres de control
137
- .trim()
138
- .slice(0, this.config.maxStringLength);
139
- }
140
- /**
141
- * Validar tamaño de item para DynamoDB (límite 400KB)
142
- */
143
- validateItemSize(item) {
144
- const size = JSON.stringify(item).length;
145
- const maxSize = 400 * 1024; // 400KB en bytes
146
- if (size > maxSize) {
147
- throw new SecurityError(`Item muy grande: ${size} bytes (máximo: ${maxSize} bytes)`);
148
- }
149
- }
150
- }
151
- exports.SecurityValidator = SecurityValidator;
152
- class SecurityError extends Error {
153
- constructor(message) {
154
- super(message);
155
- this.name = "SecurityError";
156
- }
157
- }
158
- exports.SecurityError = SecurityError;
159
- // Instancia singleton
160
- const securityValidator = new SecurityValidator();
161
- exports.securityValidator = securityValidator;
162
- exports.default = securityValidator;
163
- //# sourceMappingURL=security-validator.js.map
@@ -1,78 +0,0 @@
1
- /**
2
- * @file throttle-manager.ts
3
- * @description AWS DynamoDB throttling and retry management
4
- * @author Miguel Alejandro
5
- * @fecha 2025-08-31
6
- */
7
- interface RetryConfig {
8
- maxRetries: number;
9
- baseDelay: number;
10
- maxDelay: number;
11
- backoffMultiplier: number;
12
- jitterFactor: number;
13
- }
14
- interface ThrottleStats {
15
- totalRequests: number;
16
- throttledRequests: number;
17
- retriedRequests: number;
18
- averageLatency: number;
19
- }
20
- declare class ThrottleManager {
21
- private static readonly DEFAULT_CONFIG;
22
- private config;
23
- private stats;
24
- private requestQueue;
25
- private isProcessingQueue;
26
- private concurrentRequests;
27
- private maxConcurrentRequests;
28
- constructor(config?: Partial<RetryConfig>);
29
- /**
30
- * Ejecutar operación con retry automático
31
- */
32
- executeWithRetry<T>(operation: () => Promise<T>, operationName?: string): Promise<T>;
33
- /**
34
- * Verificar si el error es reintentable
35
- */
36
- private isRetryableError;
37
- /**
38
- * Calcular delay con exponential backoff + jitter
39
- */
40
- private calculateDelay;
41
- /**
42
- * Controlar concurrencia de requests
43
- */
44
- private acquireConcurrencySlot;
45
- private releaseConcurrencySlot;
46
- /**
47
- * Queue para operaciones batch con rate limiting
48
- */
49
- queueOperation<T>(operation: () => Promise<T>): Promise<T>;
50
- private processQueue;
51
- /**
52
- * Obtener estadísticas de throttling
53
- */
54
- getStats(): ThrottleStats;
55
- /**
56
- * Resetear estadísticas
57
- */
58
- resetStats(): void;
59
- private updateLatencyStats;
60
- private sleep;
61
- /**
62
- * Configurar límites de concurrencia dinámicamente
63
- */
64
- setConcurrencyLimit(limit: number): void;
65
- /**
66
- * Obtener métricas de salud del throttling
67
- */
68
- getHealthMetrics(): {
69
- throttleRate: number;
70
- retryRate: number;
71
- avgLatency: number;
72
- concurrentRequests: number;
73
- queueSize: number;
74
- };
75
- }
76
- declare const throttleManager: ThrottleManager;
77
- export { RetryConfig, ThrottleManager, ThrottleStats, throttleManager };
78
- export default throttleManager;