ag-common 0.0.902 → 0.0.904
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/batch.d.ts +8 -0
- package/dist/api/helpers/dynamo/batch.js +28 -0
- package/dist/api/helpers/dynamo/delete.js +8 -12
- package/dist/api/helpers/dynamo/get.js +10 -0
- package/dist/api/helpers/dynamo/set.js +6 -7
- package/dist/api/helpers/dynamo/types.d.ts +2 -0
- package/package.json +26 -32
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type BatchWriteCommandInput } from "@aws-sdk/lib-dynamodb";
|
|
2
|
+
export type DynamoWriteRequest = NonNullable<NonNullable<BatchWriteCommandInput["RequestItems"]>[string]>[number];
|
|
3
|
+
export declare const sendAllBatchRequests: ({ maxRetries, operationName, requests, tableName, }: {
|
|
4
|
+
maxRetries?: number | null;
|
|
5
|
+
operationName: string;
|
|
6
|
+
requests: DynamoWriteRequest[];
|
|
7
|
+
tableName: string;
|
|
8
|
+
}) => Promise<void>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sendAllBatchRequests = void 0;
|
|
4
|
+
const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb");
|
|
5
|
+
const _1 = require(".");
|
|
6
|
+
const sleep_1 = require("../../../common/helpers/sleep");
|
|
7
|
+
const withRetry_1 = require("../../../common/helpers/withRetry");
|
|
8
|
+
const sendAllBatchRequests = async ({ maxRetries = 3, operationName, requests, tableName, }) => {
|
|
9
|
+
let pending = requests;
|
|
10
|
+
let unprocessedRetries = 0;
|
|
11
|
+
while (pending.length > 0) {
|
|
12
|
+
// oxlint-disable-next-line no-await-in-loop -- each request depends on DynamoDB's unprocessed set
|
|
13
|
+
const result = await (0, withRetry_1.withRetry)(() => _1.dynamoDb.send(new lib_dynamodb_1.BatchWriteCommand({
|
|
14
|
+
RequestItems: { [tableName]: pending },
|
|
15
|
+
})), operationName, { maxRetries });
|
|
16
|
+
pending = result.UnprocessedItems?.[tableName] ?? [];
|
|
17
|
+
if (pending.length === 0) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (maxRetries !== null && unprocessedRetries >= maxRetries) {
|
|
21
|
+
throw new Error(`${operationName}: ${pending.length} items remained unprocessed`);
|
|
22
|
+
}
|
|
23
|
+
unprocessedRetries += 1;
|
|
24
|
+
// oxlint-disable-next-line no-await-in-loop -- unprocessed writes require backoff before retrying
|
|
25
|
+
await (0, sleep_1.sleep)(Math.min(2 ** unprocessedRetries * 25, 2000));
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
exports.sendAllBatchRequests = sendAllBatchRequests;
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.wipeTable = exports.batchDelete = void 0;
|
|
4
|
-
const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb");
|
|
5
|
-
const _1 = require(".");
|
|
6
4
|
const array_1 = require("../../../common/helpers/array");
|
|
7
5
|
const async_1 = require("../../../common/helpers/async");
|
|
8
|
-
const
|
|
6
|
+
const batch_1 = require("./batch");
|
|
9
7
|
const get_1 = require("./get");
|
|
10
8
|
const batchDelete = async (params) => {
|
|
11
9
|
try {
|
|
@@ -13,15 +11,13 @@ const batchDelete = async (params) => {
|
|
|
13
11
|
const chunked = (0, array_1.chunk)(params.keys, batchSize);
|
|
14
12
|
let processed = 0;
|
|
15
13
|
await (0, async_1.asyncForEach)(chunked, async (chunk) => {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
await (0, withRetry_1.withRetry)(() => _1.dynamoDb.send(new lib_dynamodb_1.BatchWriteCommand(batchDeleteParams)), `batchdelete ${processed}/${params.keys.length}. size=${batchSize}`, {
|
|
24
|
-
maxRetries: maxRetries === undefined ? 3 : maxRetries,
|
|
14
|
+
await (0, batch_1.sendAllBatchRequests)({
|
|
15
|
+
tableName: params.tableName,
|
|
16
|
+
requests: chunk.map((key) => ({
|
|
17
|
+
DeleteRequest: { Key: { [params.pkName]: key } },
|
|
18
|
+
})),
|
|
19
|
+
operationName: `batchdelete ${processed}/${params.keys.length}. size=${batchSize}`,
|
|
20
|
+
maxRetries,
|
|
25
21
|
});
|
|
26
22
|
processed += chunk.length;
|
|
27
23
|
});
|
|
@@ -38,11 +38,16 @@ const executeQuery = async (params, exclusiveStartKey) => {
|
|
|
38
38
|
eav[`:${skName.toLowerCase()}`] = skValue;
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
|
+
const projectionAttrs = params.requiredAttributeList?.reduce((acc, attr, index) => {
|
|
42
|
+
acc[`#proj${index}`] = attr;
|
|
43
|
+
return acc;
|
|
44
|
+
}, {});
|
|
41
45
|
const queryParams = {
|
|
42
46
|
TableName: params.tableName,
|
|
43
47
|
KeyConditionExpression: kce,
|
|
44
48
|
ExpressionAttributeNames: {
|
|
45
49
|
...ean,
|
|
50
|
+
...projectionAttrs,
|
|
46
51
|
...params.filter?.attrNames,
|
|
47
52
|
},
|
|
48
53
|
ExpressionAttributeValues: {
|
|
@@ -53,6 +58,11 @@ const executeQuery = async (params, exclusiveStartKey) => {
|
|
|
53
58
|
Limit: params.limit === -1 ? undefined : params.limit,
|
|
54
59
|
IndexName: params.indexName,
|
|
55
60
|
ExclusiveStartKey: exclusiveStartKey,
|
|
61
|
+
...(params.requiredAttributeList && {
|
|
62
|
+
ProjectionExpression: params.requiredAttributeList
|
|
63
|
+
.map((_, index) => `#proj${index}`)
|
|
64
|
+
.join(", "),
|
|
65
|
+
}),
|
|
56
66
|
...(params.filter && {
|
|
57
67
|
FilterExpression: params.filter.filterExpression,
|
|
58
68
|
...(params.filter.attrValues && {
|
|
@@ -6,6 +6,7 @@ const _1 = require(".");
|
|
|
6
6
|
const array_1 = require("../../../common/helpers/array");
|
|
7
7
|
const async_1 = require("../../../common/helpers/async");
|
|
8
8
|
const withRetry_1 = require("../../../common/helpers/withRetry");
|
|
9
|
+
const batch_1 = require("./batch");
|
|
9
10
|
const putDynamo = async (item, tableName, opt) => {
|
|
10
11
|
const putParams = {
|
|
11
12
|
TableName: tableName,
|
|
@@ -32,13 +33,11 @@ const batchWrite = async (tableName, items, opt) => {
|
|
|
32
33
|
let processed = 0;
|
|
33
34
|
const chunked = (0, array_1.chunk)(items, batchSize);
|
|
34
35
|
await (0, async_1.asyncForEach)(chunked, async (chunk) => {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
await (0, withRetry_1.withRetry)(() => _1.dynamoDb.send(new lib_dynamodb_1.BatchWriteCommand(batchWriteParams)), `batchwrite ${processed}/${items.length}. size=${batchSize}`, {
|
|
41
|
-
maxRetries: opt?.maxRetries === undefined ? 3 : opt.maxRetries,
|
|
36
|
+
await (0, batch_1.sendAllBatchRequests)({
|
|
37
|
+
tableName,
|
|
38
|
+
requests: chunk.map((Item) => ({ PutRequest: { Item } })),
|
|
39
|
+
operationName: `batchwrite ${processed}/${items.length}. size=${batchSize}`,
|
|
40
|
+
maxRetries: opt?.maxRetries,
|
|
42
41
|
});
|
|
43
42
|
processed += chunk.length;
|
|
44
43
|
});
|
|
@@ -53,6 +53,8 @@ export interface DynamoQueryParams {
|
|
|
53
53
|
*/
|
|
54
54
|
limit?: number;
|
|
55
55
|
filter?: DynamoFilter;
|
|
56
|
+
/** Return only these attributes. */
|
|
57
|
+
requiredAttributeList?: string[];
|
|
56
58
|
sortAscending?: boolean;
|
|
57
59
|
/** default 3, set to null to disable retries */
|
|
58
60
|
maxRetries?: number | null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ag-common",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.904",
|
|
4
4
|
"license": "ISC",
|
|
5
5
|
"author": "admin@gec.dev",
|
|
6
6
|
"repository": {
|
|
@@ -15,18 +15,18 @@
|
|
|
15
15
|
"main": "./dist/index.js",
|
|
16
16
|
"types": "./dist/index.d.ts",
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@aws-sdk/client-acm": "^3.
|
|
19
|
-
"@aws-sdk/client-apigatewaymanagementapi": "^3.
|
|
20
|
-
"@aws-sdk/client-dynamodb": "^3.
|
|
21
|
-
"@aws-sdk/client-s3": "^3.
|
|
22
|
-
"@aws-sdk/client-ses": "^3.
|
|
23
|
-
"@aws-sdk/client-sqs": "^3.
|
|
24
|
-
"@aws-sdk/client-sts": "^3.
|
|
25
|
-
"@aws-sdk/lib-dynamodb": "^3.
|
|
26
|
-
"@aws-sdk/s3-presigned-post": "^3.
|
|
27
|
-
"@aws-sdk/s3-request-presigner": "^3.
|
|
18
|
+
"@aws-sdk/client-acm": "^3.1121.0",
|
|
19
|
+
"@aws-sdk/client-apigatewaymanagementapi": "^3.1121.0",
|
|
20
|
+
"@aws-sdk/client-dynamodb": "^3.1121.0",
|
|
21
|
+
"@aws-sdk/client-s3": "^3.1121.0",
|
|
22
|
+
"@aws-sdk/client-ses": "^3.1121.0",
|
|
23
|
+
"@aws-sdk/client-sqs": "^3.1121.0",
|
|
24
|
+
"@aws-sdk/client-sts": "^3.1121.0",
|
|
25
|
+
"@aws-sdk/lib-dynamodb": "^3.1121.0",
|
|
26
|
+
"@aws-sdk/s3-presigned-post": "^3.1121.0",
|
|
27
|
+
"@aws-sdk/s3-request-presigner": "^3.1121.0",
|
|
28
28
|
"@azure/cosmos": "^4.10.0",
|
|
29
|
-
"@google/genai": "^2.
|
|
29
|
+
"@google/genai": "^2.19.0",
|
|
30
30
|
"@radix-ui/react-accordion": "^1.2.20",
|
|
31
31
|
"@radix-ui/react-avatar": "^1.2.6",
|
|
32
32
|
"@radix-ui/react-checkbox": "^1.3.11",
|
|
@@ -44,38 +44,32 @@
|
|
|
44
44
|
"clsx": "^2.1.1",
|
|
45
45
|
"jsonwebtoken": "^9.0.3",
|
|
46
46
|
"jwks-rsa": "^4.1.0",
|
|
47
|
-
"lucide-react": "^1.
|
|
47
|
+
"lucide-react": "^1.37.0",
|
|
48
48
|
"node-cache": "^5.1.2",
|
|
49
49
|
"react": "^19.2.8",
|
|
50
50
|
"react-dom": "^19.2.8",
|
|
51
51
|
"tailwind-merge": "^3.6.0",
|
|
52
|
-
"zod": "^4.4
|
|
52
|
+
"zod": "^4.5.4"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"@storybook/addon-docs": "^10.5.
|
|
56
|
-
"@storybook/react": "^10.5.
|
|
57
|
-
"@storybook/react-vite": "^10.5.4",
|
|
55
|
+
"@storybook/addon-docs": "^10.5.10",
|
|
56
|
+
"@storybook/react-vite": "^10.5.10",
|
|
58
57
|
"@tailwindcss/postcss": "^4.3.3",
|
|
59
58
|
"@types/jsonwebtoken": "^9.0.10",
|
|
60
|
-
"@types/node": "^26.
|
|
61
|
-
"@types/react": "^19.2.
|
|
62
|
-
"@types/react-dom": "^19.2.
|
|
63
|
-
"aws-cdk-lib": "^2.
|
|
59
|
+
"@types/node": "^26.4.0",
|
|
60
|
+
"@types/react": "^19.2.18",
|
|
61
|
+
"@types/react-dom": "^19.2.5",
|
|
62
|
+
"aws-cdk-lib": "^2.267.0",
|
|
64
63
|
"constructs": "^10.8.1",
|
|
65
|
-
"
|
|
66
|
-
"eslint-config-e7npm": "0.1.62",
|
|
67
|
-
"globstar": "^1.0.0",
|
|
68
|
-
"jiti": "^2.7.0",
|
|
69
|
-
"oxfmt": "^0.60.0",
|
|
70
|
-
"oxlint": "^1.75.0",
|
|
64
|
+
"eslint-config-e7npm": "^0.1.66",
|
|
71
65
|
"rimraf": "^6.1.3",
|
|
72
|
-
"storybook": "^10.5.
|
|
66
|
+
"storybook": "^10.5.10",
|
|
73
67
|
"tailwindcss": "^4.3.3",
|
|
74
|
-
"tsx": "^4.23.
|
|
68
|
+
"tsx": "^4.23.13",
|
|
75
69
|
"typescript": "^7.0.2"
|
|
76
70
|
},
|
|
77
71
|
"peerDependencies": {
|
|
78
|
-
"aws-cdk-lib": "^2.
|
|
72
|
+
"aws-cdk-lib": "^2.267.0",
|
|
79
73
|
"constructs": "^10.0.0"
|
|
80
74
|
},
|
|
81
75
|
"scripts": {
|
|
@@ -84,8 +78,8 @@
|
|
|
84
78
|
"lint": "e7-oxlint --config .oxlintrc.json --deny-warnings . && pnpm run typecheck",
|
|
85
79
|
"typecheck": "tsc --noEmit",
|
|
86
80
|
"build": "rimraf dist && tsc -p tsconfig.build.json",
|
|
87
|
-
"start": "
|
|
81
|
+
"start": "storybook dev -p 6006 --no-open",
|
|
88
82
|
"build-storybook": "storybook build -o docs --quiet",
|
|
89
|
-
"test": "
|
|
83
|
+
"test": "tsx --test \"src/tests/**/*.test.ts\""
|
|
90
84
|
}
|
|
91
85
|
}
|