@kensio/yulin 1.21.13 → 1.21.14
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/service/dynamodb/command/authorize/sim-dynamodb-attributes.d.ts +27 -0
- package/dist/service/dynamodb/command/authorize/sim-dynamodb-attributes.js +35 -0
- package/dist/service/dynamodb/command/authorize/sim-dynamodb-authorizer.d.ts +2 -1
- package/dist/service/dynamodb/command/authorize/sim-dynamodb-authorizer.js +5 -18
- package/dist/service/dynamodb/command/authorize/sim-dynamodb-reached.d.ts +17 -0
- package/dist/service/dynamodb/command/authorize/sim-dynamodb-reached.js +11 -0
- package/dist/service/dynamodb/command/batch/sim-dynamodb-batch-get-item.js +4 -1
- package/dist/service/dynamodb/command/batch/sim-dynamodb-batch-read-limit.d.ts +6 -0
- package/dist/service/dynamodb/command/batch/sim-dynamodb-batch-read-limit.js +16 -0
- package/dist/service/dynamodb/command/batch/sim-dynamodb-batch-reads.d.ts +2 -0
- package/dist/service/dynamodb/command/batch/sim-dynamodb-batch-reads.js +14 -22
- package/dist/service/dynamodb/command/batch/sim-dynamodb-batch-tables.d.ts +5 -5
- package/dist/service/dynamodb/command/batch/sim-dynamodb-batch-tables.js +1 -1
- package/dist/service/dynamodb/command/batch/sim-dynamodb-batch-write-item.js +5 -1
- package/dist/service/dynamodb/command/item/sim-dynamodb-condition-check.d.ts +5 -1
- package/dist/service/dynamodb/command/item/sim-dynamodb-condition-check.js +9 -2
- package/dist/service/dynamodb/command/item/sim-dynamodb-delete-item.js +7 -1
- package/dist/service/dynamodb/command/item/sim-dynamodb-get-item.js +9 -2
- package/dist/service/dynamodb/command/item/sim-dynamodb-put-item.js +5 -1
- package/dist/service/dynamodb/command/item/sim-dynamodb-update-expressions.d.ts +2 -0
- package/dist/service/dynamodb/command/item/sim-dynamodb-update-expressions.js +1 -1
- package/dist/service/dynamodb/command/item/sim-dynamodb-update-item.js +7 -1
- package/dist/service/dynamodb/command/item/sim-dynamodb-update-plan.d.ts +8 -6
- package/dist/service/dynamodb/command/item/sim-dynamodb-update-plan.js +14 -13
- package/dist/service/dynamodb/command/item/sim-dynamodb-update-touched.d.ts +10 -0
- package/dist/service/dynamodb/command/item/sim-dynamodb-update-touched.js +16 -0
- package/dist/service/dynamodb/command/query/sim-dynamodb-query-expressions.d.ts +2 -0
- package/dist/service/dynamodb/command/query/sim-dynamodb-query-expressions.js +6 -1
- package/dist/service/dynamodb/command/query/sim-dynamodb-query.js +5 -2
- package/dist/service/dynamodb/command/scan/sim-dynamodb-scan-expressions.d.ts +2 -0
- package/dist/service/dynamodb/command/scan/sim-dynamodb-scan-expressions.js +2 -2
- package/dist/service/dynamodb/command/scan/sim-dynamodb-scan.js +1 -1
- package/dist/service/dynamodb/command/table/sim-dynamodb-table-access.d.ts +3 -3
- package/dist/service/dynamodb/command/table/sim-dynamodb-table-access.js +5 -21
- package/dist/service/dynamodb/command/table/sim-dynamodb-table-reach.d.ts +25 -0
- package/dist/service/dynamodb/command/table/sim-dynamodb-table-reach.js +27 -0
- package/dist/service/dynamodb/command/transact/sim-dynamodb-transact-gets.js +1 -1
- package/dist/service/dynamodb/expression/condition/sim-dynamodb-condition-expression.d.ts +9 -1
- package/dist/service/dynamodb/expression/condition/sim-dynamodb-condition-expression.js +2 -2
- package/dist/service/dynamodb/expression/condition/sim-dynamodb-condition-grammar.js +1 -1
- package/dist/service/dynamodb/expression/condition/sim-dynamodb-condition-operand-parser.d.ts +3 -2
- package/dist/service/dynamodb/expression/condition/sim-dynamodb-condition-operand-parser.js +3 -3
- package/dist/service/dynamodb/expression/condition/sim-dynamodb-condition-parser.d.ts +2 -1
- package/dist/service/dynamodb/expression/condition/sim-dynamodb-condition-parser.js +1 -1
- package/dist/service/dynamodb/expression/key-condition/sim-dynamodb-key-condition-expression.js +1 -1
- package/dist/service/dynamodb/expression/key-condition/sim-dynamodb-key-condition-operands.d.ts +3 -2
- package/dist/service/dynamodb/expression/key-condition/sim-dynamodb-key-condition-operands.js +8 -6
- package/dist/service/dynamodb/expression/key-condition/sim-dynamodb-key-condition-parser.d.ts +2 -1
- package/dist/service/dynamodb/expression/key-condition/sim-dynamodb-key-condition-parser.js +1 -1
- package/dist/service/dynamodb/expression/projection/sim-dynamodb-projection-expression.d.ts +9 -1
- package/dist/service/dynamodb/expression/projection/sim-dynamodb-projection-expression.js +5 -5
- package/dist/service/dynamodb/expression/sim-dynamodb-document-path-parser.d.ts +3 -3
- package/dist/service/dynamodb/expression/sim-dynamodb-document-path-parser.js +8 -4
- package/dist/service/dynamodb/expression/sim-dynamodb-expression-attributes.d.ts +33 -0
- package/dist/service/dynamodb/expression/sim-dynamodb-expression-attributes.js +40 -0
- package/dist/service/dynamodb/expression/sim-dynamodb-expression-parameters.d.ts +6 -0
- package/dist/service/dynamodb/expression/sim-dynamodb-expression-parameters.js +7 -0
- package/dist/service/dynamodb/expression/update/sim-dynamodb-update-clause.d.ts +3 -3
- package/dist/service/dynamodb/expression/update/sim-dynamodb-update-clause.js +3 -3
- package/dist/service/dynamodb/expression/update/sim-dynamodb-update-expression.js +1 -1
- package/dist/service/dynamodb/expression/update/sim-dynamodb-update-operand-parser.d.ts +3 -2
- package/dist/service/dynamodb/expression/update/sim-dynamodb-update-operand-parser.js +3 -3
- package/dist/service/dynamodb/expression/update/sim-dynamodb-update-parser.d.ts +2 -1
- package/dist/service/iam/authorize/match/condition/negated/sim-iam-negated-for-all-values-string-operator.d.ts +4 -1
- package/dist/service/iam/authorize/match/condition/negated/sim-iam-negated-for-all-values-string-operator.js +6 -1
- package/dist/service/iam/authorize/match/condition/negated/sim-iam-negated-for-any-value-string-operator.d.ts +4 -1
- package/dist/service/iam/authorize/match/condition/negated/sim-iam-negated-for-any-value-string-operator.js +6 -1
- package/dist/service/iam/authorize/match/condition/negated/sim-iam-negated-scalar-string-operator.d.ts +4 -1
- package/dist/service/iam/authorize/match/condition/negated/sim-iam-negated-scalar-string-operator.js +6 -1
- package/dist/service/iam/authorize/match/condition/null/sim-iam-null.d.ts +23 -0
- package/dist/service/iam/authorize/match/condition/null/sim-iam-null.js +59 -0
- package/dist/service/iam/authorize/match/condition/numeric/less-than-equals/sim-iam-number-lte.d.ts +4 -1
- package/dist/service/iam/authorize/match/condition/numeric/less-than-equals/sim-iam-number-lte.js +6 -1
- package/dist/service/iam/authorize/match/condition/sim-iam-condition-operator-parser.js +2 -0
- package/dist/service/iam/authorize/match/condition/sim-iam-condition-operator.d.ts +5 -1
- package/dist/service/iam/authorize/match/condition/sim-iam-policy-condition-matcher.js +1 -1
- package/dist/service/iam/authorize/match/condition/string/all-values/sim-iam-for-all-values-string-condition-operator.d.ts +4 -1
- package/dist/service/iam/authorize/match/condition/string/all-values/sim-iam-for-all-values-string-condition-operator.js +6 -1
- package/dist/service/iam/authorize/match/condition/string/any-value/sim-iam-for-any-value-string-condition-operator.d.ts +4 -1
- package/dist/service/iam/authorize/match/condition/string/any-value/sim-iam-for-any-value-string-condition-operator.js +6 -1
- package/dist/service/iam/authorize/match/condition/string/sim-iam-scalar-string-condition-operator.d.ts +4 -1
- package/dist/service/iam/authorize/match/condition/string/sim-iam-scalar-string-condition-operator.js +6 -1
- package/docs/services/dynamodb/README.md +23 -4
- package/docs/services/iam/README.md +17 -3
- package/package.json +1 -1
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { SimDynamoDbItem } from "../../item/sim-dynamodb-item.js";
|
|
2
|
+
/**
|
|
3
|
+
* The condition key DynamoDB names a request's attributes by.
|
|
4
|
+
*/
|
|
5
|
+
export declare const simDynamoDbAttributesConditionKey = "dynamodb:Attributes";
|
|
6
|
+
/**
|
|
7
|
+
* The top-level attribute names a `Key` or an `Item` carries.
|
|
8
|
+
*
|
|
9
|
+
* Those parameters name their attributes outright, so there is no expression
|
|
10
|
+
* to read them out of. Every name is top-level, since an item's attributes are
|
|
11
|
+
* what nesting starts from.
|
|
12
|
+
*
|
|
13
|
+
* The items are read when authorization asks for them, and whatever reading
|
|
14
|
+
* them throws is dropped. Authorization runs ahead of the checks a command
|
|
15
|
+
* makes on what it was given, so a request too malformed to read is authorized
|
|
16
|
+
* naming no attributes and refused by the check that follows.
|
|
17
|
+
*/
|
|
18
|
+
export declare function simDynamoDbItemAttributeNames(items: () => readonly SimDynamoDbItem[]): readonly string[];
|
|
19
|
+
/**
|
|
20
|
+
* Gather the attribute names a request reaches, keeping each one once.
|
|
21
|
+
*
|
|
22
|
+
* A request names the same attribute in more than one place often enough for
|
|
23
|
+
* this to matter. An UpdateItem names its key in `Key` and may name it again
|
|
24
|
+
* in a condition, and AWS supplies one list of attributes rather than one per
|
|
25
|
+
* parameter.
|
|
26
|
+
*/
|
|
27
|
+
export declare function simDynamoDbAttributesOf(...sources: readonly (readonly string[])[]): readonly string[];
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The condition key DynamoDB names a request's attributes by.
|
|
3
|
+
*/
|
|
4
|
+
export const simDynamoDbAttributesConditionKey = "dynamodb:Attributes";
|
|
5
|
+
/**
|
|
6
|
+
* The top-level attribute names a `Key` or an `Item` carries.
|
|
7
|
+
*
|
|
8
|
+
* Those parameters name their attributes outright, so there is no expression
|
|
9
|
+
* to read them out of. Every name is top-level, since an item's attributes are
|
|
10
|
+
* what nesting starts from.
|
|
11
|
+
*
|
|
12
|
+
* The items are read when authorization asks for them, and whatever reading
|
|
13
|
+
* them throws is dropped. Authorization runs ahead of the checks a command
|
|
14
|
+
* makes on what it was given, so a request too malformed to read is authorized
|
|
15
|
+
* naming no attributes and refused by the check that follows.
|
|
16
|
+
*/
|
|
17
|
+
export function simDynamoDbItemAttributeNames(items) {
|
|
18
|
+
try {
|
|
19
|
+
return items().flatMap((item) => item.attributeNames());
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Gather the attribute names a request reaches, keeping each one once.
|
|
27
|
+
*
|
|
28
|
+
* A request names the same attribute in more than one place often enough for
|
|
29
|
+
* this to matter. An UpdateItem names its key in `Key` and may name it again
|
|
30
|
+
* in a condition, and AWS supplies one list of attributes rather than one per
|
|
31
|
+
* parameter.
|
|
32
|
+
*/
|
|
33
|
+
export function simDynamoDbAttributesOf(...sources) {
|
|
34
|
+
return [...new Set(sources.flat())];
|
|
35
|
+
}
|
|
@@ -2,6 +2,7 @@ import type { SimAwsCaller } from "../../../aws/caller/sim-aws-caller.js";
|
|
|
2
2
|
import type { SimAwsResolvedCaller } from "../../../aws/caller/sim-aws-caller-resolver.js";
|
|
3
3
|
import type { SimAwsAccountRegionScope } from "../../../aws/sim-aws-account-region-scope.js";
|
|
4
4
|
import type { SimIamInterServiceAuthZ } from "../../../iam/authorize/sim-iam-inter-service-auth-z.js";
|
|
5
|
+
import type { SimDynamoDbReached } from "./sim-dynamodb-reached.js";
|
|
5
6
|
interface SimDynamoDbAuthorizerProperties {
|
|
6
7
|
readonly iam: SimIamInterServiceAuthZ;
|
|
7
8
|
readonly accountRegionScope: SimAwsAccountRegionScope;
|
|
@@ -29,7 +30,7 @@ export declare class SimDynamoDbAuthorizer {
|
|
|
29
30
|
* omitted caller, which defaults to Account root, from an explicit anonymous
|
|
30
31
|
* caller.
|
|
31
32
|
*/
|
|
32
|
-
authorizeTable(action: string, tableName: string, caller?: SimAwsCaller,
|
|
33
|
+
authorizeTable(action: string, tableName: string, caller?: SimAwsCaller, reached?: SimDynamoDbReached): SimAwsResolvedCaller;
|
|
33
34
|
/**
|
|
34
35
|
* Ensure the caller may perform an action on a table's stream.
|
|
35
36
|
*
|
|
@@ -1,19 +1,6 @@
|
|
|
1
1
|
import { SimIamAccessDenied } from "../../../iam/error/sim-iam.error.js";
|
|
2
2
|
import { simDynamoDbTableArn } from "../../table/sim-dynamodb-table-arn.js";
|
|
3
|
-
import {
|
|
4
|
-
/**
|
|
5
|
-
* The condition values a request carries for the table it names.
|
|
6
|
-
*
|
|
7
|
-
* A request reaching no partition key value supplies none rather than an empty
|
|
8
|
-
* list, leaving the key absent from the context as it is on AWS for an
|
|
9
|
-
* operation that names no item.
|
|
10
|
-
*/
|
|
11
|
-
function conditionContextOf(leadingKeys) {
|
|
12
|
-
if (leadingKeys === undefined || leadingKeys.length === 0) {
|
|
13
|
-
return {};
|
|
14
|
-
}
|
|
15
|
-
return { [simDynamoDbLeadingKeysConditionKey]: leadingKeys };
|
|
16
|
-
}
|
|
3
|
+
import { simDynamoDbConditionContextOf } from "./sim-dynamodb-reached.js";
|
|
17
4
|
/**
|
|
18
5
|
* Applies simulated IAM authorization to DynamoDB requests.
|
|
19
6
|
*
|
|
@@ -40,8 +27,8 @@ export class SimDynamoDbAuthorizer {
|
|
|
40
27
|
* omitted caller, which defaults to Account root, from an explicit anonymous
|
|
41
28
|
* caller.
|
|
42
29
|
*/
|
|
43
|
-
authorizeTable(action, tableName, caller,
|
|
44
|
-
return this.authorizeResource(action, simDynamoDbTableArn(this.accountRegionScope, tableName), caller,
|
|
30
|
+
authorizeTable(action, tableName, caller, reached = {}) {
|
|
31
|
+
return this.authorizeResource(action, simDynamoDbTableArn(this.accountRegionScope, tableName), caller, reached);
|
|
45
32
|
}
|
|
46
33
|
/**
|
|
47
34
|
* Ensure the caller may perform an action on a table's stream.
|
|
@@ -65,12 +52,12 @@ export class SimDynamoDbAuthorizer {
|
|
|
65
52
|
authorizeAnyTable(action, caller) {
|
|
66
53
|
return this.authorizeResource(action, "*", caller);
|
|
67
54
|
}
|
|
68
|
-
authorizeResource(action, resource, caller,
|
|
55
|
+
authorizeResource(action, resource, caller, reached = {}) {
|
|
69
56
|
const decision = this.iam.authorize({
|
|
70
57
|
action,
|
|
71
58
|
resource,
|
|
72
59
|
caller,
|
|
73
|
-
conditionContext:
|
|
60
|
+
conditionContext: simDynamoDbConditionContextOf(reached),
|
|
74
61
|
});
|
|
75
62
|
if (decision.isDenied) {
|
|
76
63
|
throw new SimIamAccessDenied({
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What one request reaches in the table it names.
|
|
3
|
+
*
|
|
4
|
+
* Each entry becomes a DynamoDB condition key. A request reaching nothing
|
|
5
|
+
* under one of them leaves it out, as AWS leaves a key out for an operation
|
|
6
|
+
* that reaches nothing it names.
|
|
7
|
+
*/
|
|
8
|
+
export interface SimDynamoDbReached {
|
|
9
|
+
/** The partition key values the request reaches. */
|
|
10
|
+
readonly leadingKeys?: readonly string[] | undefined;
|
|
11
|
+
/** The top-level attribute names the request names. */
|
|
12
|
+
readonly attributes?: readonly string[] | undefined;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The condition values a request carries for the table it names.
|
|
16
|
+
*/
|
|
17
|
+
export declare function simDynamoDbConditionContextOf(reached: SimDynamoDbReached): Readonly<Record<string, readonly string[]>>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { simDynamoDbAttributesConditionKey } from "./sim-dynamodb-attributes.js";
|
|
2
|
+
import { simDynamoDbLeadingKeysConditionKey } from "./sim-dynamodb-leading-keys.js";
|
|
3
|
+
/**
|
|
4
|
+
* The condition values a request carries for the table it names.
|
|
5
|
+
*/
|
|
6
|
+
export function simDynamoDbConditionContextOf(reached) {
|
|
7
|
+
return Object.fromEntries([
|
|
8
|
+
[simDynamoDbLeadingKeysConditionKey, reached.leadingKeys],
|
|
9
|
+
[simDynamoDbAttributesConditionKey, reached.attributes],
|
|
10
|
+
].filter(([, values]) => (values ?? []).length > 0));
|
|
11
|
+
}
|
|
@@ -28,7 +28,10 @@ export class SimDynamoDbBatchGetItem {
|
|
|
28
28
|
access: this.access,
|
|
29
29
|
operation: "BatchGetItem",
|
|
30
30
|
caller: options?.caller,
|
|
31
|
-
|
|
31
|
+
reached: (entry) => ({
|
|
32
|
+
leadingKeys: simDynamoDbLeadingKeysOf(() => entry.keys),
|
|
33
|
+
attributes: entry.attributes,
|
|
34
|
+
}),
|
|
32
35
|
});
|
|
33
36
|
const responses = Object.fromEntries(reached.map((entry) => [entry.requested.reference, readItems(entry)]));
|
|
34
37
|
// Nothing here throttles or stops at a response size, so no key is ever
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { SimDynamoDbKeysAndAttributes } from "./batch.command.js";
|
|
2
|
+
import type { SimDynamoDbBatchTableRequest } from "./sim-dynamodb-batch-request-items.js";
|
|
3
|
+
/**
|
|
4
|
+
* Refuse a batch asking for more items than DynamoDB reads at once.
|
|
5
|
+
*/
|
|
6
|
+
export declare function assertSimDynamoDbBatchReadLimit(tables: readonly SimDynamoDbBatchTableRequest<SimDynamoDbKeysAndAttributes>[], operation: string): void;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { SimDynamoDbValidationException } from "../../error/dynamodb.error.js";
|
|
2
|
+
/**
|
|
3
|
+
* Real DynamoDB reads 100 items in one batch, counted across every table the
|
|
4
|
+
* request names rather than per table.
|
|
5
|
+
*/
|
|
6
|
+
const greatestKeys = 100;
|
|
7
|
+
/**
|
|
8
|
+
* Refuse a batch asking for more items than DynamoDB reads at once.
|
|
9
|
+
*/
|
|
10
|
+
export function assertSimDynamoDbBatchReadLimit(tables, operation) {
|
|
11
|
+
const total = tables.reduce((count, { requested }) => count + (requested.Keys ?? []).length, 0);
|
|
12
|
+
if (total > greatestKeys) {
|
|
13
|
+
throw new SimDynamoDbValidationException(`Too many items requested for the ${operation} call: ${total.toString()} ` +
|
|
14
|
+
`keys, where ${greatestKeys.toString()} is the most a batch reads`);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -11,6 +11,8 @@ export interface SimDynamoDbBatchTableReads {
|
|
|
11
11
|
readonly reference: string;
|
|
12
12
|
readonly keys: readonly SimDynamoDbItem[];
|
|
13
13
|
readonly projection: SimDynamoDbProjection | undefined;
|
|
14
|
+
/** The top-level attributes this table is asked for, per table as above. */
|
|
15
|
+
readonly attributes: readonly string[];
|
|
14
16
|
}
|
|
15
17
|
/**
|
|
16
18
|
* Read every key a batch asks for, before any table is reached.
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
import { SimDynamoDbValidationException } from "../../error/dynamodb.error.js";
|
|
2
2
|
import { readSimDynamoDbProjection } from "../../expression/projection/sim-dynamodb-projection-expression.js";
|
|
3
3
|
import { readSimDynamoDbKey } from "../item/sim-dynamodb-key-input.js";
|
|
4
|
-
import {
|
|
4
|
+
import { simDynamoDbAttributesOf, simDynamoDbItemAttributeNames, } from "../authorize/sim-dynamodb-attributes.js";
|
|
5
|
+
import { readSimDynamoDbBatchRequestItems } from "./sim-dynamodb-batch-request-items.js";
|
|
6
|
+
import { assertSimDynamoDbBatchReadLimit } from "./sim-dynamodb-batch-read-limit.js";
|
|
5
7
|
import { refuseUnsimulatedBatchKeysAndAttributes } from "./sim-dynamodb-unsimulated-batch-input.js";
|
|
6
8
|
const operation = "BatchGetItem";
|
|
7
|
-
/**
|
|
8
|
-
* Real DynamoDB reads 100 items in one batch, counted across every table the
|
|
9
|
-
* request names rather than per table.
|
|
10
|
-
*/
|
|
11
|
-
const greatestKeys = 100;
|
|
12
9
|
/**
|
|
13
10
|
* Read every key a batch asks for, before any table is reached.
|
|
14
11
|
*
|
|
@@ -17,22 +14,17 @@ const greatestKeys = 100;
|
|
|
17
14
|
*/
|
|
18
15
|
export function readSimDynamoDbBatchReads(requestItems) {
|
|
19
16
|
const tables = readSimDynamoDbBatchRequestItems(requestItems, operation);
|
|
20
|
-
|
|
21
|
-
return tables.map(({ reference, requested }) =>
|
|
22
|
-
reference,
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const total = tables.reduce((count, { requested }) => count + (requested.Keys ?? []).length, 0);
|
|
32
|
-
if (total > greatestKeys) {
|
|
33
|
-
throw new SimDynamoDbValidationException(`Too many items requested for the ${operation} call: ${total.toString()} ` +
|
|
34
|
-
`keys, where ${greatestKeys.toString()} is the most a batch reads`);
|
|
35
|
-
}
|
|
17
|
+
assertSimDynamoDbBatchReadLimit(tables, operation);
|
|
18
|
+
return tables.map(({ reference, requested }) => {
|
|
19
|
+
const keys = readTableKeys(reference, requested);
|
|
20
|
+
const read = readSimDynamoDbProjection(requested);
|
|
21
|
+
return {
|
|
22
|
+
reference,
|
|
23
|
+
keys,
|
|
24
|
+
projection: read.projection,
|
|
25
|
+
attributes: simDynamoDbAttributesOf(read.attributes, simDynamoDbItemAttributeNames(() => keys)),
|
|
26
|
+
};
|
|
27
|
+
});
|
|
36
28
|
}
|
|
37
29
|
/**
|
|
38
30
|
* Read the keys one table of the batch is asked for.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { SimAwsCaller } from "../../../aws/caller/sim-aws-caller.js";
|
|
2
2
|
import type { SimDynamoDbTable } from "../../table/sim-dynamodb-table.js";
|
|
3
3
|
import type { SimDynamoDbTableAccess } from "../table/sim-dynamodb-table-access.js";
|
|
4
|
-
import type {
|
|
4
|
+
import type { SimDynamoDbTableReach } from "../table/sim-dynamodb-table-reach.js";
|
|
5
5
|
/**
|
|
6
6
|
* What one table of a batch asks for, against the table it names.
|
|
7
7
|
*/
|
|
@@ -14,12 +14,12 @@ interface SimDynamoDbBatchReach<Requested> {
|
|
|
14
14
|
readonly operation: string;
|
|
15
15
|
readonly caller: SimAwsCaller | undefined;
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
17
|
+
* What one table of the batch is asked for.
|
|
18
18
|
*
|
|
19
|
-
* Each table is authorized on its own, so each carries the keys the
|
|
20
|
-
* names in that table and no others.
|
|
19
|
+
* Each table is authorized on its own, so each carries the keys and the
|
|
20
|
+
* attributes the batch names in that table and no others.
|
|
21
21
|
*/
|
|
22
|
-
readonly
|
|
22
|
+
readonly reached: (requested: Requested) => SimDynamoDbTableReach;
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
25
25
|
* Reach every table a batch names, authorizing the caller against each.
|
|
@@ -11,7 +11,7 @@ import { SimDynamoDbValidationException } from "../../error/dynamodb.error.js";
|
|
|
11
11
|
export function reachSimDynamoDbBatchTables(requested, reach) {
|
|
12
12
|
const action = `dynamodb:${reach.operation}`;
|
|
13
13
|
const reached = requested.map((entry) => ({
|
|
14
|
-
table: reach.access.required(action, entry.reference, reach.caller, reach.
|
|
14
|
+
table: reach.access.required(action, entry.reference, reach.caller, reach.reached(entry)),
|
|
15
15
|
requested: entry,
|
|
16
16
|
}));
|
|
17
17
|
assertDistinctTables(reached, reach.operation);
|
|
@@ -3,6 +3,7 @@ import { reachSimDynamoDbBatchTables } from "./sim-dynamodb-batch-tables.js";
|
|
|
3
3
|
import { readSimDynamoDbBatchWrites } from "./sim-dynamodb-batch-writes.js";
|
|
4
4
|
import { refuseUnsimulatedBatchWriteInput } from "./sim-dynamodb-unsimulated-batch-input.js";
|
|
5
5
|
import { simDynamoDbLeadingKeysOf } from "../authorize/sim-dynamodb-leading-keys.js";
|
|
6
|
+
import { simDynamoDbItemAttributeNames } from "../authorize/sim-dynamodb-attributes.js";
|
|
6
7
|
const operation = "BatchWriteItem";
|
|
7
8
|
/**
|
|
8
9
|
* The BatchWriteItem command.
|
|
@@ -30,7 +31,10 @@ export class SimDynamoDbBatchWriteItem {
|
|
|
30
31
|
access: this.access,
|
|
31
32
|
operation,
|
|
32
33
|
caller: options?.caller,
|
|
33
|
-
|
|
34
|
+
reached: (entry) => ({
|
|
35
|
+
leadingKeys: simDynamoDbLeadingKeysOf(() => entry.writes.map((write) => write.names)),
|
|
36
|
+
attributes: simDynamoDbItemAttributeNames(() => entry.writes.map((write) => write.names)),
|
|
37
|
+
}),
|
|
34
38
|
});
|
|
35
39
|
// Marshalling every key checks it against the table's key schema, and is
|
|
36
40
|
// what tells two operations on one item apart. Every table is checked
|
|
@@ -15,6 +15,10 @@ interface SimDynamoDbConditionCheckInput {
|
|
|
15
15
|
* be nothing: that is what makes `attribute_not_exists` an insert if absent.
|
|
16
16
|
*/
|
|
17
17
|
export declare class SimDynamoDbConditionCheck {
|
|
18
|
+
/**
|
|
19
|
+
* The top-level attributes the condition named, for `dynamodb:Attributes`.
|
|
20
|
+
*/
|
|
21
|
+
readonly attributeNames: readonly string[];
|
|
18
22
|
private readonly condition;
|
|
19
23
|
private readonly reportsItem;
|
|
20
24
|
private constructor();
|
|
@@ -31,7 +35,7 @@ export declare class SimDynamoDbConditionCheck {
|
|
|
31
35
|
* UpdateItem reads its condition alongside its update expression, since the
|
|
32
36
|
* two share the request's placeholders, and then hands the condition here.
|
|
33
37
|
*/
|
|
34
|
-
static of(condition: SimDynamoDbCondition | undefined, input: SimDynamoDbConditionCheckInput, operation: string): SimDynamoDbConditionCheck;
|
|
38
|
+
static of(condition: SimDynamoDbCondition | undefined, input: SimDynamoDbConditionCheckInput, operation: string, attributeNames?: readonly string[]): SimDynamoDbConditionCheck;
|
|
35
39
|
/**
|
|
36
40
|
* Whether the request asked for the item that turned it away.
|
|
37
41
|
*/
|
|
@@ -13,11 +13,16 @@ const failureModes = new Set(["NONE", "ALL_OLD"]);
|
|
|
13
13
|
* be nothing: that is what makes `attribute_not_exists` an insert if absent.
|
|
14
14
|
*/
|
|
15
15
|
export class SimDynamoDbConditionCheck {
|
|
16
|
+
/**
|
|
17
|
+
* The top-level attributes the condition named, for `dynamodb:Attributes`.
|
|
18
|
+
*/
|
|
19
|
+
attributeNames;
|
|
16
20
|
condition;
|
|
17
21
|
reportsItem;
|
|
18
22
|
constructor(properties) {
|
|
19
23
|
this.condition = properties.condition;
|
|
20
24
|
this.reportsItem = properties.reportsItem;
|
|
25
|
+
this.attributeNames = properties.attributeNames;
|
|
21
26
|
}
|
|
22
27
|
/**
|
|
23
28
|
* Read the condition a request carries, before anything is looked up.
|
|
@@ -26,7 +31,8 @@ export class SimDynamoDbConditionCheck {
|
|
|
26
31
|
* anything, so a bad expression fails the same way every time.
|
|
27
32
|
*/
|
|
28
33
|
static read(input, operation) {
|
|
29
|
-
|
|
34
|
+
const read = readSimDynamoDbCondition(input);
|
|
35
|
+
return this.of(read.condition, input, operation, read.attributes);
|
|
30
36
|
}
|
|
31
37
|
/**
|
|
32
38
|
* Guard a write with a condition that has already been read.
|
|
@@ -34,10 +40,11 @@ export class SimDynamoDbConditionCheck {
|
|
|
34
40
|
* UpdateItem reads its condition alongside its update expression, since the
|
|
35
41
|
* two share the request's placeholders, and then hands the condition here.
|
|
36
42
|
*/
|
|
37
|
-
static of(condition, input, operation) {
|
|
43
|
+
static of(condition, input, operation, attributeNames = []) {
|
|
38
44
|
return new this({
|
|
39
45
|
condition,
|
|
40
46
|
reportsItem: this.reportsItemFor(input, operation),
|
|
47
|
+
attributeNames,
|
|
41
48
|
});
|
|
42
49
|
}
|
|
43
50
|
/**
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { simDynamoDbLeadingKeysOf } from "../authorize/sim-dynamodb-leading-keys.js";
|
|
2
|
+
import { simDynamoDbAttributesOf, simDynamoDbItemAttributeNames, } from "../authorize/sim-dynamodb-attributes.js";
|
|
2
3
|
import { readSimDynamoDbKey } from "./sim-dynamodb-key-input.js";
|
|
3
4
|
import { SimDynamoDbConditionCheck } from "./sim-dynamodb-condition-check.js";
|
|
4
5
|
import { SimDynamoDbReturnValues } from "./sim-dynamodb-return-values.js";
|
|
@@ -27,7 +28,12 @@ export class SimDynamoDbDeleteItem {
|
|
|
27
28
|
// The condition is read before the table is reached, so an expression
|
|
28
29
|
// DynamoDB would refuse is refused whether or not the key holds anything.
|
|
29
30
|
const check = SimDynamoDbConditionCheck.read(input, "DeleteItem");
|
|
30
|
-
const table = this.access.required("dynamodb:DeleteItem", input.TableName, options?.caller,
|
|
31
|
+
const table = this.access.required("dynamodb:DeleteItem", input.TableName, options?.caller, {
|
|
32
|
+
leadingKeys: simDynamoDbLeadingKeysOf(() => [
|
|
33
|
+
readSimDynamoDbKey(input.Key),
|
|
34
|
+
]),
|
|
35
|
+
attributes: simDynamoDbAttributesOf(check.attributeNames, simDynamoDbItemAttributeNames(() => [readSimDynamoDbKey(input.Key)])),
|
|
36
|
+
});
|
|
31
37
|
const asked = SimDynamoDbReturnValues.read(input.ReturnValues, "DeleteItem");
|
|
32
38
|
const key = readSimDynamoDbKey(input.Key);
|
|
33
39
|
check.assertHoldsFor(table.getItem(key));
|
|
@@ -2,6 +2,7 @@ import { simDynamoDbLeadingKeysOf } from "../authorize/sim-dynamodb-leading-keys
|
|
|
2
2
|
import { readSimDynamoDbKey } from "./sim-dynamodb-key-input.js";
|
|
3
3
|
import { refuseUnsimulatedItemReadInput } from "./sim-dynamodb-unsimulated-item-read-input.js";
|
|
4
4
|
import { readSimDynamoDbProjection } from "../../expression/projection/sim-dynamodb-projection-expression.js";
|
|
5
|
+
import { simDynamoDbAttributesOf, simDynamoDbItemAttributeNames, } from "../authorize/sim-dynamodb-attributes.js";
|
|
5
6
|
/**
|
|
6
7
|
* The GetItem command.
|
|
7
8
|
*
|
|
@@ -26,8 +27,14 @@ export class SimDynamoDbGetItem {
|
|
|
26
27
|
refuseUnsimulatedItemReadInput(input);
|
|
27
28
|
// The projection is read before the table is reached, so an expression
|
|
28
29
|
// DynamoDB would refuse is refused whether or not the key holds anything.
|
|
29
|
-
const
|
|
30
|
-
const
|
|
30
|
+
const read = readSimDynamoDbProjection(input);
|
|
31
|
+
const projection = read.projection;
|
|
32
|
+
const table = this.access.required("dynamodb:GetItem", input.TableName, options?.caller, {
|
|
33
|
+
leadingKeys: simDynamoDbLeadingKeysOf(() => [
|
|
34
|
+
readSimDynamoDbKey(input.Key),
|
|
35
|
+
]),
|
|
36
|
+
attributes: simDynamoDbAttributesOf(read.attributes, simDynamoDbItemAttributeNames(() => [readSimDynamoDbKey(input.Key)])),
|
|
37
|
+
});
|
|
31
38
|
const found = table.getItem(readSimDynamoDbKey(input.Key));
|
|
32
39
|
if (found === undefined) {
|
|
33
40
|
return { $metadata: {} };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { SimDynamoDbValidationException } from "../../error/dynamodb.error.js";
|
|
2
2
|
import { SimDynamoDbItem } from "../../item/sim-dynamodb-item.js";
|
|
3
3
|
import { simDynamoDbLeadingKeysOf } from "../authorize/sim-dynamodb-leading-keys.js";
|
|
4
|
+
import { simDynamoDbAttributesOf, simDynamoDbItemAttributeNames, } from "../authorize/sim-dynamodb-attributes.js";
|
|
4
5
|
import { SimDynamoDbConditionCheck } from "./sim-dynamodb-condition-check.js";
|
|
5
6
|
import { SimDynamoDbReturnValues } from "./sim-dynamodb-return-values.js";
|
|
6
7
|
import { refuseUnsimulatedItemWriteInput } from "./sim-dynamodb-unsimulated-item-write-input.js";
|
|
@@ -37,7 +38,10 @@ export class SimDynamoDbPutItem {
|
|
|
37
38
|
// The condition is read before the table is reached, so an expression
|
|
38
39
|
// DynamoDB would refuse is refused whether or not the key holds anything.
|
|
39
40
|
const check = SimDynamoDbConditionCheck.read(input, "PutItem");
|
|
40
|
-
const table = this.access.required("dynamodb:PutItem", input.TableName, options?.caller,
|
|
41
|
+
const table = this.access.required("dynamodb:PutItem", input.TableName, options?.caller, {
|
|
42
|
+
leadingKeys: simDynamoDbLeadingKeysOf(() => [readItem(input)]),
|
|
43
|
+
attributes: simDynamoDbAttributesOf(check.attributeNames, simDynamoDbItemAttributeNames(() => [readItem(input)])),
|
|
44
|
+
});
|
|
41
45
|
const asked = SimDynamoDbReturnValues.read(input.ReturnValues, "PutItem");
|
|
42
46
|
const item = readItem(input);
|
|
43
47
|
check.assertHoldsFor(table.itemUnder(item));
|
|
@@ -14,6 +14,8 @@ export interface SimDynamoDbUpdateExpressionInput extends SimDynamoDbExpressionP
|
|
|
14
14
|
export interface SimDynamoDbUpdateExpressions {
|
|
15
15
|
readonly update: SimDynamoDbUpdate;
|
|
16
16
|
readonly condition: SimDynamoDbCondition | undefined;
|
|
17
|
+
/** The top-level attributes the expressions named, for `dynamodb:Attributes`. */
|
|
18
|
+
readonly attributes: readonly string[];
|
|
17
19
|
}
|
|
18
20
|
/**
|
|
19
21
|
* Read both expressions of an update against one set of placeholders.
|
|
@@ -13,7 +13,7 @@ export function readSimDynamoDbUpdateExpressions(input, expression) {
|
|
|
13
13
|
const update = parseSimDynamoDbUpdate(expression, parameters);
|
|
14
14
|
const condition = conditionIn(input.ConditionExpression, parameters);
|
|
15
15
|
parameters.assertAllUsed();
|
|
16
|
-
return { update, condition };
|
|
16
|
+
return { update, condition, attributes: parameters.attributes.topLevel };
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
19
19
|
* Read the condition guarding an update, if it names one.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { simDynamoDbLeadingKeysOf } from "../authorize/sim-dynamodb-leading-keys.js";
|
|
2
|
+
import { simDynamoDbAttributesOf, simDynamoDbItemAttributeNames, } from "../authorize/sim-dynamodb-attributes.js";
|
|
2
3
|
import { readSimDynamoDbKey } from "./sim-dynamodb-key-input.js";
|
|
3
4
|
import { SimDynamoDbReturnValues } from "./sim-dynamodb-return-values.js";
|
|
4
5
|
import { refuseUnsimulatedItemUpdateInput } from "./sim-dynamodb-unsimulated-item-update-input.js";
|
|
@@ -29,7 +30,12 @@ export class SimDynamoDbUpdateItem {
|
|
|
29
30
|
// The expressions are read before the table is reached, so one DynamoDB
|
|
30
31
|
// would refuse is refused whether or not the key holds anything.
|
|
31
32
|
const plan = SimDynamoDbUpdatePlan.read(input, "UpdateItem");
|
|
32
|
-
const table = this.access.required("dynamodb:UpdateItem", input.TableName, options?.caller,
|
|
33
|
+
const table = this.access.required("dynamodb:UpdateItem", input.TableName, options?.caller, {
|
|
34
|
+
leadingKeys: simDynamoDbLeadingKeysOf(() => [
|
|
35
|
+
readSimDynamoDbKey(input.Key),
|
|
36
|
+
]),
|
|
37
|
+
attributes: simDynamoDbAttributesOf(plan.attributeNames, simDynamoDbItemAttributeNames(() => [readSimDynamoDbKey(input.Key)])),
|
|
38
|
+
});
|
|
33
39
|
const asked = SimDynamoDbReturnValues.readForUpdate(input.ReturnValues, "UpdateItem");
|
|
34
40
|
const key = readSimDynamoDbKey(input.Key);
|
|
35
41
|
const existing = table.getItem(key);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SimDynamoDbProjection } from "../../expression/projection/sim-dynamodb-projection.js";
|
|
1
|
+
import type { SimDynamoDbProjection } from "../../expression/projection/sim-dynamodb-projection.js";
|
|
2
2
|
import type { SimDynamoDbItem } from "../../item/sim-dynamodb-item.js";
|
|
3
3
|
import { SimDynamoDbConditionCheck } from "./sim-dynamodb-condition-check.js";
|
|
4
4
|
import { type SimDynamoDbUpdateExpressionInput } from "./sim-dynamodb-update-expressions.js";
|
|
@@ -10,6 +10,12 @@ interface SimDynamoDbUpdatePlanInput extends SimDynamoDbUpdateExpressionInput {
|
|
|
10
10
|
*/
|
|
11
11
|
export declare class SimDynamoDbUpdatePlan {
|
|
12
12
|
readonly check: SimDynamoDbConditionCheck;
|
|
13
|
+
/**
|
|
14
|
+
* The top-level attributes both expressions named, for
|
|
15
|
+
* `dynamodb:Attributes`. They share one set of placeholders, so the update
|
|
16
|
+
* and the condition guarding it are gathered together.
|
|
17
|
+
*/
|
|
18
|
+
readonly attributeNames: readonly string[];
|
|
13
19
|
private readonly update;
|
|
14
20
|
private constructor();
|
|
15
21
|
/**
|
|
@@ -24,11 +30,7 @@ export declare class SimDynamoDbUpdatePlan {
|
|
|
24
30
|
*/
|
|
25
31
|
assertLeavesKeyAlone(keyAttributeNames: readonly string[]): void;
|
|
26
32
|
/**
|
|
27
|
-
* The parts of an item this update touched
|
|
28
|
-
* answer with those and nothing else.
|
|
29
|
-
*
|
|
30
|
-
* A request that says nothing to change touched nothing, so the projection it
|
|
31
|
-
* answers with finds nothing in either item.
|
|
33
|
+
* The parts of an item this update touched.
|
|
32
34
|
*/
|
|
33
35
|
touched(): SimDynamoDbProjection;
|
|
34
36
|
/**
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { updateExpressionName } from "../../expression/update/sim-dynamodb-update-refusal.js";
|
|
1
|
+
import { simDynamoDbTouchedBy } from "./sim-dynamodb-update-touched.js";
|
|
3
2
|
import { SimDynamoDbConditionCheck } from "./sim-dynamodb-condition-check.js";
|
|
4
3
|
import { readSimDynamoDbUpdateExpressions, } from "./sim-dynamodb-update-expressions.js";
|
|
5
4
|
/**
|
|
@@ -7,10 +6,17 @@ import { readSimDynamoDbUpdateExpressions, } from "./sim-dynamodb-update-express
|
|
|
7
6
|
*/
|
|
8
7
|
export class SimDynamoDbUpdatePlan {
|
|
9
8
|
check;
|
|
9
|
+
/**
|
|
10
|
+
* The top-level attributes both expressions named, for
|
|
11
|
+
* `dynamodb:Attributes`. They share one set of placeholders, so the update
|
|
12
|
+
* and the condition guarding it are gathered together.
|
|
13
|
+
*/
|
|
14
|
+
attributeNames;
|
|
10
15
|
update;
|
|
11
16
|
constructor(properties) {
|
|
12
17
|
this.update = properties.update;
|
|
13
18
|
this.check = properties.check;
|
|
19
|
+
this.attributeNames = properties.attributeNames;
|
|
14
20
|
}
|
|
15
21
|
/**
|
|
16
22
|
* Read the expressions a request carries, before anything is looked up.
|
|
@@ -21,15 +27,18 @@ export class SimDynamoDbUpdatePlan {
|
|
|
21
27
|
static read(input, operation) {
|
|
22
28
|
const expression = input.UpdateExpression;
|
|
23
29
|
if (expression === undefined) {
|
|
30
|
+
const check = SimDynamoDbConditionCheck.read(input, operation);
|
|
24
31
|
return new this({
|
|
25
32
|
update: undefined,
|
|
26
|
-
check
|
|
33
|
+
check,
|
|
34
|
+
attributeNames: check.attributeNames,
|
|
27
35
|
});
|
|
28
36
|
}
|
|
29
37
|
const read = readSimDynamoDbUpdateExpressions(input, expression);
|
|
30
38
|
return new this({
|
|
31
39
|
update: read.update,
|
|
32
40
|
check: SimDynamoDbConditionCheck.of(read.condition, input, operation),
|
|
41
|
+
attributeNames: read.attributes,
|
|
33
42
|
});
|
|
34
43
|
}
|
|
35
44
|
/**
|
|
@@ -39,18 +48,10 @@ export class SimDynamoDbUpdatePlan {
|
|
|
39
48
|
this.update?.assertLeavesKeyAlone(keyAttributeNames);
|
|
40
49
|
}
|
|
41
50
|
/**
|
|
42
|
-
* The parts of an item this update touched
|
|
43
|
-
* answer with those and nothing else.
|
|
44
|
-
*
|
|
45
|
-
* A request that says nothing to change touched nothing, so the projection it
|
|
46
|
-
* answers with finds nothing in either item.
|
|
51
|
+
* The parts of an item this update touched.
|
|
47
52
|
*/
|
|
48
53
|
touched() {
|
|
49
|
-
return (this.update
|
|
50
|
-
new SimDynamoDbProjection({
|
|
51
|
-
expressionName: updateExpressionName,
|
|
52
|
-
paths: [],
|
|
53
|
-
}));
|
|
54
|
+
return simDynamoDbTouchedBy(this.update);
|
|
54
55
|
}
|
|
55
56
|
/**
|
|
56
57
|
* The item this update makes of the one that was there.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { SimDynamoDbProjection } from "../../expression/projection/sim-dynamodb-projection.js";
|
|
2
|
+
import type { SimDynamoDbUpdate } from "../../expression/update/sim-dynamodb-update.js";
|
|
3
|
+
/**
|
|
4
|
+
* The parts of an item an update touched, for the reporting modes that answer
|
|
5
|
+
* with those and nothing else.
|
|
6
|
+
*
|
|
7
|
+
* A request that says nothing to change touched nothing, so the projection it
|
|
8
|
+
* answers with finds nothing in either item.
|
|
9
|
+
*/
|
|
10
|
+
export declare function simDynamoDbTouchedBy(update: SimDynamoDbUpdate | undefined): SimDynamoDbProjection;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { SimDynamoDbProjection } from "../../expression/projection/sim-dynamodb-projection.js";
|
|
2
|
+
import { updateExpressionName } from "../../expression/update/sim-dynamodb-update-refusal.js";
|
|
3
|
+
/**
|
|
4
|
+
* The parts of an item an update touched, for the reporting modes that answer
|
|
5
|
+
* with those and nothing else.
|
|
6
|
+
*
|
|
7
|
+
* A request that says nothing to change touched nothing, so the projection it
|
|
8
|
+
* answers with finds nothing in either item.
|
|
9
|
+
*/
|
|
10
|
+
export function simDynamoDbTouchedBy(update) {
|
|
11
|
+
return (update?.touched() ??
|
|
12
|
+
new SimDynamoDbProjection({
|
|
13
|
+
expressionName: updateExpressionName,
|
|
14
|
+
paths: [],
|
|
15
|
+
}));
|
|
16
|
+
}
|
|
@@ -9,6 +9,8 @@ export interface SimDynamoDbQueryExpressions {
|
|
|
9
9
|
readonly terms: SimDynamoDbKeyConditionTerms;
|
|
10
10
|
readonly filter: SimDynamoDbFilter | undefined;
|
|
11
11
|
readonly projection: SimDynamoDbProjection | undefined;
|
|
12
|
+
/** The top-level attributes the expressions named, for `dynamodb:Attributes`. */
|
|
13
|
+
readonly attributes: readonly string[];
|
|
12
14
|
}
|
|
13
15
|
/**
|
|
14
16
|
* Read every expression of a query against one set of placeholders.
|
|
@@ -21,7 +21,12 @@ export function readSimDynamoDbQueryExpressions(input) {
|
|
|
21
21
|
const filter = filterIn(input.FilterExpression, parameters);
|
|
22
22
|
const projection = projectionIn(input.ProjectionExpression, parameters);
|
|
23
23
|
parameters.assertAllUsed();
|
|
24
|
-
return {
|
|
24
|
+
return {
|
|
25
|
+
terms,
|
|
26
|
+
filter,
|
|
27
|
+
projection,
|
|
28
|
+
attributes: parameters.attributes.topLevel,
|
|
29
|
+
};
|
|
25
30
|
}
|
|
26
31
|
/**
|
|
27
32
|
* Read the filter a query drops read items by, if it names one.
|