@exabugs/dynamodb-client 0.1.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/CHANGELOG.md +41 -0
- package/LICENSE +21 -0
- package/README.md +283 -0
- package/dist/client/Collection.d.ts +57 -0
- package/dist/client/Collection.d.ts.map +1 -0
- package/dist/client/Collection.js +174 -0
- package/dist/client/Collection.js.map +1 -0
- package/dist/client/Database.d.ts +35 -0
- package/dist/client/Database.d.ts.map +1 -0
- package/dist/client/Database.js +48 -0
- package/dist/client/Database.js.map +1 -0
- package/dist/client/DynamoClient.d.ts +43 -0
- package/dist/client/DynamoClient.d.ts.map +1 -0
- package/dist/client/DynamoClient.js +62 -0
- package/dist/client/DynamoClient.js.map +1 -0
- package/dist/client/FindCursor.d.ts +174 -0
- package/dist/client/FindCursor.d.ts.map +1 -0
- package/dist/client/FindCursor.js +256 -0
- package/dist/client/FindCursor.js.map +1 -0
- package/dist/client/aws-sigv4.d.ts +10 -0
- package/dist/client/aws-sigv4.d.ts.map +1 -0
- package/dist/client/aws-sigv4.js +54 -0
- package/dist/client/aws-sigv4.js.map +1 -0
- package/dist/client/index.cognito.d.ts +34 -0
- package/dist/client/index.cognito.d.ts.map +1 -0
- package/dist/client/index.cognito.js +30 -0
- package/dist/client/index.cognito.js.map +1 -0
- package/dist/client/index.d.ts +12 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.iam.d.ts +34 -0
- package/dist/client/index.iam.d.ts.map +1 -0
- package/dist/client/index.iam.js +28 -0
- package/dist/client/index.iam.js.map +1 -0
- package/dist/client/index.js +12 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/index.token.d.ts +33 -0
- package/dist/client/index.token.d.ts.map +1 -0
- package/dist/client/index.token.js +28 -0
- package/dist/client/index.token.js.map +1 -0
- package/dist/dynamodb.d.ts +20 -0
- package/dist/dynamodb.d.ts.map +1 -0
- package/dist/dynamodb.js +31 -0
- package/dist/dynamodb.js.map +1 -0
- package/dist/errors.d.ts +100 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +146 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/react-admin/dataProvider.d.ts +59 -0
- package/dist/integrations/react-admin/dataProvider.d.ts.map +1 -0
- package/dist/integrations/react-admin/dataProvider.js +364 -0
- package/dist/integrations/react-admin/dataProvider.js.map +1 -0
- package/dist/integrations/react-admin/index.d.ts +24 -0
- package/dist/integrations/react-admin/index.d.ts.map +1 -0
- package/dist/integrations/react-admin/index.js +23 -0
- package/dist/integrations/react-admin/index.js.map +1 -0
- package/dist/integrations/react-admin/types.d.ts +47 -0
- package/dist/integrations/react-admin/types.d.ts.map +1 -0
- package/dist/integrations/react-admin/types.js +5 -0
- package/dist/integrations/react-admin/types.js.map +1 -0
- package/dist/logger.d.ts +61 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +87 -0
- package/dist/logger.js.map +1 -0
- package/dist/scripts/repair-shadows.d.ts +3 -0
- package/dist/scripts/repair-shadows.d.ts.map +1 -0
- package/dist/scripts/repair-shadows.js +190 -0
- package/dist/scripts/repair-shadows.js.map +1 -0
- package/dist/server/handler.cjs +31378 -0
- package/dist/server/handler.cjs.map +7 -0
- package/dist/server/handler.d.ts +18 -0
- package/dist/server/handler.d.ts.map +1 -0
- package/dist/server/handler.js +435 -0
- package/dist/server/handler.js.map +1 -0
- package/dist/server/handler.zip +0 -0
- package/dist/server/index.d.ts +8 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +8 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/operations/deleteMany.d.ts +18 -0
- package/dist/server/operations/deleteMany.d.ts.map +1 -0
- package/dist/server/operations/deleteMany.js +222 -0
- package/dist/server/operations/deleteMany.js.map +1 -0
- package/dist/server/operations/deleteOne.d.ts +17 -0
- package/dist/server/operations/deleteOne.d.ts.map +1 -0
- package/dist/server/operations/deleteOne.js +87 -0
- package/dist/server/operations/deleteOne.js.map +1 -0
- package/dist/server/operations/find.d.ts +18 -0
- package/dist/server/operations/find.d.ts.map +1 -0
- package/dist/server/operations/find.js +382 -0
- package/dist/server/operations/find.js.map +1 -0
- package/dist/server/operations/findMany.d.ts +13 -0
- package/dist/server/operations/findMany.d.ts.map +1 -0
- package/dist/server/operations/findMany.js +61 -0
- package/dist/server/operations/findMany.js.map +1 -0
- package/dist/server/operations/findManyReference.d.ts +18 -0
- package/dist/server/operations/findManyReference.d.ts.map +1 -0
- package/dist/server/operations/findManyReference.js +150 -0
- package/dist/server/operations/findManyReference.js.map +1 -0
- package/dist/server/operations/findOne.d.ts +14 -0
- package/dist/server/operations/findOne.d.ts.map +1 -0
- package/dist/server/operations/findOne.js +56 -0
- package/dist/server/operations/findOne.js.map +1 -0
- package/dist/server/operations/insertMany.d.ts +19 -0
- package/dist/server/operations/insertMany.d.ts.map +1 -0
- package/dist/server/operations/insertMany.js +243 -0
- package/dist/server/operations/insertMany.js.map +1 -0
- package/dist/server/operations/insertOne.d.ts +18 -0
- package/dist/server/operations/insertOne.d.ts.map +1 -0
- package/dist/server/operations/insertOne.js +85 -0
- package/dist/server/operations/insertOne.js.map +1 -0
- package/dist/server/operations/updateMany.d.ts +20 -0
- package/dist/server/operations/updateMany.d.ts.map +1 -0
- package/dist/server/operations/updateMany.js +316 -0
- package/dist/server/operations/updateMany.js.map +1 -0
- package/dist/server/operations/updateOne.d.ts +20 -0
- package/dist/server/operations/updateOne.d.ts.map +1 -0
- package/dist/server/operations/updateOne.js +159 -0
- package/dist/server/operations/updateOne.js.map +1 -0
- package/dist/server/query/converter.d.ts +85 -0
- package/dist/server/query/converter.d.ts.map +1 -0
- package/dist/server/query/converter.js +161 -0
- package/dist/server/query/converter.js.map +1 -0
- package/dist/server/query/index.d.ts +5 -0
- package/dist/server/query/index.d.ts.map +1 -0
- package/dist/server/query/index.js +5 -0
- package/dist/server/query/index.js.map +1 -0
- package/dist/server/shadow/config.d.ts +147 -0
- package/dist/server/shadow/config.d.ts.map +1 -0
- package/dist/server/shadow/config.js +162 -0
- package/dist/server/shadow/config.js.map +1 -0
- package/dist/server/shadow/differ.d.ts +42 -0
- package/dist/server/shadow/differ.d.ts.map +1 -0
- package/dist/server/shadow/differ.js +66 -0
- package/dist/server/shadow/differ.js.map +1 -0
- package/dist/server/shadow/generator.d.ts +104 -0
- package/dist/server/shadow/generator.d.ts.map +1 -0
- package/dist/server/shadow/generator.js +148 -0
- package/dist/server/shadow/generator.js.map +1 -0
- package/dist/server/shadow/index.d.ts +11 -0
- package/dist/server/shadow/index.d.ts.map +1 -0
- package/dist/server/shadow/index.js +11 -0
- package/dist/server/shadow/index.js.map +1 -0
- package/dist/server/shadow/types.d.ts +44 -0
- package/dist/server/shadow/types.d.ts.map +1 -0
- package/dist/server/shadow/types.js +2 -0
- package/dist/server/shadow/types.js.map +1 -0
- package/dist/server/types.d.ts +295 -0
- package/dist/server/types.d.ts.map +1 -0
- package/dist/server/types.js +7 -0
- package/dist/server/types.js.map +1 -0
- package/dist/server/utils/auth.d.ts +43 -0
- package/dist/server/utils/auth.d.ts.map +1 -0
- package/dist/server/utils/auth.js +123 -0
- package/dist/server/utils/auth.js.map +1 -0
- package/dist/server/utils/bulkOperations.d.ts +81 -0
- package/dist/server/utils/bulkOperations.d.ts.map +1 -0
- package/dist/server/utils/bulkOperations.js +147 -0
- package/dist/server/utils/bulkOperations.js.map +1 -0
- package/dist/server/utils/chunking.d.ts +96 -0
- package/dist/server/utils/chunking.d.ts.map +1 -0
- package/dist/server/utils/chunking.js +225 -0
- package/dist/server/utils/chunking.js.map +1 -0
- package/dist/server/utils/dynamodb.d.ts +41 -0
- package/dist/server/utils/dynamodb.d.ts.map +1 -0
- package/dist/server/utils/dynamodb.js +83 -0
- package/dist/server/utils/dynamodb.js.map +1 -0
- package/dist/server/utils/filter.d.ts +152 -0
- package/dist/server/utils/filter.d.ts.map +1 -0
- package/dist/server/utils/filter.js +270 -0
- package/dist/server/utils/filter.js.map +1 -0
- package/dist/server/utils/pagination.d.ts +27 -0
- package/dist/server/utils/pagination.d.ts.map +1 -0
- package/dist/server/utils/pagination.js +56 -0
- package/dist/server/utils/pagination.js.map +1 -0
- package/dist/server/utils/timestamps.d.ts +31 -0
- package/dist/server/utils/timestamps.d.ts.map +1 -0
- package/dist/server/utils/timestamps.js +84 -0
- package/dist/server/utils/timestamps.js.map +1 -0
- package/dist/server/utils/ttl.d.ts +17 -0
- package/dist/server/utils/ttl.d.ts.map +1 -0
- package/dist/server/utils/ttl.js +62 -0
- package/dist/server/utils/ttl.js.map +1 -0
- package/dist/server/utils/validation.d.ts +40 -0
- package/dist/server/utils/validation.d.ts.map +1 -0
- package/dist/server/utils/validation.js +54 -0
- package/dist/server/utils/validation.js.map +1 -0
- package/dist/shadows/config.d.ts +54 -0
- package/dist/shadows/config.d.ts.map +1 -0
- package/dist/shadows/config.js +95 -0
- package/dist/shadows/config.js.map +1 -0
- package/dist/shadows/differ.d.ts +42 -0
- package/dist/shadows/differ.d.ts.map +1 -0
- package/dist/shadows/differ.js +66 -0
- package/dist/shadows/differ.js.map +1 -0
- package/dist/shadows/generator.d.ts +63 -0
- package/dist/shadows/generator.d.ts.map +1 -0
- package/dist/shadows/generator.js +107 -0
- package/dist/shadows/generator.js.map +1 -0
- package/dist/shadows/index.d.ts +15 -0
- package/dist/shadows/index.d.ts.map +1 -0
- package/dist/shadows/index.js +17 -0
- package/dist/shadows/index.js.map +1 -0
- package/dist/shadows/types.d.ts +44 -0
- package/dist/shadows/types.d.ts.map +1 -0
- package/dist/shadows/types.js +2 -0
- package/dist/shadows/types.js.map +1 -0
- package/dist/types.d.ts +165 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/ulid.d.ts +46 -0
- package/dist/ulid.d.ts.map +1 -0
- package/dist/ulid.js +66 -0
- package/dist/ulid.js.map +1 -0
- package/package.json +136 -0
- package/terraform/README.md +222 -0
- package/terraform/examples/advanced/README.md +129 -0
- package/terraform/examples/advanced/main.tf +158 -0
- package/terraform/examples/advanced/shadow.config.json +35 -0
- package/terraform/examples/advanced/variables.tf +28 -0
- package/terraform/examples/basic/README.md +53 -0
- package/terraform/examples/basic/main.tf +99 -0
- package/terraform/examples/basic/variables.tf +17 -0
- package/terraform/main.tf +159 -0
- package/terraform/outputs.tf +56 -0
- package/terraform/variables.tf +59 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { CognitoJwtPayload } from 'aws-jwt-verify/jwt-model';
|
|
2
|
+
/**
|
|
3
|
+
* JWT ペイロード(Cognito ID Token)
|
|
4
|
+
* aws-jwt-verify の CognitoJwtPayload を使用
|
|
5
|
+
*/
|
|
6
|
+
export type JwtPayload = CognitoJwtPayload;
|
|
7
|
+
/**
|
|
8
|
+
* Cognito JWT トークンを検証する(署名検証あり)
|
|
9
|
+
*
|
|
10
|
+
* aws-jwt-verify を使用して以下を検証:
|
|
11
|
+
* - 署名検証(JWKS を使用した RSA 署名検証)
|
|
12
|
+
* - 有効期限(exp)
|
|
13
|
+
* - 発行時刻(iat)
|
|
14
|
+
* - 発行者(iss)
|
|
15
|
+
* - オーディエンス(aud、clientId が指定されている場合)
|
|
16
|
+
* - token_use('id' トークンのみ許可)
|
|
17
|
+
*
|
|
18
|
+
* @param token - JWT トークン(Bearer プレフィックスなし)
|
|
19
|
+
* @param userPoolId - Cognito User Pool ID
|
|
20
|
+
* @param clientId - Cognito App Client ID(オプション)
|
|
21
|
+
* @returns 検証済みの JWT ペイロード
|
|
22
|
+
* @throws トークンが無効な場合
|
|
23
|
+
*/
|
|
24
|
+
export declare function verifyJwt(token: string, userPoolId: string, clientId?: string): Promise<JwtPayload>;
|
|
25
|
+
/**
|
|
26
|
+
* HTTP Authorization ヘッダーから JWT トークンを抽出する
|
|
27
|
+
*
|
|
28
|
+
* @param authHeader - Authorization ヘッダーの値
|
|
29
|
+
* @returns JWT トークン(Bearer プレフィックスなし)
|
|
30
|
+
* @throws ヘッダーの形式が不正な場合
|
|
31
|
+
*/
|
|
32
|
+
export declare function extractTokenFromHeader(authHeader: string | undefined): string;
|
|
33
|
+
/**
|
|
34
|
+
* HTTP リクエストから JWT トークンを検証する(ヘルパー関数)
|
|
35
|
+
*
|
|
36
|
+
* @param authHeader - Authorization ヘッダーの値
|
|
37
|
+
* @param userPoolId - Cognito User Pool ID
|
|
38
|
+
* @param clientId - Cognito App Client ID(オプション)
|
|
39
|
+
* @returns 検証済みの JWT ペイロード
|
|
40
|
+
* @throws トークンが無効な場合
|
|
41
|
+
*/
|
|
42
|
+
export declare function verifyAuthHeader(authHeader: string | undefined, userPoolId: string, clientId?: string): Promise<JwtPayload>;
|
|
43
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/server/utils/auth.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAMlE;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,iBAAiB,CAAC;AA+B3C;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,SAAS,CAC7B,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,UAAU,CAAC,CAyCrB;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAY7E;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,UAAU,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,UAAU,CAAC,CAGrB"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cognito JWT 検証ユーティリティ
|
|
3
|
+
* aws-jwt-verify を使用した署名検証を実装
|
|
4
|
+
*
|
|
5
|
+
* 要件: 9.1, 9.3
|
|
6
|
+
*/
|
|
7
|
+
import { CognitoJwtVerifier } from 'aws-jwt-verify';
|
|
8
|
+
import { AuthError, createLogger } from '../../index.js';
|
|
9
|
+
const logger = createLogger({ service: 'records-lambda' });
|
|
10
|
+
/**
|
|
11
|
+
* JWT Verifier インスタンス(Lambda コンテキスト間で再利用)
|
|
12
|
+
*
|
|
13
|
+
* aws-jwt-verify は内部で JWKS をキャッシュするため、
|
|
14
|
+
* グローバル変数として保持することでパフォーマンスを向上させる
|
|
15
|
+
*/
|
|
16
|
+
let verifierInstance = null;
|
|
17
|
+
/**
|
|
18
|
+
* JWT Verifier インスタンスを取得する(シングルトンパターン)
|
|
19
|
+
*
|
|
20
|
+
* @param userPoolId - Cognito User Pool ID
|
|
21
|
+
* @param clientId - Cognito App Client ID(オプション、指定時は aud を検証)
|
|
22
|
+
* @returns JWT Verifier インスタンス
|
|
23
|
+
*/
|
|
24
|
+
function getVerifier(userPoolId, clientId) {
|
|
25
|
+
if (!verifierInstance) {
|
|
26
|
+
logger.debug('Creating JWT verifier instance', { userPoolId, clientId });
|
|
27
|
+
verifierInstance = CognitoJwtVerifier.create({
|
|
28
|
+
userPoolId,
|
|
29
|
+
tokenUse: 'id', // ID トークンを検証
|
|
30
|
+
clientId: clientId || null, // undefined を null に変換(aws-jwt-verify の型要件)
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
return verifierInstance;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Cognito JWT トークンを検証する(署名検証あり)
|
|
37
|
+
*
|
|
38
|
+
* aws-jwt-verify を使用して以下を検証:
|
|
39
|
+
* - 署名検証(JWKS を使用した RSA 署名検証)
|
|
40
|
+
* - 有効期限(exp)
|
|
41
|
+
* - 発行時刻(iat)
|
|
42
|
+
* - 発行者(iss)
|
|
43
|
+
* - オーディエンス(aud、clientId が指定されている場合)
|
|
44
|
+
* - token_use('id' トークンのみ許可)
|
|
45
|
+
*
|
|
46
|
+
* @param token - JWT トークン(Bearer プレフィックスなし)
|
|
47
|
+
* @param userPoolId - Cognito User Pool ID
|
|
48
|
+
* @param clientId - Cognito App Client ID(オプション)
|
|
49
|
+
* @returns 検証済みの JWT ペイロード
|
|
50
|
+
* @throws トークンが無効な場合
|
|
51
|
+
*/
|
|
52
|
+
export async function verifyJwt(token, userPoolId, clientId) {
|
|
53
|
+
logger.debug('Verifying JWT token with signature validation');
|
|
54
|
+
try {
|
|
55
|
+
const verifier = getVerifier(userPoolId, clientId);
|
|
56
|
+
// aws-jwt-verify による完全な検証(署名検証を含む)
|
|
57
|
+
const payload = await verifier.verify(token);
|
|
58
|
+
logger.debug('JWT token verified successfully', {
|
|
59
|
+
sub: payload.sub,
|
|
60
|
+
email: payload.email,
|
|
61
|
+
tokenUse: payload.token_use,
|
|
62
|
+
});
|
|
63
|
+
return payload;
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
logger.error('JWT verification failed', {
|
|
67
|
+
error: error instanceof Error ? error.message : String(error),
|
|
68
|
+
});
|
|
69
|
+
// エラーメッセージを整形
|
|
70
|
+
let message = 'JWT verification failed';
|
|
71
|
+
if (error instanceof Error) {
|
|
72
|
+
if (error.message.includes('expired')) {
|
|
73
|
+
message = 'Token has expired';
|
|
74
|
+
}
|
|
75
|
+
else if (error.message.includes('invalid signature')) {
|
|
76
|
+
message = 'Invalid token signature';
|
|
77
|
+
}
|
|
78
|
+
else if (error.message.includes('invalid issuer')) {
|
|
79
|
+
message = 'Invalid token issuer';
|
|
80
|
+
}
|
|
81
|
+
else if (error.message.includes('invalid audience')) {
|
|
82
|
+
message = 'Invalid token audience';
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
message = error.message;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
throw new AuthError(message, {
|
|
89
|
+
originalError: error instanceof Error ? error.message : String(error),
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* HTTP Authorization ヘッダーから JWT トークンを抽出する
|
|
95
|
+
*
|
|
96
|
+
* @param authHeader - Authorization ヘッダーの値
|
|
97
|
+
* @returns JWT トークン(Bearer プレフィックスなし)
|
|
98
|
+
* @throws ヘッダーの形式が不正な場合
|
|
99
|
+
*/
|
|
100
|
+
export function extractTokenFromHeader(authHeader) {
|
|
101
|
+
if (!authHeader) {
|
|
102
|
+
throw new AuthError('Missing Authorization header');
|
|
103
|
+
}
|
|
104
|
+
const parts = authHeader.split(' ');
|
|
105
|
+
if (parts.length !== 2 || parts[0] !== 'Bearer') {
|
|
106
|
+
throw new AuthError('Invalid Authorization header format: expected "Bearer <token>"');
|
|
107
|
+
}
|
|
108
|
+
return parts[1];
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* HTTP リクエストから JWT トークンを検証する(ヘルパー関数)
|
|
112
|
+
*
|
|
113
|
+
* @param authHeader - Authorization ヘッダーの値
|
|
114
|
+
* @param userPoolId - Cognito User Pool ID
|
|
115
|
+
* @param clientId - Cognito App Client ID(オプション)
|
|
116
|
+
* @returns 検証済みの JWT ペイロード
|
|
117
|
+
* @throws トークンが無効な場合
|
|
118
|
+
*/
|
|
119
|
+
export async function verifyAuthHeader(authHeader, userPoolId, clientId) {
|
|
120
|
+
const token = extractTokenFromHeader(authHeader);
|
|
121
|
+
return await verifyJwt(token, userPoolId, clientId);
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/server/utils/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lambda実行時間制限(ミリ秒)
|
|
3
|
+
* AWS Lambdaの最大実行時間は15分(900秒)
|
|
4
|
+
*/
|
|
5
|
+
export declare const LAMBDA_TIMEOUT_MS: number;
|
|
6
|
+
/**
|
|
7
|
+
* 警告を出すレコード数の閾値
|
|
8
|
+
* この数を超えるとタイムアウトリスクの警告を出力
|
|
9
|
+
*/
|
|
10
|
+
export declare const LARGE_BATCH_WARNING_THRESHOLD = 1000;
|
|
11
|
+
/**
|
|
12
|
+
* タイムアウトリスク判定の閾値(残り時間の割合)
|
|
13
|
+
* 残り時間がこの割合未満になると高リスクと判定
|
|
14
|
+
*/
|
|
15
|
+
export declare const TIMEOUT_RISK_THRESHOLD = 0.2;
|
|
16
|
+
/**
|
|
17
|
+
* バルク操作のタイムアウトリスク情報
|
|
18
|
+
*/
|
|
19
|
+
export interface TimeoutRiskInfo {
|
|
20
|
+
/** 経過時間(ミリ秒) */
|
|
21
|
+
elapsedMs: number;
|
|
22
|
+
/** 残り時間(ミリ秒) */
|
|
23
|
+
remainingMs: number;
|
|
24
|
+
/** タイムアウトリスク(high/low) */
|
|
25
|
+
risk: 'high' | 'low';
|
|
26
|
+
/** タイムアウト利用率(0-100%) */
|
|
27
|
+
utilizationPercent: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* 大量レコード処理時の警告ログを出力する
|
|
31
|
+
*
|
|
32
|
+
* @param operation - 操作名(createMany、updateMany、deleteManyなど)
|
|
33
|
+
* @param recordCount - レコード数
|
|
34
|
+
* @param requestId - リクエストID
|
|
35
|
+
* @param resource - リソース名
|
|
36
|
+
*/
|
|
37
|
+
export declare function logLargeBatchWarning(operation: string, recordCount: number, requestId: string, resource: string): void;
|
|
38
|
+
/**
|
|
39
|
+
* タイムアウトリスク情報を計算する
|
|
40
|
+
*
|
|
41
|
+
* @param startTime - 処理開始時刻(Date.now()の値)
|
|
42
|
+
* @returns タイムアウトリスク情報
|
|
43
|
+
*/
|
|
44
|
+
export declare function calculateTimeoutRisk(startTime: number): TimeoutRiskInfo;
|
|
45
|
+
/**
|
|
46
|
+
* 準備段階のタイムアウトリスクをログ出力する
|
|
47
|
+
*
|
|
48
|
+
* @param requestId - リクエストID
|
|
49
|
+
* @param resource - リソース名
|
|
50
|
+
* @param totalRecords - 総レコード数
|
|
51
|
+
* @param chunkCount - チャンク数
|
|
52
|
+
* @param riskInfo - タイムアウトリスク情報
|
|
53
|
+
*/
|
|
54
|
+
export declare function logPreparationTimeoutRisk(requestId: string, resource: string, totalRecords: number, chunkCount: number, riskInfo: TimeoutRiskInfo): void;
|
|
55
|
+
/**
|
|
56
|
+
* バルク操作完了時のログを出力する
|
|
57
|
+
*
|
|
58
|
+
* @param operation - 操作名(createMany、updateMany、deleteManyなど)
|
|
59
|
+
* @param requestId - リクエストID
|
|
60
|
+
* @param resource - リソース名
|
|
61
|
+
* @param requested - リクエストされたレコード数
|
|
62
|
+
* @param succeeded - 成功したレコード数
|
|
63
|
+
* @param failed - 失敗したレコード数
|
|
64
|
+
* @param riskInfo - タイムアウトリスク情報
|
|
65
|
+
* @param additionalInfo - 追加情報(オプション)
|
|
66
|
+
*/
|
|
67
|
+
export declare function logBulkOperationComplete(operation: string, requestId: string, resource: string, requested: number, succeeded: number, failed: number, riskInfo: TimeoutRiskInfo, additionalInfo?: Record<string, unknown>): void;
|
|
68
|
+
/**
|
|
69
|
+
* 部分失敗時の詳細ログを出力する
|
|
70
|
+
*
|
|
71
|
+
* @param operation - 操作名(createMany、updateMany、deleteManyなど)
|
|
72
|
+
* @param requestId - リクエストID
|
|
73
|
+
* @param resource - リソース名
|
|
74
|
+
* @param requested - リクエストされたレコード数
|
|
75
|
+
* @param succeeded - 成功したレコード数
|
|
76
|
+
* @param failed - 失敗したレコード数
|
|
77
|
+
* @param errorCodes - エラーコードの配列
|
|
78
|
+
* @param additionalInfo - 追加情報(オプション)
|
|
79
|
+
*/
|
|
80
|
+
export declare function logPartialFailure(operation: string, requestId: string, resource: string, requested: number, succeeded: number, failed: number, errorCodes: string[], additionalInfo?: Record<string, unknown>): void;
|
|
81
|
+
//# sourceMappingURL=bulkOperations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bulkOperations.d.ts","sourceRoot":"","sources":["../../../src/server/utils/bulkOperations.ts"],"names":[],"mappings":"AAYA;;;GAGG;AACH,eAAO,MAAM,iBAAiB,QAAiB,CAAC;AAEhD;;;GAGG;AACH,eAAO,MAAM,6BAA6B,OAAO,CAAC;AAElD;;;GAGG;AACH,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAE1C;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,gBAAgB;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,0BAA0B;IAC1B,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IACrB,wBAAwB;IACxB,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,IAAI,CAYN;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,CAYvE;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,eAAe,GACxB,IAAI,CAsBN;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,eAAe,EACzB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACvC,IAAI,CAeN;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAAE,EACpB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACvC,IAAI,CAaN"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* バルク操作共通ユーティリティ
|
|
3
|
+
*
|
|
4
|
+
* createMany、updateMany、deleteManyなどのバルク操作で共通して使用される
|
|
5
|
+
* 定数、型、ヘルパー関数を提供する。
|
|
6
|
+
*
|
|
7
|
+
* 要件: 13.12
|
|
8
|
+
*/
|
|
9
|
+
import { createLogger } from '../../index.js';
|
|
10
|
+
const logger = createLogger({ service: 'records-lambda' });
|
|
11
|
+
/**
|
|
12
|
+
* Lambda実行時間制限(ミリ秒)
|
|
13
|
+
* AWS Lambdaの最大実行時間は15分(900秒)
|
|
14
|
+
*/
|
|
15
|
+
export const LAMBDA_TIMEOUT_MS = 15 * 60 * 1000; // 15分
|
|
16
|
+
/**
|
|
17
|
+
* 警告を出すレコード数の閾値
|
|
18
|
+
* この数を超えるとタイムアウトリスクの警告を出力
|
|
19
|
+
*/
|
|
20
|
+
export const LARGE_BATCH_WARNING_THRESHOLD = 1000;
|
|
21
|
+
/**
|
|
22
|
+
* タイムアウトリスク判定の閾値(残り時間の割合)
|
|
23
|
+
* 残り時間がこの割合未満になると高リスクと判定
|
|
24
|
+
*/
|
|
25
|
+
export const TIMEOUT_RISK_THRESHOLD = 0.2; // 20%
|
|
26
|
+
/**
|
|
27
|
+
* 大量レコード処理時の警告ログを出力する
|
|
28
|
+
*
|
|
29
|
+
* @param operation - 操作名(createMany、updateMany、deleteManyなど)
|
|
30
|
+
* @param recordCount - レコード数
|
|
31
|
+
* @param requestId - リクエストID
|
|
32
|
+
* @param resource - リソース名
|
|
33
|
+
*/
|
|
34
|
+
export function logLargeBatchWarning(operation, recordCount, requestId, resource) {
|
|
35
|
+
if (recordCount > LARGE_BATCH_WARNING_THRESHOLD) {
|
|
36
|
+
logger.warn(`Large batch ${operation} operation detected`, {
|
|
37
|
+
requestId,
|
|
38
|
+
resource,
|
|
39
|
+
recordCount,
|
|
40
|
+
warningThreshold: LARGE_BATCH_WARNING_THRESHOLD,
|
|
41
|
+
estimatedTimeoutRisk: 'high',
|
|
42
|
+
recommendation: 'Consider splitting the batch into smaller requests to avoid Lambda timeout (15 min limit)',
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* タイムアウトリスク情報を計算する
|
|
48
|
+
*
|
|
49
|
+
* @param startTime - 処理開始時刻(Date.now()の値)
|
|
50
|
+
* @returns タイムアウトリスク情報
|
|
51
|
+
*/
|
|
52
|
+
export function calculateTimeoutRisk(startTime) {
|
|
53
|
+
const elapsedMs = Date.now() - startTime;
|
|
54
|
+
const remainingMs = LAMBDA_TIMEOUT_MS - elapsedMs;
|
|
55
|
+
const utilizationPercent = Math.round((elapsedMs / LAMBDA_TIMEOUT_MS) * 100);
|
|
56
|
+
const risk = remainingMs < LAMBDA_TIMEOUT_MS * TIMEOUT_RISK_THRESHOLD ? 'high' : 'low';
|
|
57
|
+
return {
|
|
58
|
+
elapsedMs,
|
|
59
|
+
remainingMs,
|
|
60
|
+
risk,
|
|
61
|
+
utilizationPercent,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* 準備段階のタイムアウトリスクをログ出力する
|
|
66
|
+
*
|
|
67
|
+
* @param requestId - リクエストID
|
|
68
|
+
* @param resource - リソース名
|
|
69
|
+
* @param totalRecords - 総レコード数
|
|
70
|
+
* @param chunkCount - チャンク数
|
|
71
|
+
* @param riskInfo - タイムアウトリスク情報
|
|
72
|
+
*/
|
|
73
|
+
export function logPreparationTimeoutRisk(requestId, resource, totalRecords, chunkCount, riskInfo) {
|
|
74
|
+
logger.info('Records prepared for chunk execution', {
|
|
75
|
+
requestId,
|
|
76
|
+
resource,
|
|
77
|
+
totalRecords,
|
|
78
|
+
chunkCount,
|
|
79
|
+
preparationTimeMs: riskInfo.elapsedMs,
|
|
80
|
+
remainingTimeMs: riskInfo.remainingMs,
|
|
81
|
+
timeoutRisk: riskInfo.risk,
|
|
82
|
+
});
|
|
83
|
+
// タイムアウトリスクが高い場合の警告
|
|
84
|
+
if (riskInfo.risk === 'high') {
|
|
85
|
+
logger.warn('High timeout risk detected during preparation phase', {
|
|
86
|
+
requestId,
|
|
87
|
+
resource,
|
|
88
|
+
preparationElapsedMs: riskInfo.elapsedMs,
|
|
89
|
+
remainingTimeMs: riskInfo.remainingMs,
|
|
90
|
+
lambdaTimeoutMs: LAMBDA_TIMEOUT_MS,
|
|
91
|
+
recommendation: 'Consider reducing batch size or optimizing preparation logic',
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* バルク操作完了時のログを出力する
|
|
97
|
+
*
|
|
98
|
+
* @param operation - 操作名(createMany、updateMany、deleteManyなど)
|
|
99
|
+
* @param requestId - リクエストID
|
|
100
|
+
* @param resource - リソース名
|
|
101
|
+
* @param requested - リクエストされたレコード数
|
|
102
|
+
* @param succeeded - 成功したレコード数
|
|
103
|
+
* @param failed - 失敗したレコード数
|
|
104
|
+
* @param riskInfo - タイムアウトリスク情報
|
|
105
|
+
* @param additionalInfo - 追加情報(オプション)
|
|
106
|
+
*/
|
|
107
|
+
export function logBulkOperationComplete(operation, requestId, resource, requested, succeeded, failed, riskInfo, additionalInfo) {
|
|
108
|
+
const totalElapsedSeconds = Math.round(riskInfo.elapsedMs / 1000);
|
|
109
|
+
logger.info(`${operation} completed`, {
|
|
110
|
+
requestId,
|
|
111
|
+
resource,
|
|
112
|
+
requested,
|
|
113
|
+
succeeded,
|
|
114
|
+
totalFailed: failed,
|
|
115
|
+
totalExecutionTimeMs: riskInfo.elapsedMs,
|
|
116
|
+
totalExecutionTimeSeconds: totalElapsedSeconds,
|
|
117
|
+
lambdaTimeoutMs: LAMBDA_TIMEOUT_MS,
|
|
118
|
+
timeoutUtilization: `${riskInfo.utilizationPercent}%`,
|
|
119
|
+
...additionalInfo,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* 部分失敗時の詳細ログを出力する
|
|
124
|
+
*
|
|
125
|
+
* @param operation - 操作名(createMany、updateMany、deleteManyなど)
|
|
126
|
+
* @param requestId - リクエストID
|
|
127
|
+
* @param resource - リソース名
|
|
128
|
+
* @param requested - リクエストされたレコード数
|
|
129
|
+
* @param succeeded - 成功したレコード数
|
|
130
|
+
* @param failed - 失敗したレコード数
|
|
131
|
+
* @param errorCodes - エラーコードの配列
|
|
132
|
+
* @param additionalInfo - 追加情報(オプション)
|
|
133
|
+
*/
|
|
134
|
+
export function logPartialFailure(operation, requestId, resource, requested, succeeded, failed, errorCodes, additionalInfo) {
|
|
135
|
+
const failureRate = Math.round((failed / requested) * 100);
|
|
136
|
+
logger.warn(`Partial failure in ${operation} operation`, {
|
|
137
|
+
requestId,
|
|
138
|
+
resource,
|
|
139
|
+
totalRequested: requested,
|
|
140
|
+
successCount: succeeded,
|
|
141
|
+
failedCount: failed,
|
|
142
|
+
failureRate: `${failureRate}%`,
|
|
143
|
+
errorCodes: [...new Set(errorCodes)],
|
|
144
|
+
...additionalInfo,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=bulkOperations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bulkOperations.js","sourceRoot":"","sources":["../../../src/server/utils/bulkOperations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DynamoDB TransactWriteItemsの最大アイテム数制限
|
|
3
|
+
*
|
|
4
|
+
* DynamoDBのTransactWriteItemsは最大100アイテムまでしか処理できない。
|
|
5
|
+
* この制限を超える場合は、複数のトランザクションに分割する必要がある。
|
|
6
|
+
*
|
|
7
|
+
* 参考: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/transaction-apis.html
|
|
8
|
+
*/
|
|
9
|
+
export declare const DYNAMODB_TRANSACT_WRITE_MAX_ITEMS = 100;
|
|
10
|
+
/**
|
|
11
|
+
* チャンク分割結果
|
|
12
|
+
*/
|
|
13
|
+
export interface ChunkResult<T> {
|
|
14
|
+
/** チャンク配列(各チャンクは100アイテム以下) */
|
|
15
|
+
chunks: T[][];
|
|
16
|
+
/** 各チャンクのアイテム数 */
|
|
17
|
+
itemCounts: number[];
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* バルク操作のチャンクサイズを動的に計算する
|
|
21
|
+
*
|
|
22
|
+
* 各レコードのアイテム数(メインレコード + シャドーレコード)を考慮して、
|
|
23
|
+
* TransactWriteItemsの100アイテム制限内に収まるようにチャンクを分割する。
|
|
24
|
+
*
|
|
25
|
+
* @param records - 処理対象のレコード配列
|
|
26
|
+
* @param getItemCount - 各レコードのアイテム数を計算する関数
|
|
27
|
+
* @returns チャンク分割結果
|
|
28
|
+
* @throws {Error} 単一レコードが100アイテムを超える場合
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```typescript
|
|
32
|
+
* // createMany操作の例
|
|
33
|
+
* const result = calculateChunks(records, (record) => {
|
|
34
|
+
* const shadowCount = calculateShadowCount(record);
|
|
35
|
+
* return 1 + shadowCount; // メイン + シャドー
|
|
36
|
+
* });
|
|
37
|
+
*
|
|
38
|
+
* // updateMany操作の例
|
|
39
|
+
* const result = calculateChunks(records, (record) => {
|
|
40
|
+
* const oldShadowCount = record.__shadowKeys?.length || 0;
|
|
41
|
+
* const newShadowCount = calculateNewShadowCount(record);
|
|
42
|
+
* return 1 + oldShadowCount + newShadowCount; // メイン + 削除 + 追加
|
|
43
|
+
* });
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export declare function calculateChunks<T>(records: T[], getItemCount: (record: T) => number): ChunkResult<T>;
|
|
47
|
+
/**
|
|
48
|
+
* チャンク実行結果
|
|
49
|
+
*/
|
|
50
|
+
export interface ChunkExecutionResult<T> {
|
|
51
|
+
/** 成功したレコード */
|
|
52
|
+
successRecords: T[];
|
|
53
|
+
/** 失敗したレコードのID */
|
|
54
|
+
failedIds: string[];
|
|
55
|
+
/** エラー情報 */
|
|
56
|
+
errors: ChunkError[];
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* チャンクエラー情報
|
|
60
|
+
*/
|
|
61
|
+
export interface ChunkError {
|
|
62
|
+
/** レコードID */
|
|
63
|
+
id: string;
|
|
64
|
+
/** エラーコード */
|
|
65
|
+
code: string;
|
|
66
|
+
/** エラーメッセージ */
|
|
67
|
+
message: string;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* チャンクを順次実行し、結果を集約する
|
|
71
|
+
*
|
|
72
|
+
* 各チャンクを独立したトランザクションとして実行し、1つのチャンクが失敗しても
|
|
73
|
+
* 他のチャンクの処理を継続する(部分成功サポート)。
|
|
74
|
+
*
|
|
75
|
+
* @param chunks - 実行するチャンク配列
|
|
76
|
+
* @param executeChunk - 各チャンクを実行する関数(成功したレコードを返す)
|
|
77
|
+
* @param getRecordId - レコードからIDを取得する関数
|
|
78
|
+
* @returns チャンク実行結果
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```typescript
|
|
82
|
+
* const result = await executeChunks(
|
|
83
|
+
* chunks,
|
|
84
|
+
* async (chunk) => {
|
|
85
|
+
* // TransactWriteItemsでチャンクを実行
|
|
86
|
+
* await dynamoDBClient.send(new TransactWriteItemsCommand({
|
|
87
|
+
* TransactItems: buildTransactItems(chunk)
|
|
88
|
+
* }));
|
|
89
|
+
* return chunk; // 成功したレコードを返す
|
|
90
|
+
* },
|
|
91
|
+
* (record) => record.id
|
|
92
|
+
* );
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
export declare function executeChunks<T>(chunks: T[][], executeChunk: (chunk: T[]) => Promise<T[]>, getRecordId: (record: T) => string): Promise<ChunkExecutionResult<T>>;
|
|
96
|
+
//# sourceMappingURL=chunking.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunking.d.ts","sourceRoot":"","sources":["../../../src/server/utils/chunking.ts"],"names":[],"mappings":"AAaA;;;;;;;GAOG;AACH,eAAO,MAAM,iCAAiC,MAAM,CAAC;AAErD;;GAEG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,8BAA8B;IAC9B,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;IACd,kBAAkB;IAClB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAC/B,OAAO,EAAE,CAAC,EAAE,EACZ,YAAY,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,MAAM,GAClC,WAAW,CAAC,CAAC,CAAC,CAsDhB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB,CAAC,CAAC;IACrC,eAAe;IACf,cAAc,EAAE,CAAC,EAAE,CAAC;IACpB,kBAAkB;IAClB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,YAAY;IACZ,MAAM,EAAE,UAAU,EAAE,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,aAAa;IACb,EAAE,EAAE,MAAM,CAAC;IACX,aAAa;IACb,IAAI,EAAE,MAAM,CAAC;IACb,eAAe;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,aAAa,CAAC,CAAC,EACnC,MAAM,EAAE,CAAC,EAAE,EAAE,EACb,YAAY,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC,EAAE,CAAC,EAC1C,WAAW,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,MAAM,GACjC,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CA8FlC"}
|