@arcaelas/dynamite 1.0.9 → 1.0.13
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/LICENSE.txt +32 -0
- package/README.txt +206 -0
- package/package.json +5 -4
- package/src/@types/index.d.ts +96 -0
- package/src/@types/index.js +9 -0
- package/src/core/client.d.ts +69 -0
- package/src/core/client.js +164 -0
- package/src/core/table.d.ts +98 -0
- package/src/core/table.js +459 -0
- package/src/core/wrapper.d.ts +17 -0
- package/src/core/wrapper.js +46 -0
- package/src/decorators/belongs_to.d.ts +1 -0
- package/src/decorators/belongs_to.js +24 -0
- package/src/decorators/created_at.d.ts +1 -0
- package/{build → src}/decorators/created_at.js +0 -11
- package/src/decorators/default.d.ts +1 -0
- package/{build → src}/decorators/default.js +7 -12
- package/src/decorators/has_many.d.ts +1 -0
- package/src/decorators/has_many.js +24 -0
- package/src/decorators/index.d.ts +11 -0
- package/src/decorators/index.js +36 -0
- package/src/decorators/index_sort.d.ts +12 -0
- package/src/decorators/index_sort.js +43 -0
- package/{build → src}/decorators/mutate.js +12 -14
- package/{build → src}/decorators/name.js +1 -14
- package/src/decorators/not_null.d.ts +1 -0
- package/src/decorators/not_null.js +13 -0
- package/src/decorators/primary_key.d.ts +6 -0
- package/src/decorators/primary_key.js +30 -0
- package/src/decorators/updated_at.d.ts +12 -0
- package/src/decorators/updated_at.js +26 -0
- package/{build → src}/decorators/validate.js +12 -13
- package/src/index.d.ts +22 -0
- package/{build → src}/index.js +22 -6
- package/src/utils/batch-relations.d.ts +14 -0
- package/src/utils/batch-relations.js +131 -0
- package/src/utils/circular-detector.d.ts +82 -0
- package/src/utils/circular-detector.js +209 -0
- package/src/utils/memory-manager.d.ts +42 -0
- package/src/utils/memory-manager.js +108 -0
- package/src/utils/naming.d.ts +8 -0
- package/src/utils/naming.js +18 -0
- package/src/utils/projection.d.ts +12 -0
- package/src/utils/projection.js +51 -0
- package/src/utils/relations.d.ts +17 -0
- package/src/utils/relations.js +166 -0
- package/src/utils/security-validator.d.ts +49 -0
- package/src/utils/security-validator.js +152 -0
- package/src/utils/throttle-manager.d.ts +78 -0
- package/src/utils/throttle-manager.js +196 -0
- package/src/utils/transaction-manager.d.ts +88 -0
- package/src/utils/transaction-manager.js +298 -0
- package/build/core/table.d.ts +0 -138
- package/build/core/table.js +0 -400
- package/build/core/table.js.map +0 -1
- package/build/core/wrapper.d.ts +0 -44
- package/build/core/wrapper.js +0 -26
- package/build/core/wrapper.js.map +0 -1
- package/build/decorators/created_at.d.ts +0 -4
- package/build/decorators/created_at.js.map +0 -1
- package/build/decorators/default.d.ts +0 -2
- package/build/decorators/default.js.map +0 -1
- package/build/decorators/index.d.ts +0 -1
- package/build/decorators/index.js +0 -24
- package/build/decorators/index.js.map +0 -1
- package/build/decorators/index_sort.d.ts +0 -1
- package/build/decorators/index_sort.js +0 -27
- package/build/decorators/index_sort.js.map +0 -1
- package/build/decorators/mutate.js.map +0 -1
- package/build/decorators/name.js.map +0 -1
- package/build/decorators/not_null.d.ts +0 -4
- package/build/decorators/not_null.js +0 -28
- package/build/decorators/not_null.js.map +0 -1
- package/build/decorators/primary_key.d.ts +0 -7
- package/build/decorators/primary_key.js +0 -30
- package/build/decorators/primary_key.js.map +0 -1
- package/build/decorators/updated_at.d.ts +0 -4
- package/build/decorators/updated_at.js +0 -23
- package/build/decorators/updated_at.js.map +0 -1
- package/build/decorators/validate.js.map +0 -1
- package/build/index.d.ts +0 -11
- package/build/index.js.map +0 -1
- package/build/utils/naming.d.ts +0 -1
- package/build/utils/naming.js +0 -18
- package/build/utils/naming.js.map +0 -1
- /package/{build → src}/decorators/mutate.d.ts +0 -0
- /package/{build → src}/decorators/name.d.ts +0 -0
- /package/{build → src}/decorators/validate.d.ts +0 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file transaction-manager.ts
|
|
3
|
+
* @description Transaction simulation and rollback system for DynamoDB
|
|
4
|
+
* @author Miguel Alejandro
|
|
5
|
+
* @fecha 2025-08-31
|
|
6
|
+
*/
|
|
7
|
+
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
|
|
8
|
+
interface TransactionOperation {
|
|
9
|
+
type: 'create' | 'update' | 'delete';
|
|
10
|
+
tableName: string;
|
|
11
|
+
key: Record<string, any>;
|
|
12
|
+
item?: Record<string, any>;
|
|
13
|
+
conditionExpression?: string;
|
|
14
|
+
rollbackData?: Record<string, any>;
|
|
15
|
+
}
|
|
16
|
+
interface TransactionSnapshot {
|
|
17
|
+
id: string;
|
|
18
|
+
operations: TransactionOperation[];
|
|
19
|
+
timestamp: number;
|
|
20
|
+
status: 'pending' | 'committed' | 'rolled_back' | 'failed';
|
|
21
|
+
}
|
|
22
|
+
interface TransactionConfig {
|
|
23
|
+
maxOperationsPerTransaction: number;
|
|
24
|
+
snapshotTTL: number;
|
|
25
|
+
enableOptimisticLocking: boolean;
|
|
26
|
+
maxRetries: number;
|
|
27
|
+
}
|
|
28
|
+
declare class TransactionManager {
|
|
29
|
+
private static readonly DEFAULT_CONFIG;
|
|
30
|
+
private client;
|
|
31
|
+
private config;
|
|
32
|
+
private activeTransactions;
|
|
33
|
+
private snapshots;
|
|
34
|
+
constructor(client: DynamoDBClient, config?: Partial<TransactionConfig>);
|
|
35
|
+
/**
|
|
36
|
+
* Iniciar nueva transacción
|
|
37
|
+
*/
|
|
38
|
+
beginTransaction(operations: TransactionOperation[]): Promise<string>;
|
|
39
|
+
/**
|
|
40
|
+
* Ejecutar transacción usando DynamoDB TransactWrite
|
|
41
|
+
*/
|
|
42
|
+
commitTransaction(transactionId: string): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Rollback manual de transacción
|
|
45
|
+
*/
|
|
46
|
+
rollbackTransaction(transactionId: string): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Crear snapshot del estado actual para rollback
|
|
49
|
+
*/
|
|
50
|
+
private createSnapshot;
|
|
51
|
+
/**
|
|
52
|
+
* Obtener estado actual de un item
|
|
53
|
+
*/
|
|
54
|
+
private getCurrentItemState;
|
|
55
|
+
/**
|
|
56
|
+
* Crear operaciones inversas para rollback
|
|
57
|
+
*/
|
|
58
|
+
private createRollbackOperations;
|
|
59
|
+
/**
|
|
60
|
+
* Ejecutar lote de operaciones usando TransactWrite
|
|
61
|
+
*/
|
|
62
|
+
private executeBatch;
|
|
63
|
+
/**
|
|
64
|
+
* Dividir operaciones en lotes según límites DynamoDB
|
|
65
|
+
*/
|
|
66
|
+
private splitIntoBatches;
|
|
67
|
+
/**
|
|
68
|
+
* Validar operaciones antes de transacción
|
|
69
|
+
*/
|
|
70
|
+
private validateOperations;
|
|
71
|
+
/**
|
|
72
|
+
* Limpiar snapshots expirados
|
|
73
|
+
*/
|
|
74
|
+
private cleanupExpiredSnapshots;
|
|
75
|
+
/**
|
|
76
|
+
* Obtener estado de transacción
|
|
77
|
+
*/
|
|
78
|
+
getTransactionStatus(transactionId: string): TransactionSnapshot | null;
|
|
79
|
+
/**
|
|
80
|
+
* Listar transacciones activas
|
|
81
|
+
*/
|
|
82
|
+
getActiveTransactions(): TransactionSnapshot[];
|
|
83
|
+
private generateTransactionId;
|
|
84
|
+
}
|
|
85
|
+
declare class TransactionError extends Error {
|
|
86
|
+
constructor(message: string);
|
|
87
|
+
}
|
|
88
|
+
export { TransactionManager, TransactionOperation, TransactionSnapshot, TransactionError, TransactionConfig };
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @file transaction-manager.ts
|
|
4
|
+
* @description Transaction simulation and rollback system for DynamoDB
|
|
5
|
+
* @author Miguel Alejandro
|
|
6
|
+
* @fecha 2025-08-31
|
|
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.TransactionError = exports.TransactionManager = void 0;
|
|
13
|
+
const client_dynamodb_1 = require("@aws-sdk/client-dynamodb");
|
|
14
|
+
const util_dynamodb_1 = require("@aws-sdk/util-dynamodb");
|
|
15
|
+
const throttle_manager_1 = __importDefault(require("./throttle-manager"));
|
|
16
|
+
const security_validator_1 = __importDefault(require("./security-validator"));
|
|
17
|
+
class TransactionManager {
|
|
18
|
+
static { this.DEFAULT_CONFIG = {
|
|
19
|
+
maxOperationsPerTransaction: 25, // DynamoDB limit
|
|
20
|
+
snapshotTTL: 3600000, // 1 hour
|
|
21
|
+
enableOptimisticLocking: true,
|
|
22
|
+
maxRetries: 3,
|
|
23
|
+
}; }
|
|
24
|
+
constructor(client, config) {
|
|
25
|
+
this.activeTransactions = new Map();
|
|
26
|
+
this.snapshots = new Map();
|
|
27
|
+
this.client = client;
|
|
28
|
+
this.config = { ...TransactionManager.DEFAULT_CONFIG, ...config };
|
|
29
|
+
// Cleanup expired snapshots
|
|
30
|
+
setInterval(() => this.cleanupExpiredSnapshots(), 300000); // 5 minutes
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Iniciar nueva transacción
|
|
34
|
+
*/
|
|
35
|
+
async beginTransaction(operations) {
|
|
36
|
+
const transactionId = this.generateTransactionId();
|
|
37
|
+
// Validar operaciones
|
|
38
|
+
this.validateOperations(operations);
|
|
39
|
+
// Crear snapshot del estado actual para rollback
|
|
40
|
+
const snapshot = await this.createSnapshot(transactionId, operations);
|
|
41
|
+
this.activeTransactions.set(transactionId, snapshot);
|
|
42
|
+
this.snapshots.set(transactionId, snapshot);
|
|
43
|
+
return transactionId;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Ejecutar transacción usando DynamoDB TransactWrite
|
|
47
|
+
*/
|
|
48
|
+
async commitTransaction(transactionId) {
|
|
49
|
+
const snapshot = this.activeTransactions.get(transactionId);
|
|
50
|
+
if (!snapshot) {
|
|
51
|
+
throw new TransactionError(`Transaction ${transactionId} not found`);
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
snapshot.status = 'pending';
|
|
55
|
+
// Agrupar operaciones en lotes de 25 (límite DynamoDB)
|
|
56
|
+
const batches = this.splitIntoBatches(snapshot.operations);
|
|
57
|
+
for (const batch of batches) {
|
|
58
|
+
await this.executeBatch(batch);
|
|
59
|
+
}
|
|
60
|
+
snapshot.status = 'committed';
|
|
61
|
+
this.activeTransactions.delete(transactionId);
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
snapshot.status = 'failed';
|
|
65
|
+
// Intentar rollback automático
|
|
66
|
+
try {
|
|
67
|
+
await this.rollbackTransaction(transactionId);
|
|
68
|
+
}
|
|
69
|
+
catch (rollbackError) {
|
|
70
|
+
console.error('Rollback failed after commit error:', rollbackError);
|
|
71
|
+
}
|
|
72
|
+
throw new TransactionError(`Transaction commit failed: ${error.message}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Rollback manual de transacción
|
|
77
|
+
*/
|
|
78
|
+
async rollbackTransaction(transactionId) {
|
|
79
|
+
const snapshot = this.snapshots.get(transactionId);
|
|
80
|
+
if (!snapshot) {
|
|
81
|
+
throw new TransactionError(`Transaction snapshot ${transactionId} not found`);
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
// Crear operaciones inversas para rollback
|
|
85
|
+
const rollbackOps = this.createRollbackOperations(snapshot.operations);
|
|
86
|
+
if (rollbackOps.length > 0) {
|
|
87
|
+
const batches = this.splitIntoBatches(rollbackOps);
|
|
88
|
+
for (const batch of batches) {
|
|
89
|
+
await this.executeBatch(batch);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
snapshot.status = 'rolled_back';
|
|
93
|
+
this.activeTransactions.delete(transactionId);
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
throw new TransactionError(`Rollback failed: ${error.message}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Crear snapshot del estado actual para rollback
|
|
101
|
+
*/
|
|
102
|
+
async createSnapshot(transactionId, operations) {
|
|
103
|
+
const snapshot = {
|
|
104
|
+
id: transactionId,
|
|
105
|
+
operations: [],
|
|
106
|
+
timestamp: Date.now(),
|
|
107
|
+
status: 'pending',
|
|
108
|
+
};
|
|
109
|
+
// Para cada operación, guardar el estado actual del item
|
|
110
|
+
for (const op of operations) {
|
|
111
|
+
try {
|
|
112
|
+
const currentItem = await this.getCurrentItemState(op.tableName, op.key);
|
|
113
|
+
const snapshotOp = {
|
|
114
|
+
...op,
|
|
115
|
+
rollbackData: currentItem || undefined, // Estado actual para rollback
|
|
116
|
+
};
|
|
117
|
+
snapshot.operations.push(snapshotOp);
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
if (error.name !== 'ResourceNotFoundException') {
|
|
121
|
+
throw error;
|
|
122
|
+
}
|
|
123
|
+
// Item no existe, sin datos de rollback necesarios
|
|
124
|
+
snapshot.operations.push(op);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return snapshot;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Obtener estado actual de un item
|
|
131
|
+
*/
|
|
132
|
+
async getCurrentItemState(tableName, key) {
|
|
133
|
+
const params = {
|
|
134
|
+
TransactItems: [{
|
|
135
|
+
Get: {
|
|
136
|
+
TableName: tableName,
|
|
137
|
+
Key: (0, util_dynamodb_1.marshall)(key),
|
|
138
|
+
}
|
|
139
|
+
}]
|
|
140
|
+
};
|
|
141
|
+
const result = await throttle_manager_1.default.executeWithRetry(() => this.client.send(new client_dynamodb_1.TransactGetItemsCommand(params)), `GetItem-${tableName}`);
|
|
142
|
+
return result.Responses?.[0]?.Item
|
|
143
|
+
? (0, util_dynamodb_1.unmarshall)(result.Responses[0].Item)
|
|
144
|
+
: null;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Crear operaciones inversas para rollback
|
|
148
|
+
*/
|
|
149
|
+
createRollbackOperations(operations) {
|
|
150
|
+
const rollbackOps = [];
|
|
151
|
+
// Procesar en orden inverso
|
|
152
|
+
for (let i = operations.length - 1; i >= 0; i--) {
|
|
153
|
+
const op = operations[i];
|
|
154
|
+
switch (op.type) {
|
|
155
|
+
case 'create':
|
|
156
|
+
// Para rollback de create: delete el item
|
|
157
|
+
rollbackOps.push({
|
|
158
|
+
type: 'delete',
|
|
159
|
+
tableName: op.tableName,
|
|
160
|
+
key: op.key,
|
|
161
|
+
});
|
|
162
|
+
break;
|
|
163
|
+
case 'update':
|
|
164
|
+
if (op.rollbackData) {
|
|
165
|
+
// Para rollback de update: restore estado anterior
|
|
166
|
+
rollbackOps.push({
|
|
167
|
+
type: 'update',
|
|
168
|
+
tableName: op.tableName,
|
|
169
|
+
key: op.key,
|
|
170
|
+
item: op.rollbackData,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
break;
|
|
174
|
+
case 'delete':
|
|
175
|
+
if (op.rollbackData) {
|
|
176
|
+
// Para rollback de delete: recrear el item
|
|
177
|
+
rollbackOps.push({
|
|
178
|
+
type: 'create',
|
|
179
|
+
tableName: op.tableName,
|
|
180
|
+
key: op.key,
|
|
181
|
+
item: op.rollbackData,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return rollbackOps;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Ejecutar lote de operaciones usando TransactWrite
|
|
191
|
+
*/
|
|
192
|
+
async executeBatch(operations) {
|
|
193
|
+
const transactItems = operations.map(op => {
|
|
194
|
+
security_validator_1.default.validateItemSize(op.item || op.key);
|
|
195
|
+
switch (op.type) {
|
|
196
|
+
case 'create':
|
|
197
|
+
case 'update':
|
|
198
|
+
return {
|
|
199
|
+
Put: {
|
|
200
|
+
TableName: op.tableName,
|
|
201
|
+
Item: (0, util_dynamodb_1.marshall)(op.item, { removeUndefinedValues: true }),
|
|
202
|
+
ConditionExpression: op.conditionExpression,
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
case 'delete':
|
|
206
|
+
return {
|
|
207
|
+
Delete: {
|
|
208
|
+
TableName: op.tableName,
|
|
209
|
+
Key: (0, util_dynamodb_1.marshall)(op.key),
|
|
210
|
+
ConditionExpression: op.conditionExpression,
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
default:
|
|
214
|
+
throw new TransactionError(`Unknown operation type: ${op.type}`);
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
const command = new client_dynamodb_1.TransactWriteItemsCommand({
|
|
218
|
+
TransactItems: transactItems,
|
|
219
|
+
});
|
|
220
|
+
await throttle_manager_1.default.executeWithRetry(() => this.client.send(command), 'TransactWrite');
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Dividir operaciones en lotes según límites DynamoDB
|
|
224
|
+
*/
|
|
225
|
+
splitIntoBatches(operations) {
|
|
226
|
+
const batches = [];
|
|
227
|
+
const batchSize = this.config.maxOperationsPerTransaction;
|
|
228
|
+
for (let i = 0; i < operations.length; i += batchSize) {
|
|
229
|
+
batches.push(operations.slice(i, i + batchSize));
|
|
230
|
+
}
|
|
231
|
+
return batches;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Validar operaciones antes de transacción
|
|
235
|
+
*/
|
|
236
|
+
validateOperations(operations) {
|
|
237
|
+
if (operations.length === 0) {
|
|
238
|
+
throw new TransactionError('Transaction must contain at least one operation');
|
|
239
|
+
}
|
|
240
|
+
if (operations.length > this.config.maxOperationsPerTransaction * 10) {
|
|
241
|
+
throw new TransactionError(`Too many operations: ${operations.length}`);
|
|
242
|
+
}
|
|
243
|
+
for (const op of operations) {
|
|
244
|
+
// Validar estructura de la operación
|
|
245
|
+
if (!op.tableName || !op.key) {
|
|
246
|
+
throw new TransactionError('Invalid operation: missing tableName or key');
|
|
247
|
+
}
|
|
248
|
+
// Validar datos de seguridad
|
|
249
|
+
security_validator_1.default.validateQueryFilters(op.key);
|
|
250
|
+
if (op.item) {
|
|
251
|
+
security_validator_1.default.validateValue(op.item);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Limpiar snapshots expirados
|
|
257
|
+
*/
|
|
258
|
+
cleanupExpiredSnapshots() {
|
|
259
|
+
const now = Date.now();
|
|
260
|
+
const expired = [];
|
|
261
|
+
for (const [id, snapshot] of this.snapshots.entries()) {
|
|
262
|
+
if (now - snapshot.timestamp > this.config.snapshotTTL) {
|
|
263
|
+
expired.push(id);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
expired.forEach(id => {
|
|
267
|
+
this.snapshots.delete(id);
|
|
268
|
+
this.activeTransactions.delete(id);
|
|
269
|
+
});
|
|
270
|
+
if (expired.length > 0) {
|
|
271
|
+
console.log(`Cleaned up ${expired.length} expired transaction snapshots`);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Obtener estado de transacción
|
|
276
|
+
*/
|
|
277
|
+
getTransactionStatus(transactionId) {
|
|
278
|
+
return this.snapshots.get(transactionId) || null;
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Listar transacciones activas
|
|
282
|
+
*/
|
|
283
|
+
getActiveTransactions() {
|
|
284
|
+
return Array.from(this.activeTransactions.values());
|
|
285
|
+
}
|
|
286
|
+
generateTransactionId() {
|
|
287
|
+
return `txn_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
exports.TransactionManager = TransactionManager;
|
|
291
|
+
class TransactionError extends Error {
|
|
292
|
+
constructor(message) {
|
|
293
|
+
super(message);
|
|
294
|
+
this.name = 'TransactionError';
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
exports.TransactionError = TransactionError;
|
|
298
|
+
//# sourceMappingURL=transaction-manager.js.map
|
package/build/core/table.d.ts
DELETED
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
import { DynamoDBClientConfig } from "@aws-sdk/client-dynamodb";
|
|
2
|
-
import { InferAttributes, STORE, WrapperEntry } from "./wrapper";
|
|
3
|
-
export declare function connect(cfg: DynamoDBClientConfig): void;
|
|
4
|
-
export default class Table<T extends {} = any> {
|
|
5
|
-
protected [STORE]: {
|
|
6
|
-
[K in keyof T]?: T[K];
|
|
7
|
-
};
|
|
8
|
-
constructor(data: InferAttributes<T>);
|
|
9
|
-
save(): Promise<this>;
|
|
10
|
-
update(patch: InferAttributes<T>): Promise<this>;
|
|
11
|
-
destroy(): Promise<void>;
|
|
12
|
-
static create<M extends Table>(this: {
|
|
13
|
-
new (data: InferAttributes<M>): M;
|
|
14
|
-
prototype: M;
|
|
15
|
-
}, data: InferAttributes<M>): Promise<M>;
|
|
16
|
-
static update<M extends Table>(this: {
|
|
17
|
-
new (data: InferAttributes<M>): M;
|
|
18
|
-
prototype: M;
|
|
19
|
-
}, id: string, record: InferAttributes<M>): Promise<void>;
|
|
20
|
-
static destroy<M extends Table>(this: {
|
|
21
|
-
new (data: InferAttributes<M>): M;
|
|
22
|
-
prototype: M;
|
|
23
|
-
}, id: string): Promise<null>;
|
|
24
|
-
/**
|
|
25
|
-
* Realiza una consulta sobre la tabla, devolviendo una lista de resultados
|
|
26
|
-
* según condiciones y opciones de paginación/orden. Utiliza `QueryCommand`
|
|
27
|
-
* si la condición es por PK/SK con igualdad, o `ScanCommand` como fallback.
|
|
28
|
-
*
|
|
29
|
-
* @template M Instancia de la clase Table.
|
|
30
|
-
* @template K Clave de atributos inferida.
|
|
31
|
-
*
|
|
32
|
-
* @param key - Clave a filtrar (ej. "id").
|
|
33
|
-
* @param value - Valor a comparar (equivalente a '=' implícito).
|
|
34
|
-
* @param options - (Opcional) Opciones de paginación: { limit, skip, order }.
|
|
35
|
-
*
|
|
36
|
-
* @example
|
|
37
|
-
* await User.where('id', 'u1');
|
|
38
|
-
* await User.where('email', '=', 'a@b.com', { limit: 5, order: 'DESC' });
|
|
39
|
-
* await User.where({ email: 'x@y.com' }, { skip: 10, limit: 1 });
|
|
40
|
-
*
|
|
41
|
-
* @param filters - Objeto con pares clave/valor para consulta tipo AND.
|
|
42
|
-
* @param options - (Opcional) Opciones de paginación: { limit, skip, order }.
|
|
43
|
-
*
|
|
44
|
-
* @returns - Array de instancias de la tabla que cumplen la condición.
|
|
45
|
-
*/
|
|
46
|
-
static where<M extends Table, K extends keyof InferAttributes<M>>(this: {
|
|
47
|
-
new (data: InferAttributes<M>): M;
|
|
48
|
-
prototype: M;
|
|
49
|
-
}, key: K, value: InferAttributes<M>[K], options?: {
|
|
50
|
-
limit?: number;
|
|
51
|
-
skip?: number;
|
|
52
|
-
order?: "ASC" | "DESC";
|
|
53
|
-
}): Promise<M[]>;
|
|
54
|
-
static where<M extends Table, K extends keyof InferAttributes<M>>(this: {
|
|
55
|
-
new (data: InferAttributes<M>): M;
|
|
56
|
-
prototype: M;
|
|
57
|
-
}, key: K, op: "=" | "!=" | "<" | "<=" | ">" | ">=" | "in" | "not-in", value: InferAttributes<M>[K] | InferAttributes<M>[K][], options?: {
|
|
58
|
-
limit?: number;
|
|
59
|
-
skip?: number;
|
|
60
|
-
order?: "ASC" | "DESC";
|
|
61
|
-
}): Promise<M[]>;
|
|
62
|
-
static where<M extends Table>(this: {
|
|
63
|
-
new (data: InferAttributes<M>): M;
|
|
64
|
-
prototype: M;
|
|
65
|
-
}, filters: Partial<{
|
|
66
|
-
[K in keyof InferAttributes<M>]: InferAttributes<M>[K] | InferAttributes<M>[K][];
|
|
67
|
-
}>, options?: {
|
|
68
|
-
limit?: number;
|
|
69
|
-
skip?: number;
|
|
70
|
-
order?: "ASC" | "DESC";
|
|
71
|
-
}): Promise<M[]>;
|
|
72
|
-
/**
|
|
73
|
-
* Obtiene el primer elemento que coincida con la condición especificada.
|
|
74
|
-
* Equivalente a where() con { limit: 1, skip: 0, order: "ASC" }.
|
|
75
|
-
*
|
|
76
|
-
* @template M Instancia de la clase Table.
|
|
77
|
-
* @template K Clave de atributos inferida.
|
|
78
|
-
*
|
|
79
|
-
* @param key - Clave a filtrar (ej. "id").
|
|
80
|
-
* @param value - Valor a comparar (equivalente a '=' implícito).
|
|
81
|
-
*
|
|
82
|
-
* @example
|
|
83
|
-
* const user = await User.first('id', 'u1');
|
|
84
|
-
* const firstActive = await User.first('status', '=', 'active');
|
|
85
|
-
* const firstMatch = await User.first({ email: 'test@example.com' });
|
|
86
|
-
*
|
|
87
|
-
* @returns - El primer elemento encontrado o undefined si no hay coincidencias.
|
|
88
|
-
*/
|
|
89
|
-
static first<M extends Table, K extends keyof InferAttributes<M>>(this: {
|
|
90
|
-
new (data: InferAttributes<M>): M;
|
|
91
|
-
prototype: M;
|
|
92
|
-
}, key: K, value: InferAttributes<M>[K]): Promise<M | undefined>;
|
|
93
|
-
static first<M extends Table, K extends keyof InferAttributes<M>>(this: {
|
|
94
|
-
new (data: InferAttributes<M>): M;
|
|
95
|
-
prototype: M;
|
|
96
|
-
}, key: K, op: "=" | "!=" | "<" | "<=" | ">" | ">=" | "in" | "not-in", value: InferAttributes<M>[K] | InferAttributes<M>[K][]): Promise<M | undefined>;
|
|
97
|
-
static first<M extends Table>(this: {
|
|
98
|
-
new (data: InferAttributes<M>): M;
|
|
99
|
-
prototype: M;
|
|
100
|
-
}, filters: Partial<{
|
|
101
|
-
[K in keyof InferAttributes<M>]: InferAttributes<M>[K] | InferAttributes<M>[K][];
|
|
102
|
-
}>): Promise<M | undefined>;
|
|
103
|
-
/**
|
|
104
|
-
* Obtiene el último elemento que coincida con la condición especificada.
|
|
105
|
-
* Equivalente a where() con { limit: 1, skip: 0, order: "DESC" }.
|
|
106
|
-
*
|
|
107
|
-
* @template M Instancia de la clase Table.
|
|
108
|
-
* @template K Clave de atributos inferida.
|
|
109
|
-
*
|
|
110
|
-
* @param key - Clave a filtrar (ej. "id").
|
|
111
|
-
* @param value - Valor a comparar (equivalente a '=' implícito).
|
|
112
|
-
*
|
|
113
|
-
* @example
|
|
114
|
-
* const user = await User.last('id', 'u1');
|
|
115
|
-
* const lastActive = await User.last('status', '=', 'active');
|
|
116
|
-
* const lastMatch = await User.last({ email: 'test@example.com' });
|
|
117
|
-
*
|
|
118
|
-
* @returns - El último elemento encontrado o undefined si no hay coincidencias.
|
|
119
|
-
*/
|
|
120
|
-
static last<M extends Table, K extends keyof InferAttributes<M>>(this: {
|
|
121
|
-
new (data: InferAttributes<M>): M;
|
|
122
|
-
prototype: M;
|
|
123
|
-
}, key: K, value: InferAttributes<M>[K]): Promise<M | undefined>;
|
|
124
|
-
static last<M extends Table, K extends keyof InferAttributes<M>>(this: {
|
|
125
|
-
new (data: InferAttributes<M>): M;
|
|
126
|
-
prototype: M;
|
|
127
|
-
}, key: K, op: "=" | "!=" | "<" | "<=" | ">" | ">=" | "in" | "not-in", value: InferAttributes<M>[K] | InferAttributes<M>[K][]): Promise<M | undefined>;
|
|
128
|
-
static last<M extends Table>(this: {
|
|
129
|
-
new (data: InferAttributes<M>): M;
|
|
130
|
-
prototype: M;
|
|
131
|
-
}, filters: Partial<{
|
|
132
|
-
[K in keyof InferAttributes<M>]: InferAttributes<M>[K] | InferAttributes<M>[K][];
|
|
133
|
-
}>): Promise<M | undefined>;
|
|
134
|
-
toJSON(): Record<string, unknown>;
|
|
135
|
-
toString(): string;
|
|
136
|
-
}
|
|
137
|
-
export { STORE };
|
|
138
|
-
export type { WrapperEntry };
|