ag-common 0.0.744 → 0.0.746
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/dist/api/helpers/dynamo/get.d.ts +39 -8
- package/dist/api/helpers/dynamo/get.js +137 -3
- package/dist/api/helpers/dynamo/index.d.ts +1 -6
- package/dist/api/helpers/dynamo/index.js +2 -2
- package/dist/api/helpers/dynamo/types.d.ts +9 -2
- package/dist/api/helpers/withRetry.js +4 -2
- package/dist/ui/components/BarChart/Base.js +1 -0
- package/package.json +1 -1
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import type { Key } from '../../types';
|
|
2
1
|
import type { DynamoDBResult } from './types';
|
|
3
|
-
import type { DynamoQueryParams, ScanOptions } from './types';
|
|
2
|
+
import type { DynamoBatchQueryParams, DynamoQueryParams, ScanOptions } from './types';
|
|
4
3
|
export declare const getItemsDynamo: <T>(params: {
|
|
5
4
|
tableName: string;
|
|
6
5
|
items: {
|
|
@@ -13,13 +12,45 @@ export declare const getItemDynamo: <T>(params: {
|
|
|
13
12
|
pkName: string;
|
|
14
13
|
pkValue: string;
|
|
15
14
|
}) => Promise<DynamoDBResult<T>>;
|
|
16
|
-
export declare const queryDynamo: <T>(params: DynamoQueryParams) => Promise<
|
|
17
|
-
data: T[];
|
|
18
|
-
startKey?: Key;
|
|
19
|
-
} | {
|
|
20
|
-
error: string;
|
|
21
|
-
}>;
|
|
15
|
+
export declare const queryDynamo: <T>(params: DynamoQueryParams) => Promise<DynamoDBResult<T[]>>;
|
|
22
16
|
export declare const scan: <T>(tableName: string, options?: ScanOptions) => Promise<DynamoDBResult<T[]>>;
|
|
17
|
+
/**
|
|
18
|
+
* Batch query DynamoDB using PartiQL to query multiple partition key values at once
|
|
19
|
+
*
|
|
20
|
+
* This function uses PartiQL's IN operator to query multiple partition key values
|
|
21
|
+
* in a single request, which is more efficient than making multiple individual queries.
|
|
22
|
+
*
|
|
23
|
+
* Note: AWS has limits on the number of items in WHERE IN queries:
|
|
24
|
+
* - Primary index: 100 items max
|
|
25
|
+
* - Secondary index (GSI/LSI): 50 items max
|
|
26
|
+
* This function automatically chunks requests to stay within these limits.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* // Basic usage with multiple partition keys
|
|
30
|
+
* const result = await batchQueryDynamo<User>({
|
|
31
|
+
* tableName: 'Users',
|
|
32
|
+
* pkName: 'userId',
|
|
33
|
+
* pkValues: ['user1', 'user2', 'user3']
|
|
34
|
+
* });
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* // With filter and limit
|
|
38
|
+
* const result = await batchQueryDynamo<Product>({
|
|
39
|
+
* tableName: 'Products',
|
|
40
|
+
* pkName: 'categoryId',
|
|
41
|
+
* pkValues: ['electronics', 'books'],
|
|
42
|
+
* filter: {
|
|
43
|
+
* filterExpression: 'price < :maxPrice',
|
|
44
|
+
* attrNames: {},
|
|
45
|
+
* attrValues: { ':maxPrice': 100 }
|
|
46
|
+
* },
|
|
47
|
+
* limit: 50
|
|
48
|
+
* });
|
|
49
|
+
*
|
|
50
|
+
* @param params - The batch query parameters
|
|
51
|
+
* @returns Promise resolving to query results or error
|
|
52
|
+
*/
|
|
53
|
+
export declare const batchQueryDynamo: <T>(params: DynamoBatchQueryParams) => Promise<DynamoDBResult<T[]>>;
|
|
23
54
|
export declare function queryWithGenerator<T>(params: DynamoQueryParams & {
|
|
24
55
|
/** how many to return in query generator. default 100 */
|
|
25
56
|
BATCH_SIZE?: number;
|
|
@@ -22,7 +22,7 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar
|
|
|
22
22
|
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
|
|
23
23
|
};
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
exports.scan = exports.queryDynamo = exports.getItemDynamo = exports.getItemsDynamo = void 0;
|
|
25
|
+
exports.batchQueryDynamo = exports.scan = exports.queryDynamo = exports.getItemDynamo = exports.getItemsDynamo = void 0;
|
|
26
26
|
exports.queryWithGenerator = queryWithGenerator;
|
|
27
27
|
exports.scanWithGenerator = scanWithGenerator;
|
|
28
28
|
/* eslint-disable no-await-in-loop */
|
|
@@ -65,7 +65,9 @@ const executeQuery = (params, startKey) => __awaiter(void 0, void 0, void 0, fun
|
|
|
65
65
|
const queryParams = Object.assign({ TableName: params.tableName, KeyConditionExpression: kce, ExpressionAttributeNames: Object.assign(Object.assign({}, ean), (_b = params.filter) === null || _b === void 0 ? void 0 : _b.attrNames), ExpressionAttributeValues: Object.assign(Object.assign({}, eav), (_c = params.filter) === null || _c === void 0 ? void 0 : _c.attrValues), ScanIndexForward: (_d = params.sortAscending) !== null && _d !== void 0 ? _d : true, Limit: (_e = params.BATCH_SIZE) !== null && _e !== void 0 ? _e : params.limit, IndexName: params.indexName, ExclusiveStartKey: startKey }, (params.filter && Object.assign({ FilterExpression: params.filter.filterExpression }, (params.filter.attrValues && {
|
|
66
66
|
ExpressionAttributeValues: Object.assign(Object.assign({}, eav), params.filter.attrValues),
|
|
67
67
|
}))));
|
|
68
|
-
return (0, withRetry_1.withRetry)(() => _1.dynamoDb.send(new lib_dynamodb_1.QueryCommand(queryParams)), 'queryDynamo'
|
|
68
|
+
return (0, withRetry_1.withRetry)(() => _1.dynamoDb.send(new lib_dynamodb_1.QueryCommand(queryParams)), 'queryDynamo', {
|
|
69
|
+
maxRetries: params.alwaysRetry ? null : undefined,
|
|
70
|
+
});
|
|
69
71
|
});
|
|
70
72
|
/**
|
|
71
73
|
* Helper function that builds the scan parameters and executes the scan
|
|
@@ -133,10 +135,10 @@ const queryDynamo = (params) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
133
135
|
items.push(...result.Items);
|
|
134
136
|
}
|
|
135
137
|
startKey = result.LastEvaluatedKey;
|
|
138
|
+
// If we have a limit and we've reached it, stop processing
|
|
136
139
|
if (params.limit && items.length >= params.limit) {
|
|
137
140
|
return {
|
|
138
141
|
data: items.slice(0, params.limit),
|
|
139
|
-
startKey,
|
|
140
142
|
};
|
|
141
143
|
}
|
|
142
144
|
} while (startKey && Object.keys(startKey).length > 0);
|
|
@@ -165,6 +167,138 @@ const scan = (tableName, options) => __awaiter(void 0, void 0, void 0, function*
|
|
|
165
167
|
}
|
|
166
168
|
});
|
|
167
169
|
exports.scan = scan;
|
|
170
|
+
/**
|
|
171
|
+
* Batch query DynamoDB using PartiQL to query multiple partition key values at once
|
|
172
|
+
*
|
|
173
|
+
* This function uses PartiQL's IN operator to query multiple partition key values
|
|
174
|
+
* in a single request, which is more efficient than making multiple individual queries.
|
|
175
|
+
*
|
|
176
|
+
* Note: AWS has limits on the number of items in WHERE IN queries:
|
|
177
|
+
* - Primary index: 100 items max
|
|
178
|
+
* - Secondary index (GSI/LSI): 50 items max
|
|
179
|
+
* This function automatically chunks requests to stay within these limits.
|
|
180
|
+
*
|
|
181
|
+
* @example
|
|
182
|
+
* // Basic usage with multiple partition keys
|
|
183
|
+
* const result = await batchQueryDynamo<User>({
|
|
184
|
+
* tableName: 'Users',
|
|
185
|
+
* pkName: 'userId',
|
|
186
|
+
* pkValues: ['user1', 'user2', 'user3']
|
|
187
|
+
* });
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* // With filter and limit
|
|
191
|
+
* const result = await batchQueryDynamo<Product>({
|
|
192
|
+
* tableName: 'Products',
|
|
193
|
+
* pkName: 'categoryId',
|
|
194
|
+
* pkValues: ['electronics', 'books'],
|
|
195
|
+
* filter: {
|
|
196
|
+
* filterExpression: 'price < :maxPrice',
|
|
197
|
+
* attrNames: {},
|
|
198
|
+
* attrValues: { ':maxPrice': 100 }
|
|
199
|
+
* },
|
|
200
|
+
* limit: 50
|
|
201
|
+
* });
|
|
202
|
+
*
|
|
203
|
+
* @param params - The batch query parameters
|
|
204
|
+
* @returns Promise resolving to query results or error
|
|
205
|
+
*/
|
|
206
|
+
const batchQueryDynamo = (params) => __awaiter(void 0, void 0, void 0, function* () {
|
|
207
|
+
try {
|
|
208
|
+
if (params.pkValues.length === 0) {
|
|
209
|
+
return { data: [] };
|
|
210
|
+
}
|
|
211
|
+
// Determine chunk size based on whether we're using a secondary index
|
|
212
|
+
const isSecondaryIndex = !!params.indexName;
|
|
213
|
+
const chunkSize = isSecondaryIndex ? 50 : 100;
|
|
214
|
+
// Chunk the partition key values
|
|
215
|
+
const chunks = [];
|
|
216
|
+
for (let i = 0; i < params.pkValues.length; i += chunkSize) {
|
|
217
|
+
chunks.push(params.pkValues.slice(i, i + chunkSize));
|
|
218
|
+
}
|
|
219
|
+
const allItems = [];
|
|
220
|
+
let totalProcessed = 0;
|
|
221
|
+
// Process each chunk
|
|
222
|
+
for (const chunk of chunks) {
|
|
223
|
+
const result = yield executePartiQLQuery(Object.assign(Object.assign({}, params), { pkValues: chunk }));
|
|
224
|
+
if ('error' in result) {
|
|
225
|
+
return result;
|
|
226
|
+
}
|
|
227
|
+
allItems.push(...result.data);
|
|
228
|
+
totalProcessed += result.data.length;
|
|
229
|
+
// If we have a limit and we've reached it, stop processing
|
|
230
|
+
if (params.limit && totalProcessed >= params.limit) {
|
|
231
|
+
return {
|
|
232
|
+
data: allItems.slice(0, params.limit),
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return {
|
|
237
|
+
data: allItems,
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
catch (e) {
|
|
241
|
+
return { error: e.toString() };
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
exports.batchQueryDynamo = batchQueryDynamo;
|
|
245
|
+
/**
|
|
246
|
+
* Helper function to execute a single PartiQL query for a chunk of partition keys
|
|
247
|
+
*/
|
|
248
|
+
const executePartiQLQuery = (params) => __awaiter(void 0, void 0, void 0, function* () {
|
|
249
|
+
try {
|
|
250
|
+
// Build the PartiQL WHERE clause for multiple partition keys
|
|
251
|
+
const pkPlaceholders = params.pkValues.map(() => '?').join(', ');
|
|
252
|
+
let whereClause = `"${params.pkName}" IN (${pkPlaceholders})`;
|
|
253
|
+
// Build parameters array for PartiQL (positional parameters)
|
|
254
|
+
const parameters = [...params.pkValues];
|
|
255
|
+
// Add filter conditions if provided
|
|
256
|
+
if (params.filter) {
|
|
257
|
+
// For filters, we need to replace the named parameters with positional ones
|
|
258
|
+
let filterExpression = params.filter.filterExpression;
|
|
259
|
+
if (params.filter.attrValues) {
|
|
260
|
+
Object.entries(params.filter.attrValues).forEach(([key, value]) => {
|
|
261
|
+
filterExpression = filterExpression.replace(new RegExp(key.replace(':', '\\:'), 'g'), '?');
|
|
262
|
+
parameters.push(value);
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
whereClause += ` AND ${filterExpression}`;
|
|
266
|
+
}
|
|
267
|
+
// Build the PartiQL statement
|
|
268
|
+
const tableName = params.indexName
|
|
269
|
+
? `"${params.tableName}"."${params.indexName}"`
|
|
270
|
+
: `"${params.tableName}"`;
|
|
271
|
+
const statement = `SELECT * FROM ${tableName} WHERE ${whereClause}`;
|
|
272
|
+
const allItems = [];
|
|
273
|
+
let nextToken;
|
|
274
|
+
// Loop until all results are retrieved
|
|
275
|
+
do {
|
|
276
|
+
const executeParams = {
|
|
277
|
+
Statement: statement,
|
|
278
|
+
Parameters: parameters,
|
|
279
|
+
Limit: params.limit,
|
|
280
|
+
NextToken: nextToken,
|
|
281
|
+
};
|
|
282
|
+
const result = yield (0, withRetry_1.withRetry)(() => _1.dynamoDb.send(new lib_dynamodb_1.ExecuteStatementCommand(executeParams)), 'batchQueryDynamo');
|
|
283
|
+
if (result.Items) {
|
|
284
|
+
allItems.push(...result.Items);
|
|
285
|
+
}
|
|
286
|
+
nextToken = result.NextToken;
|
|
287
|
+
// If we have a limit and we've reached it, stop processing
|
|
288
|
+
if (params.limit && allItems.length >= params.limit) {
|
|
289
|
+
return {
|
|
290
|
+
data: allItems.slice(0, params.limit),
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
} while (nextToken);
|
|
294
|
+
return {
|
|
295
|
+
data: allItems,
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
catch (e) {
|
|
299
|
+
return { error: e.toString() };
|
|
300
|
+
}
|
|
301
|
+
});
|
|
168
302
|
function queryWithGenerator(params) {
|
|
169
303
|
return __asyncGenerator(this, arguments, function* queryWithGenerator_1() {
|
|
170
304
|
var _a;
|
|
@@ -19,12 +19,7 @@ export declare const getItemDynamo: <T>(params: {
|
|
|
19
19
|
pkName: string;
|
|
20
20
|
pkValue: string;
|
|
21
21
|
}[];
|
|
22
|
-
}) => Promise<import("./types").DynamoDBResult<T[]>>, queryDynamo: <T>(params: import("./types").DynamoQueryParams) => Promise<
|
|
23
|
-
data: T[];
|
|
24
|
-
startKey?: import("../..").Key;
|
|
25
|
-
} | {
|
|
26
|
-
error: string;
|
|
27
|
-
}>, queryWithGenerator: typeof getOps.queryWithGenerator, scan: <T>(tableName: string, options?: import("./types").ScanOptions) => Promise<import("./types").DynamoDBResult<T[]>>, scanWithGenerator: typeof getOps.scanWithGenerator;
|
|
22
|
+
}) => Promise<import("./types").DynamoDBResult<T[]>>, queryDynamo: <T>(params: import("./types").DynamoQueryParams) => Promise<import("./types").DynamoDBResult<T[]>>, batchQueryDynamo: <T>(params: import("./types").DynamoBatchQueryParams) => Promise<import("./types").DynamoDBResult<T[]>>, queryWithGenerator: typeof getOps.queryWithGenerator, scan: <T>(tableName: string, options?: import("./types").ScanOptions) => Promise<import("./types").DynamoDBResult<T[]>>, scanWithGenerator: typeof getOps.scanWithGenerator;
|
|
28
23
|
export declare const putDynamo: <T extends Record<string, unknown>>(item: T, tableName: string, opt?: {
|
|
29
24
|
pkName?: string;
|
|
30
25
|
}) => Promise<import("./types").DynamoDBResult<void>>, batchWrite: <T extends Record<string, unknown>>(tableName: string, items: T[], opt?: {
|
|
@@ -36,7 +36,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
36
36
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.wipeTable = exports.batchDelete = exports.getDynamoUpdates = exports.batchWrite = exports.putDynamo = exports.scanWithGenerator = exports.scan = exports.queryWithGenerator = exports.queryDynamo = exports.getItemsDynamo = exports.getItemDynamo = exports.setDynamo = exports.dynamoDb = void 0;
|
|
39
|
+
exports.wipeTable = exports.batchDelete = exports.getDynamoUpdates = exports.batchWrite = exports.putDynamo = exports.scanWithGenerator = exports.scan = exports.queryWithGenerator = exports.batchQueryDynamo = exports.queryDynamo = exports.getItemsDynamo = exports.getItemDynamo = exports.setDynamo = exports.dynamoDb = void 0;
|
|
40
40
|
const client_dynamodb_1 = require("@aws-sdk/client-dynamodb");
|
|
41
41
|
const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb");
|
|
42
42
|
const deleteOps = __importStar(require("./delete"));
|
|
@@ -59,7 +59,7 @@ exports.setDynamo = setDynamo;
|
|
|
59
59
|
// Initialize with default region
|
|
60
60
|
exports.dynamoDb = (0, exports.setDynamo)('ap-southeast-2');
|
|
61
61
|
// Export all operations
|
|
62
|
-
exports.getItemDynamo = getOps.getItemDynamo, exports.getItemsDynamo = getOps.getItemsDynamo, exports.queryDynamo = getOps.queryDynamo, exports.queryWithGenerator = getOps.queryWithGenerator, exports.scan = getOps.scan, exports.scanWithGenerator = getOps.scanWithGenerator;
|
|
62
|
+
exports.getItemDynamo = getOps.getItemDynamo, exports.getItemsDynamo = getOps.getItemsDynamo, exports.queryDynamo = getOps.queryDynamo, exports.batchQueryDynamo = getOps.batchQueryDynamo, exports.queryWithGenerator = getOps.queryWithGenerator, exports.scan = getOps.scan, exports.scanWithGenerator = getOps.scanWithGenerator;
|
|
63
63
|
exports.putDynamo = setOps.putDynamo, exports.batchWrite = setOps.batchWrite, exports.getDynamoUpdates = setOps.getDynamoUpdates;
|
|
64
64
|
exports.batchDelete = deleteOps.batchDelete, exports.wipeTable = deleteOps.wipeTable;
|
|
65
65
|
// Export types
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { Key } from '../../types';
|
|
2
1
|
export type DynamoDBError = {
|
|
3
2
|
error: string;
|
|
4
3
|
};
|
|
@@ -36,8 +35,16 @@ export interface DynamoQueryParams {
|
|
|
36
35
|
skOperator?: '=' | '<' | '>' | '<=' | '>=' | 'BETWEEN' | 'BEGINS_WITH';
|
|
37
36
|
indexName?: string;
|
|
38
37
|
limit?: number;
|
|
39
|
-
startKey?: Key;
|
|
40
38
|
filter?: DynamoFilter;
|
|
41
39
|
sortAscending?: boolean;
|
|
40
|
+
alwaysRetry?: boolean;
|
|
41
|
+
}
|
|
42
|
+
export interface DynamoBatchQueryParams {
|
|
43
|
+
tableName: string;
|
|
44
|
+
pkName: string;
|
|
45
|
+
pkValues: (string | number)[];
|
|
46
|
+
indexName?: string;
|
|
47
|
+
limit?: number;
|
|
48
|
+
filter?: DynamoFilter;
|
|
42
49
|
}
|
|
43
50
|
export declare const isError: <T>(result: DynamoDBResult<T>) => result is DynamoDBError;
|
|
@@ -10,6 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.withRetry = void 0;
|
|
13
|
+
/* eslint-disable no-await-in-loop */
|
|
13
14
|
const log_1 = require("../../common/helpers/log");
|
|
14
15
|
const sleep_1 = require("../../common/helpers/sleep");
|
|
15
16
|
const withRetry = (operation, operationName, opt) => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -23,10 +24,11 @@ const withRetry = (operation, operationName, opt) => __awaiter(void 0, void 0, v
|
|
|
23
24
|
}
|
|
24
25
|
catch (e) {
|
|
25
26
|
const error = e;
|
|
26
|
-
const errorString = error.toString().toLowerCase();
|
|
27
|
+
const errorString = error.toString().toLowerCase().replace(/\s+/gim, '');
|
|
27
28
|
if (errorString.includes('429') ||
|
|
28
29
|
errorString.includes('provisionedthroughputexceeded') ||
|
|
29
|
-
errorString.includes('
|
|
30
|
+
errorString.includes('toolarge') ||
|
|
31
|
+
errorString.includes('ratelimited')) {
|
|
30
32
|
retryCount++;
|
|
31
33
|
if (maxRetries !== null && retryCount >= maxRetries) {
|
|
32
34
|
(0, log_1.warn)(`${operationName}: Max retries exceeded`);
|
package/package.json
CHANGED