ag-common 0.0.744 → 0.0.745
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 +134 -2
- 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 +8 -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 */
|
|
@@ -133,10 +133,10 @@ const queryDynamo = (params) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
133
133
|
items.push(...result.Items);
|
|
134
134
|
}
|
|
135
135
|
startKey = result.LastEvaluatedKey;
|
|
136
|
+
// If we have a limit and we've reached it, stop processing
|
|
136
137
|
if (params.limit && items.length >= params.limit) {
|
|
137
138
|
return {
|
|
138
139
|
data: items.slice(0, params.limit),
|
|
139
|
-
startKey,
|
|
140
140
|
};
|
|
141
141
|
}
|
|
142
142
|
} while (startKey && Object.keys(startKey).length > 0);
|
|
@@ -165,6 +165,138 @@ const scan = (tableName, options) => __awaiter(void 0, void 0, void 0, function*
|
|
|
165
165
|
}
|
|
166
166
|
});
|
|
167
167
|
exports.scan = scan;
|
|
168
|
+
/**
|
|
169
|
+
* Batch query DynamoDB using PartiQL to query multiple partition key values at once
|
|
170
|
+
*
|
|
171
|
+
* This function uses PartiQL's IN operator to query multiple partition key values
|
|
172
|
+
* in a single request, which is more efficient than making multiple individual queries.
|
|
173
|
+
*
|
|
174
|
+
* Note: AWS has limits on the number of items in WHERE IN queries:
|
|
175
|
+
* - Primary index: 100 items max
|
|
176
|
+
* - Secondary index (GSI/LSI): 50 items max
|
|
177
|
+
* This function automatically chunks requests to stay within these limits.
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* // Basic usage with multiple partition keys
|
|
181
|
+
* const result = await batchQueryDynamo<User>({
|
|
182
|
+
* tableName: 'Users',
|
|
183
|
+
* pkName: 'userId',
|
|
184
|
+
* pkValues: ['user1', 'user2', 'user3']
|
|
185
|
+
* });
|
|
186
|
+
*
|
|
187
|
+
* @example
|
|
188
|
+
* // With filter and limit
|
|
189
|
+
* const result = await batchQueryDynamo<Product>({
|
|
190
|
+
* tableName: 'Products',
|
|
191
|
+
* pkName: 'categoryId',
|
|
192
|
+
* pkValues: ['electronics', 'books'],
|
|
193
|
+
* filter: {
|
|
194
|
+
* filterExpression: 'price < :maxPrice',
|
|
195
|
+
* attrNames: {},
|
|
196
|
+
* attrValues: { ':maxPrice': 100 }
|
|
197
|
+
* },
|
|
198
|
+
* limit: 50
|
|
199
|
+
* });
|
|
200
|
+
*
|
|
201
|
+
* @param params - The batch query parameters
|
|
202
|
+
* @returns Promise resolving to query results or error
|
|
203
|
+
*/
|
|
204
|
+
const batchQueryDynamo = (params) => __awaiter(void 0, void 0, void 0, function* () {
|
|
205
|
+
try {
|
|
206
|
+
if (params.pkValues.length === 0) {
|
|
207
|
+
return { data: [] };
|
|
208
|
+
}
|
|
209
|
+
// Determine chunk size based on whether we're using a secondary index
|
|
210
|
+
const isSecondaryIndex = !!params.indexName;
|
|
211
|
+
const chunkSize = isSecondaryIndex ? 50 : 100;
|
|
212
|
+
// Chunk the partition key values
|
|
213
|
+
const chunks = [];
|
|
214
|
+
for (let i = 0; i < params.pkValues.length; i += chunkSize) {
|
|
215
|
+
chunks.push(params.pkValues.slice(i, i + chunkSize));
|
|
216
|
+
}
|
|
217
|
+
const allItems = [];
|
|
218
|
+
let totalProcessed = 0;
|
|
219
|
+
// Process each chunk
|
|
220
|
+
for (const chunk of chunks) {
|
|
221
|
+
const result = yield executePartiQLQuery(Object.assign(Object.assign({}, params), { pkValues: chunk }));
|
|
222
|
+
if ('error' in result) {
|
|
223
|
+
return result;
|
|
224
|
+
}
|
|
225
|
+
allItems.push(...result.data);
|
|
226
|
+
totalProcessed += result.data.length;
|
|
227
|
+
// If we have a limit and we've reached it, stop processing
|
|
228
|
+
if (params.limit && totalProcessed >= params.limit) {
|
|
229
|
+
return {
|
|
230
|
+
data: allItems.slice(0, params.limit),
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return {
|
|
235
|
+
data: allItems,
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
catch (e) {
|
|
239
|
+
return { error: e.toString() };
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
exports.batchQueryDynamo = batchQueryDynamo;
|
|
243
|
+
/**
|
|
244
|
+
* Helper function to execute a single PartiQL query for a chunk of partition keys
|
|
245
|
+
*/
|
|
246
|
+
const executePartiQLQuery = (params) => __awaiter(void 0, void 0, void 0, function* () {
|
|
247
|
+
try {
|
|
248
|
+
// Build the PartiQL WHERE clause for multiple partition keys
|
|
249
|
+
const pkPlaceholders = params.pkValues.map(() => '?').join(', ');
|
|
250
|
+
let whereClause = `"${params.pkName}" IN (${pkPlaceholders})`;
|
|
251
|
+
// Build parameters array for PartiQL (positional parameters)
|
|
252
|
+
const parameters = [...params.pkValues];
|
|
253
|
+
// Add filter conditions if provided
|
|
254
|
+
if (params.filter) {
|
|
255
|
+
// For filters, we need to replace the named parameters with positional ones
|
|
256
|
+
let filterExpression = params.filter.filterExpression;
|
|
257
|
+
if (params.filter.attrValues) {
|
|
258
|
+
Object.entries(params.filter.attrValues).forEach(([key, value]) => {
|
|
259
|
+
filterExpression = filterExpression.replace(new RegExp(key.replace(':', '\\:'), 'g'), '?');
|
|
260
|
+
parameters.push(value);
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
whereClause += ` AND ${filterExpression}`;
|
|
264
|
+
}
|
|
265
|
+
// Build the PartiQL statement
|
|
266
|
+
const tableName = params.indexName
|
|
267
|
+
? `"${params.tableName}"."${params.indexName}"`
|
|
268
|
+
: `"${params.tableName}"`;
|
|
269
|
+
const statement = `SELECT * FROM ${tableName} WHERE ${whereClause}`;
|
|
270
|
+
const allItems = [];
|
|
271
|
+
let nextToken;
|
|
272
|
+
// Loop until all results are retrieved
|
|
273
|
+
do {
|
|
274
|
+
const executeParams = {
|
|
275
|
+
Statement: statement,
|
|
276
|
+
Parameters: parameters,
|
|
277
|
+
Limit: params.limit,
|
|
278
|
+
NextToken: nextToken,
|
|
279
|
+
};
|
|
280
|
+
const result = yield (0, withRetry_1.withRetry)(() => _1.dynamoDb.send(new lib_dynamodb_1.ExecuteStatementCommand(executeParams)), 'batchQueryDynamo');
|
|
281
|
+
if (result.Items) {
|
|
282
|
+
allItems.push(...result.Items);
|
|
283
|
+
}
|
|
284
|
+
nextToken = result.NextToken;
|
|
285
|
+
// If we have a limit and we've reached it, stop processing
|
|
286
|
+
if (params.limit && allItems.length >= params.limit) {
|
|
287
|
+
return {
|
|
288
|
+
data: allItems.slice(0, params.limit),
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
} while (nextToken);
|
|
292
|
+
return {
|
|
293
|
+
data: allItems,
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
catch (e) {
|
|
297
|
+
return { error: e.toString() };
|
|
298
|
+
}
|
|
299
|
+
});
|
|
168
300
|
function queryWithGenerator(params) {
|
|
169
301
|
return __asyncGenerator(this, arguments, function* queryWithGenerator_1() {
|
|
170
302
|
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,15 @@ 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;
|
|
42
40
|
}
|
|
41
|
+
export interface DynamoBatchQueryParams {
|
|
42
|
+
tableName: string;
|
|
43
|
+
pkName: string;
|
|
44
|
+
pkValues: (string | number)[];
|
|
45
|
+
indexName?: string;
|
|
46
|
+
limit?: number;
|
|
47
|
+
filter?: DynamoFilter;
|
|
48
|
+
}
|
|
43
49
|
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