inlaweb-lib-dynamodb 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/.vscode/launch.json +22 -0
- package/.vscode/task.json +13 -0
- package/coverage/clover.xml +169 -0
- package/coverage/coverage-final.json +2 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +116 -0
- package/coverage/lcov-report/index.ts.html +1114 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +196 -0
- package/coverage/lcov.info +265 -0
- package/dist/commons/types.js +2 -0
- package/dist/index.js +317 -0
- package/dist/types/commons/types.d.ts +62 -0
- package/dist/types/index.d.ts +29 -0
- package/jest.config.js +9 -0
- package/package.json +27 -0
- package/readme.MD +8 -0
- package/src/commons/types.ts +71 -0
- package/src/index.ts +344 -0
- package/tests/index.test.ts +244 -0
- package/tsconfig.json +12 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.DynamoLib = void 0;
|
|
7
|
+
const client_dynamodb_1 = require("@aws-sdk/client-dynamodb");
|
|
8
|
+
const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb");
|
|
9
|
+
const logger_1 = require("@aws-lambda-powertools/logger");
|
|
10
|
+
const moment_timezone_1 = __importDefault(require("moment-timezone"));
|
|
11
|
+
const templatesUpdateExpresion = {
|
|
12
|
+
SET: (atribute) => `#${atribute} = :${atribute},`,
|
|
13
|
+
ADD: (atribute) => `#${atribute} :${atribute},`,
|
|
14
|
+
REMOVE: (atribute) => `#${atribute},`,
|
|
15
|
+
};
|
|
16
|
+
class DynamoLib {
|
|
17
|
+
constructor() {
|
|
18
|
+
this.client = new client_dynamodb_1.DynamoDBClient({});
|
|
19
|
+
this.docClient = lib_dynamodb_1.DynamoDBDocumentClient.from(this.client);
|
|
20
|
+
this.logger = new logger_1.Logger();
|
|
21
|
+
}
|
|
22
|
+
async putItem(tableName, item) {
|
|
23
|
+
const params = {
|
|
24
|
+
TableName: tableName,
|
|
25
|
+
Item: item,
|
|
26
|
+
ReturnItemCollectionMetrics: "SIZE",
|
|
27
|
+
ReturnConsumedCapacity: "TOTAL",
|
|
28
|
+
};
|
|
29
|
+
this.logger.debug(`PutItem: ${JSON.stringify(params)}`);
|
|
30
|
+
const result = await this.docClient.send(new lib_dynamodb_1.PutCommand(params));
|
|
31
|
+
this.logger.debug(`PutItem Result: ${JSON.stringify(result)}`);
|
|
32
|
+
}
|
|
33
|
+
async getItem(tableName, key, projectionExpression) {
|
|
34
|
+
const params = {
|
|
35
|
+
TableName: tableName,
|
|
36
|
+
Key: key,
|
|
37
|
+
ReturnConsumedCapacity: "TOTAL",
|
|
38
|
+
};
|
|
39
|
+
const projection = this.buildProjectionExpression(projectionExpression);
|
|
40
|
+
if (projection) {
|
|
41
|
+
params.ProjectionExpression = projection.projectionExpression;
|
|
42
|
+
params.ExpressionAttributeNames = projection.expressionAttributeNames;
|
|
43
|
+
}
|
|
44
|
+
this.logger.debug(`GetItem: ${JSON.stringify(params)}`);
|
|
45
|
+
const response = await this.docClient.send(new lib_dynamodb_1.GetCommand(params));
|
|
46
|
+
this.logger.debug(`GetItem Result: ${JSON.stringify(response)}`);
|
|
47
|
+
if (response.Item) {
|
|
48
|
+
return response.Item;
|
|
49
|
+
}
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
async updateItem(params) {
|
|
53
|
+
const itemUpdate = this.createUpdateParams(params);
|
|
54
|
+
this.logger.debug(`UpdateItem: ${JSON.stringify(itemUpdate.Update)}`);
|
|
55
|
+
const result = await this.docClient.send(new lib_dynamodb_1.UpdateCommand(itemUpdate.Update));
|
|
56
|
+
this.logger.debug(`UpdateItem Result: ${JSON.stringify(result)}`);
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
async query(params) {
|
|
60
|
+
const parameters = this.buildQueryParams(params);
|
|
61
|
+
this.logger.debug(`Query: ${JSON.stringify(parameters)}`);
|
|
62
|
+
const response = await this.docClient.send(new lib_dynamodb_1.QueryCommand(parameters));
|
|
63
|
+
this.logger.debug(`Query Result: ${JSON.stringify(response)}`);
|
|
64
|
+
if (response.Items) {
|
|
65
|
+
return response.Items;
|
|
66
|
+
}
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
buildQueryParams(params) {
|
|
70
|
+
const projection = this.buildProjectionExpression(params.searchParameters.projectionExpression);
|
|
71
|
+
const parameters = {
|
|
72
|
+
TableName: params.tableName,
|
|
73
|
+
KeyConditionExpression: "",
|
|
74
|
+
ExpressionAttributeNames: projection?.expressionAttributeNames || {},
|
|
75
|
+
ExpressionAttributeValues: {}
|
|
76
|
+
};
|
|
77
|
+
if (params.permission && params.permission === "OWNS") {
|
|
78
|
+
params.searchParameters.parameters.push({
|
|
79
|
+
name: "creationUser",
|
|
80
|
+
value: params.username,
|
|
81
|
+
operator: "FILTER",
|
|
82
|
+
filterOperator: "=",
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
params.searchParameters.parameters.forEach((searchParameter, index) => {
|
|
86
|
+
this.buildExpressions(searchParameter, index, parameters);
|
|
87
|
+
});
|
|
88
|
+
return parameters;
|
|
89
|
+
}
|
|
90
|
+
buildExpressions(searchParameter, index, params) {
|
|
91
|
+
if (index !== 0 && searchParameter.operator !== "FILTER")
|
|
92
|
+
params.KeyConditionExpression += " and ";
|
|
93
|
+
switch (searchParameter.operator) {
|
|
94
|
+
case "begins_with":
|
|
95
|
+
params.KeyConditionExpression += `${searchParameter.operator}(#key${index}, :value${index})`;
|
|
96
|
+
break;
|
|
97
|
+
case "BETWEEN":
|
|
98
|
+
params.KeyConditionExpression += `#key${index} ${searchParameter.operator} :value${index} AND :value1${index}`;
|
|
99
|
+
params.ExpressionAttributeValues[`:value1${index}`] = searchParameter.value1;
|
|
100
|
+
break;
|
|
101
|
+
case "FILTER":
|
|
102
|
+
this.buildFilterExpression(searchParameter, index, params);
|
|
103
|
+
break;
|
|
104
|
+
default:
|
|
105
|
+
params.KeyConditionExpression += `#key${index} ${searchParameter.operator} :value${index}`;
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
params.ExpressionAttributeNames[`#key${index}`] = searchParameter.name;
|
|
109
|
+
params.ExpressionAttributeValues[`:value${index}`] = searchParameter.value;
|
|
110
|
+
}
|
|
111
|
+
buildFilterExpression(searchParameter, index, params) {
|
|
112
|
+
if (params.FilterExpression)
|
|
113
|
+
params.FilterExpression += ' and ';
|
|
114
|
+
else
|
|
115
|
+
params.FilterExpression = '';
|
|
116
|
+
switch (searchParameter.filterOperator) {
|
|
117
|
+
case 'contains':
|
|
118
|
+
params.FilterExpression += `contains (#key${index}, :value${index})`;
|
|
119
|
+
break;
|
|
120
|
+
case 'begins_with':
|
|
121
|
+
params.FilterExpression += `${searchParameter.filterOperator}(#key${index}, :value${index})`;
|
|
122
|
+
break;
|
|
123
|
+
case "attribute_not_exists":
|
|
124
|
+
params.FilterExpression += `attribute_not_exists (#key${index})`;
|
|
125
|
+
break;
|
|
126
|
+
case "attribute_exists":
|
|
127
|
+
params.FilterExpression += `attribute_exists (#key${index})`;
|
|
128
|
+
break;
|
|
129
|
+
default:
|
|
130
|
+
params.FilterExpression += `#key${index} ${searchParameter.filterOperator} :value${index}`;
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
buildProjectionExpression(projectionExpression) {
|
|
135
|
+
if (!projectionExpression) {
|
|
136
|
+
return undefined;
|
|
137
|
+
}
|
|
138
|
+
const fields = projectionExpression.split(",");
|
|
139
|
+
if (fields.length > 0) {
|
|
140
|
+
let projectionExpression = "";
|
|
141
|
+
const expressionAttributeNames = {};
|
|
142
|
+
fields.forEach((field) => {
|
|
143
|
+
projectionExpression += `#${field},`;
|
|
144
|
+
expressionAttributeNames[`#${field}`] = field;
|
|
145
|
+
});
|
|
146
|
+
projectionExpression = projectionExpression.slice(0, -1);
|
|
147
|
+
return { projectionExpression, expressionAttributeNames };
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
async saveBatch(table, items) {
|
|
151
|
+
const executions = this.createBatch(items);
|
|
152
|
+
for (let i = 0; i < executions.length; i++) {
|
|
153
|
+
const params = {
|
|
154
|
+
RequestItems: {
|
|
155
|
+
[table]: executions[i]
|
|
156
|
+
},
|
|
157
|
+
ReturnConsumedCapacity: "TOTAL",
|
|
158
|
+
};
|
|
159
|
+
this.logger.debug(`BatchWrite: ${JSON.stringify(params)}`);
|
|
160
|
+
const response = await this.docClient.send(new lib_dynamodb_1.BatchWriteCommand(params));
|
|
161
|
+
this.logger.debug(`BatchWrite Result: ${JSON.stringify(response)}`);
|
|
162
|
+
}
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
createBatch(items) {
|
|
166
|
+
const executions = [];
|
|
167
|
+
const numberOfBacthInsertions = Math.ceil(items.length / 25);
|
|
168
|
+
for (let i = 0; i < numberOfBacthInsertions; i++) {
|
|
169
|
+
executions[i] = [];
|
|
170
|
+
}
|
|
171
|
+
items.forEach((item, index) => {
|
|
172
|
+
const currentIndex = Math.ceil((index + 1) / 25);
|
|
173
|
+
executions[currentIndex - 1].push({ PutRequest: { Item: item } });
|
|
174
|
+
});
|
|
175
|
+
return executions;
|
|
176
|
+
}
|
|
177
|
+
async writeTransactions(items, limit) {
|
|
178
|
+
const executions = this.createWriteTransactions(items, limit);
|
|
179
|
+
for (let i = 0; i < executions.length; i++) {
|
|
180
|
+
const params = {
|
|
181
|
+
TransactItems: executions[i],
|
|
182
|
+
ReturnConsumedCapacity: "TOTAL",
|
|
183
|
+
};
|
|
184
|
+
this.logger.debug(`TransactWrite: ${JSON.stringify(params)}`);
|
|
185
|
+
const response = await this.docClient.send(new lib_dynamodb_1.TransactWriteCommand(params));
|
|
186
|
+
this.logger.debug(`TransactWrite Result: ${JSON.stringify(response)}`);
|
|
187
|
+
}
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
createWriteTransactions(items, limit) {
|
|
191
|
+
const executions = [];
|
|
192
|
+
const numberOfBacthInsertions = Math.ceil(items.length / limit);
|
|
193
|
+
for (let i = 0; i < numberOfBacthInsertions; i++) {
|
|
194
|
+
executions[i] = [];
|
|
195
|
+
}
|
|
196
|
+
items.forEach((item, index) => {
|
|
197
|
+
const currentIndex = Math.ceil((index + 1) / limit);
|
|
198
|
+
executions[currentIndex - 1].push({ Put: { Item: item } });
|
|
199
|
+
});
|
|
200
|
+
return executions;
|
|
201
|
+
}
|
|
202
|
+
createUpdateParams(params) {
|
|
203
|
+
const { table, PK, SK, item, setAttributes, addAttributes, removeAttributes, username } = params;
|
|
204
|
+
// Se agregan los datos de auditoría para la actualización
|
|
205
|
+
item.updateUser = username;
|
|
206
|
+
item.updateDate = moment_timezone_1.default.tz(new Date(), "America/Bogota").format("YYYY-MM-DD");
|
|
207
|
+
if (!setAttributes.includes("updateUser"))
|
|
208
|
+
setAttributes.push("updateUser");
|
|
209
|
+
if (!setAttributes.includes("updateDate"))
|
|
210
|
+
setAttributes.push("updateDate");
|
|
211
|
+
// Se crea el objeto de la operación
|
|
212
|
+
let itemUpdate = {
|
|
213
|
+
Update: {
|
|
214
|
+
TableName: table,
|
|
215
|
+
Key: { PK, SK },
|
|
216
|
+
UpdateExpression: ``,
|
|
217
|
+
ExpressionAttributeNames: {},
|
|
218
|
+
ExpressionAttributeValues: {},
|
|
219
|
+
ReturnConsumedCapacity: "TOTAL",
|
|
220
|
+
},
|
|
221
|
+
};
|
|
222
|
+
// Se agregan los campos a modificar
|
|
223
|
+
if (Array.isArray(setAttributes) && setAttributes.length) {
|
|
224
|
+
this.formatUpdateExpression("SET", itemUpdate, item, setAttributes);
|
|
225
|
+
}
|
|
226
|
+
// Se agragan los campos nuevos del item
|
|
227
|
+
if (Array.isArray(addAttributes) && addAttributes.length) {
|
|
228
|
+
this.formatUpdateExpression("ADD", itemUpdate, item, addAttributes);
|
|
229
|
+
}
|
|
230
|
+
// Se agregan los campos que deben ser borrados
|
|
231
|
+
if (Array.isArray(removeAttributes) && removeAttributes.length) {
|
|
232
|
+
this.formatUpdateExpressionRemove(itemUpdate, removeAttributes);
|
|
233
|
+
}
|
|
234
|
+
// Se remueve el espacio al final de la expresión
|
|
235
|
+
itemUpdate.Update.UpdateExpression = itemUpdate.Update.UpdateExpression.slice(0, -1);
|
|
236
|
+
return itemUpdate;
|
|
237
|
+
}
|
|
238
|
+
formatUpdateExpression(operation, updateObject, item, atributes) {
|
|
239
|
+
// Se agrega la operación.
|
|
240
|
+
updateObject.Update.UpdateExpression += `${operation} `;
|
|
241
|
+
// Se obtiene el templete de acuerdo a la operación.
|
|
242
|
+
let operationTemplate = templatesUpdateExpresion[operation];
|
|
243
|
+
// Se añaden los items afectados por la operación.
|
|
244
|
+
for (let atribute of atributes) {
|
|
245
|
+
if (typeof item[atribute] === "boolean" || typeof item[atribute] === "number" || item[atribute]) {
|
|
246
|
+
updateObject.Update.UpdateExpression += operationTemplate(atribute);
|
|
247
|
+
updateObject.Update.ExpressionAttributeNames[`#${atribute}`] = atribute;
|
|
248
|
+
updateObject.Update.ExpressionAttributeValues[`:${atribute}`] = item[atribute];
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
// Se remueve la coma final para evitar errores con el SDK.
|
|
252
|
+
updateObject.Update.UpdateExpression = updateObject.Update.UpdateExpression.slice(0, -1);
|
|
253
|
+
// Se añade un espacio para poder agregar nuevas operaciones.
|
|
254
|
+
updateObject.Update.UpdateExpression += " ";
|
|
255
|
+
}
|
|
256
|
+
formatUpdateExpressionRemove(updateObject, atributes) {
|
|
257
|
+
let operation = "REMOVE";
|
|
258
|
+
// Se agrega la operación.
|
|
259
|
+
updateObject.Update.UpdateExpression += `${operation} `;
|
|
260
|
+
// Se obtiene el templete de acuerdo a la operación.
|
|
261
|
+
let operationTemplate = templatesUpdateExpresion[operation];
|
|
262
|
+
// Se añaden los items afectados por la operación.
|
|
263
|
+
for (let atribute of atributes) {
|
|
264
|
+
updateObject.Update.UpdateExpression += operationTemplate(atribute);
|
|
265
|
+
updateObject.Update.ExpressionAttributeNames[`#${atribute}`] = atribute;
|
|
266
|
+
}
|
|
267
|
+
// Se remueve la coma final para evitar errores con el SDK.
|
|
268
|
+
updateObject.Update.UpdateExpression = updateObject.Update.UpdateExpression.slice(0, -1);
|
|
269
|
+
// Se añade un espacio para poder agregar nuevas operaciones.
|
|
270
|
+
updateObject.Update.UpdateExpression += " ";
|
|
271
|
+
}
|
|
272
|
+
async getId(table, entity, username, quantity) {
|
|
273
|
+
let item = await this.getItem(table, { PK: "COUN", SK: entity }, "order");
|
|
274
|
+
if (!item) {
|
|
275
|
+
item = {
|
|
276
|
+
PK: "COUN",
|
|
277
|
+
SK: entity,
|
|
278
|
+
entity: "COUN",
|
|
279
|
+
order: 0,
|
|
280
|
+
creationUser: username,
|
|
281
|
+
creationDate: moment_timezone_1.default.tz(new Date(), "America/Bogota").format("YYYY-MM-DD"),
|
|
282
|
+
};
|
|
283
|
+
await this.putItem(table, item);
|
|
284
|
+
}
|
|
285
|
+
const params = {
|
|
286
|
+
TableName: table,
|
|
287
|
+
Key: { PK: "COUN", SK: entity },
|
|
288
|
+
UpdateExpression: `SET #id = #id + :increment`,
|
|
289
|
+
ExpressionAttributeNames: { "#id": "order" },
|
|
290
|
+
ExpressionAttributeValues: { ":increment": quantity || 1 },
|
|
291
|
+
ReturnValues: "UPDATED_OLD"
|
|
292
|
+
};
|
|
293
|
+
this.logger.debug(`GetId: ${JSON.stringify(params)}`);
|
|
294
|
+
const result = await this.docClient.send(new lib_dynamodb_1.UpdateCommand(params));
|
|
295
|
+
this.logger.debug(`GetId Result: ${JSON.stringify(result)}`);
|
|
296
|
+
if (result.Attributes)
|
|
297
|
+
return result.Attributes.order + 1;
|
|
298
|
+
return 1;
|
|
299
|
+
}
|
|
300
|
+
async validatePermission(table, entity, action, profile) {
|
|
301
|
+
let result;
|
|
302
|
+
let searchParameters = {
|
|
303
|
+
indexName: "GSI2",
|
|
304
|
+
parameters: [
|
|
305
|
+
{ name: "entity", value: "PERM", operator: "=" },
|
|
306
|
+
{ name: "relation2", value: `${profile}|${entity}|${action}`, operator: "=" },
|
|
307
|
+
],
|
|
308
|
+
};
|
|
309
|
+
let permissionQuery = await this.query({ tableName: table, searchParameters });
|
|
310
|
+
if (permissionQuery.length) {
|
|
311
|
+
result = permissionQuery[0];
|
|
312
|
+
return result.type === "ALL" ? "ALL" : "OWNS";
|
|
313
|
+
}
|
|
314
|
+
throw new Error("UNAUTHORIZE_REQUEST");
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
exports.DynamoLib = DynamoLib;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { ReturnConsumedCapacity, ReturnValue, ReturnItemCollectionMetrics } from "@aws-sdk/client-dynamodb";
|
|
2
|
+
export interface ParamsPut {
|
|
3
|
+
TableName: string;
|
|
4
|
+
Item: KeyValue;
|
|
5
|
+
ReturnConsumedCapacity?: ReturnConsumedCapacity;
|
|
6
|
+
ReturnItemCollectionMetrics?: ReturnItemCollectionMetrics;
|
|
7
|
+
}
|
|
8
|
+
export interface ParamsGet {
|
|
9
|
+
TableName: string;
|
|
10
|
+
Key: KeyValue;
|
|
11
|
+
ProjectionExpression?: string;
|
|
12
|
+
ExpressionAttributeNames?: KeyValue;
|
|
13
|
+
ReturnConsumedCapacity?: ReturnConsumedCapacity;
|
|
14
|
+
}
|
|
15
|
+
export interface ParamsQuery {
|
|
16
|
+
TableName: string;
|
|
17
|
+
KeyConditionExpression: string;
|
|
18
|
+
ExpressionAttributeNames: KeyValue;
|
|
19
|
+
ExpressionAttributeValues: KeyValue;
|
|
20
|
+
ProjectionExpression?: string;
|
|
21
|
+
ExclusiveStartKey?: KeyValue;
|
|
22
|
+
Limit?: number;
|
|
23
|
+
ScanIndexForward?: boolean;
|
|
24
|
+
IndexName?: string;
|
|
25
|
+
FilterExpression?: string;
|
|
26
|
+
ConsistentRead?: boolean;
|
|
27
|
+
ReturnConsumedCapacity?: ReturnConsumedCapacity;
|
|
28
|
+
}
|
|
29
|
+
export interface ParamsUpdate {
|
|
30
|
+
TableName: string;
|
|
31
|
+
Key: KeyValue;
|
|
32
|
+
UpdateExpression: string;
|
|
33
|
+
ExpressionAttributeNames: KeyValue;
|
|
34
|
+
ExpressionAttributeValues: KeyValue;
|
|
35
|
+
ReturnValues?: ReturnValue;
|
|
36
|
+
}
|
|
37
|
+
export interface ProjectionExpression {
|
|
38
|
+
projectionExpression: string;
|
|
39
|
+
expressionAttributeNames: KeyValue;
|
|
40
|
+
}
|
|
41
|
+
export interface SearchParameters {
|
|
42
|
+
indexName: string;
|
|
43
|
+
parameters: KeyValue[];
|
|
44
|
+
projectionExpression?: string;
|
|
45
|
+
exclusiveStartKey?: KeyValue;
|
|
46
|
+
scanIndexForward?: boolean;
|
|
47
|
+
limit?: number;
|
|
48
|
+
}
|
|
49
|
+
export interface InputUpdate {
|
|
50
|
+
table: string;
|
|
51
|
+
PK: string;
|
|
52
|
+
SK: string;
|
|
53
|
+
username: string;
|
|
54
|
+
item: KeyValue;
|
|
55
|
+
setAttributes: string[];
|
|
56
|
+
addAttributes?: string[];
|
|
57
|
+
removeAttributes?: string[];
|
|
58
|
+
}
|
|
59
|
+
export interface KeyValue {
|
|
60
|
+
[key: string]: any;
|
|
61
|
+
}
|
|
62
|
+
export type Operation = "SET" | "ADD" | "REMOVE";
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { SearchParameters, KeyValue, InputUpdate } from "./commons/types";
|
|
2
|
+
export declare class DynamoLib {
|
|
3
|
+
private readonly client;
|
|
4
|
+
private readonly docClient;
|
|
5
|
+
private readonly logger;
|
|
6
|
+
constructor();
|
|
7
|
+
putItem(tableName: string, item: KeyValue): Promise<void>;
|
|
8
|
+
getItem(tableName: string, key: KeyValue, projectionExpression?: string): Promise<KeyValue | undefined>;
|
|
9
|
+
updateItem(params: InputUpdate): Promise<boolean>;
|
|
10
|
+
query(params: {
|
|
11
|
+
tableName: string;
|
|
12
|
+
searchParameters: SearchParameters;
|
|
13
|
+
permission?: string;
|
|
14
|
+
username?: string;
|
|
15
|
+
}): Promise<KeyValue[]>;
|
|
16
|
+
private buildQueryParams;
|
|
17
|
+
private buildExpressions;
|
|
18
|
+
private buildFilterExpression;
|
|
19
|
+
private buildProjectionExpression;
|
|
20
|
+
saveBatch(table: string, items: KeyValue[]): Promise<boolean>;
|
|
21
|
+
private createBatch;
|
|
22
|
+
writeTransactions(items: KeyValue[], limit: number): Promise<boolean>;
|
|
23
|
+
createWriteTransactions(items: KeyValue[], limit: number): KeyValue[][];
|
|
24
|
+
createUpdateParams(params: InputUpdate): KeyValue;
|
|
25
|
+
private formatUpdateExpression;
|
|
26
|
+
private formatUpdateExpressionRemove;
|
|
27
|
+
getId(table: string, entity: string, username: string, quantity?: number): Promise<number>;
|
|
28
|
+
validatePermission(table: string, entity: string, action: string, profile: string): Promise<string | undefined>;
|
|
29
|
+
}
|
package/jest.config.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
preset: 'ts-jest', // Usa ts-jest para compilar los archivos TypeScript antes de ejecutar las pruebas
|
|
3
|
+
testEnvironment: 'node', // Establece el entorno de prueba a 'node' (ya que estamos trabajando con DynamoDB en Node.js)
|
|
4
|
+
moduleNameMapper: {
|
|
5
|
+
// Si usas el alias de módulos, puedes configurarlos aquí
|
|
6
|
+
// Ejemplo: '^@libs/(.*)$': '<rootDir>/src/libs/$1',
|
|
7
|
+
},
|
|
8
|
+
};
|
|
9
|
+
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "inlaweb-lib-dynamodb",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"types": "dist/types/index.d.ts",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "tsc",
|
|
8
|
+
"test": "jest --coverage"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@aws-lambda-powertools/logger": "^2.15.0",
|
|
12
|
+
"@aws-sdk/client-dynamodb": "^3.731.1",
|
|
13
|
+
"@aws-sdk/lib-dynamodb": "^3.749.0",
|
|
14
|
+
"@types/aws-lambda": "^8.10.147",
|
|
15
|
+
"moment-timezone": "^0.5.47"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@types/jest": "^29.5.14",
|
|
19
|
+
"jest": "^29.7.0",
|
|
20
|
+
"ts-jest": "^29.2.5",
|
|
21
|
+
"typescript": "^5.7.3"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [],
|
|
24
|
+
"author": "",
|
|
25
|
+
"license": "ISC",
|
|
26
|
+
"description": ""
|
|
27
|
+
}
|
package/readme.MD
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { ReturnConsumedCapacity, ReturnValue, ReturnItemCollectionMetrics } from "@aws-sdk/client-dynamodb";
|
|
2
|
+
|
|
3
|
+
export interface ParamsPut {
|
|
4
|
+
TableName: string;
|
|
5
|
+
Item: KeyValue;
|
|
6
|
+
ReturnConsumedCapacity?: ReturnConsumedCapacity;
|
|
7
|
+
ReturnItemCollectionMetrics?: ReturnItemCollectionMetrics;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface ParamsGet {
|
|
11
|
+
TableName: string;
|
|
12
|
+
Key: KeyValue;
|
|
13
|
+
ProjectionExpression?: string;
|
|
14
|
+
ExpressionAttributeNames?: KeyValue;
|
|
15
|
+
ReturnConsumedCapacity?: ReturnConsumedCapacity;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface ParamsQuery {
|
|
19
|
+
TableName: string;
|
|
20
|
+
KeyConditionExpression: string;
|
|
21
|
+
ExpressionAttributeNames: KeyValue;
|
|
22
|
+
ExpressionAttributeValues: KeyValue;
|
|
23
|
+
ProjectionExpression?: string;
|
|
24
|
+
ExclusiveStartKey?: KeyValue;
|
|
25
|
+
Limit?: number;
|
|
26
|
+
ScanIndexForward?: boolean;
|
|
27
|
+
IndexName?: string;
|
|
28
|
+
FilterExpression?: string;
|
|
29
|
+
ConsistentRead?: boolean;
|
|
30
|
+
ReturnConsumedCapacity?: ReturnConsumedCapacity;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface ParamsUpdate {
|
|
34
|
+
TableName: string;
|
|
35
|
+
Key: KeyValue;
|
|
36
|
+
UpdateExpression: string;
|
|
37
|
+
ExpressionAttributeNames: KeyValue;
|
|
38
|
+
ExpressionAttributeValues: KeyValue;
|
|
39
|
+
ReturnValues?: ReturnValue;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface ProjectionExpression {
|
|
43
|
+
projectionExpression: string;
|
|
44
|
+
expressionAttributeNames: KeyValue;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface SearchParameters {
|
|
48
|
+
indexName: string;
|
|
49
|
+
parameters: KeyValue[];
|
|
50
|
+
projectionExpression?: string;
|
|
51
|
+
exclusiveStartKey?: KeyValue;
|
|
52
|
+
scanIndexForward?: boolean;
|
|
53
|
+
limit?: number;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface InputUpdate {
|
|
57
|
+
table: string;
|
|
58
|
+
PK: string;
|
|
59
|
+
SK: string;
|
|
60
|
+
username: string;
|
|
61
|
+
item: KeyValue;
|
|
62
|
+
setAttributes: string[];
|
|
63
|
+
addAttributes?: string[];
|
|
64
|
+
removeAttributes?: string[];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface KeyValue {
|
|
68
|
+
[key: string]: any;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export type Operation = "SET" | "ADD" | "REMOVE";
|