From 38b1a2882c70da815b081a378d39bb6dec06d4d2 Mon Sep 17 00:00:00 2001 From: George Fu Date: Mon, 1 Aug 2022 13:04:42 -0400 Subject: [PATCH] fix(lib-dynamodb): make command middleware useable, turn marshalling into middleware (#3808) * fix(lib-dynamodb): make command middleware useable, turn marshalling into middleware * fix(lib-dynamodb): fix unit test * fix(lib-dynamodb): move inner command construction to ctor body * fix(lib-dynamodb): remove command name field * fix(lib-dynamodb): fix ctor code order --- .../DocumentClientCommandGenerator.java | 133 +++++++++--------- lib/lib-dynamodb/README.md | 73 ++++++++++ .../DynamoDBDocumentClientCommand.spec.ts | 57 ++++++++ .../DynamoDBDocumentClientCommand.ts | 65 +++++++++ .../commands/BatchExecuteStatementCommand.ts | 33 +++-- .../src/commands/BatchGetCommand.ts | 33 +++-- .../src/commands/BatchWriteCommand.ts | 33 +++-- .../src/commands/DeleteCommand.ts | 33 +++-- .../src/commands/ExecuteStatementCommand.ts | 35 ++--- .../src/commands/ExecuteTransactionCommand.ts | 33 +++-- lib/lib-dynamodb/src/commands/GetCommand.ts | 39 ++--- lib/lib-dynamodb/src/commands/PutCommand.ts | 37 +++-- lib/lib-dynamodb/src/commands/QueryCommand.ts | 33 +++-- lib/lib-dynamodb/src/commands/ScanCommand.ts | 37 +++-- .../src/commands/TransactGetCommand.ts | 33 +++-- .../src/commands/TransactWriteCommand.ts | 33 +++-- .../src/commands/UpdateCommand.ts | 33 +++-- packages/util-dynamodb/src/marshall.ts | 1 + 18 files changed, 512 insertions(+), 262 deletions(-) create mode 100644 lib/lib-dynamodb/src/baseCommand/DynamoDBDocumentClientCommand.spec.ts create mode 100644 lib/lib-dynamodb/src/baseCommand/DynamoDBDocumentClientCommand.ts diff --git a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/DocumentClientCommandGenerator.java b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/DocumentClientCommandGenerator.java index 75890893e9d8..432dd703e475 100644 --- a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/DocumentClientCommandGenerator.java +++ b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/DocumentClientCommandGenerator.java @@ -15,8 +15,6 @@ package software.amazon.smithy.aws.typescript.codegen; -import static software.amazon.smithy.aws.typescript.codegen.propertyaccess.PropertyAccessor.getFrom; - import java.nio.file.Paths; import java.util.ArrayList; import java.util.HashSet; @@ -55,10 +53,14 @@ final class DocumentClientCommandGenerator implements Runnable { private final TypeScriptWriter writer; private final Symbol symbol; private final OperationIndex operationIndex; + private final String originalInputTypeName; private final String inputTypeName; private final List inputMembersWithAttr; + private final String originalOutputTypeName; private final String outputTypeName; private final List outputMembersWithAttr; + private final String clientCommandClassName; + private final String clientCommandLocalName; DocumentClientCommandGenerator( TypeScriptSettings settings, @@ -75,14 +77,21 @@ final class DocumentClientCommandGenerator implements Runnable { symbol = symbolProvider.toSymbol(operation); operationIndex = OperationIndex.of(model); + String inputType = symbol.expectProperty("inputType", Symbol.class).getName(); + originalInputTypeName = inputType; inputTypeName = DocumentClientUtils.getModifiedName( - symbol.expectProperty("inputType", Symbol.class).getName() + inputType ); inputMembersWithAttr = getStructureMembersWithAttr(operationIndex.getInput(operation)); + String outputType = symbol.expectProperty("outputType", Symbol.class).getName(); + originalOutputTypeName = outputType; outputTypeName = DocumentClientUtils.getModifiedName( - symbol.expectProperty("outputType", Symbol.class).getName() + outputType ); outputMembersWithAttr = getStructureMembersWithAttr(operationIndex.getOutput(operation)); + + clientCommandClassName = symbol.getName(); + clientCommandLocalName = "__" + clientCommandClassName; } @Override @@ -92,37 +101,56 @@ public void run() { // Add required imports. writer.addImport(configType, configType, servicePath); - writer.addImport("Command", "$Command", "@aws-sdk/smithy-client"); + writer.addImport( + "DynamoDBDocumentClientCommand", + "DynamoDBDocumentClientCommand", + "./baseCommand/DynamoDBDocumentClientCommand" + ); generateInputAndOutputTypes(); + String ioTypes = String.join(", ", new String[]{ + inputTypeName, + outputTypeName, + "__" + originalInputTypeName, + "__" + originalOutputTypeName + }); + String name = DocumentClientUtils.getModifiedName(symbol.getName()); writer.writeDocs(DocumentClientUtils.getCommandDocs(symbol.getName())); - writer.openBlock("export class $L extends $$Command<$L, $L, $L> {", "}", - name, inputTypeName, outputTypeName, configType, () -> { - - // Section for adding custom command properties. - writer.pushState(COMMAND_PROPERTIES_SECTION); - if (!inputMembersWithAttr.isEmpty()) { - writer.openBlock("private readonly $L = [", "];", COMMAND_INPUT_KEYNODES, () -> { + writer.openBlock( + "export class $L extends DynamoDBDocumentClientCommand<" + ioTypes + ", $L> {", + "}", + name, + configType, + () -> { + // Section for adding custom command properties. + writer.pushState(COMMAND_PROPERTIES_SECTION); + writer.openBlock("protected readonly $L = [", "];", COMMAND_INPUT_KEYNODES, () -> { writeKeyNodes(inputMembersWithAttr); }); - } - if (!outputMembersWithAttr.isEmpty()) { - writer.openBlock("private readonly $L = [", "];", COMMAND_OUTPUT_KEYNODES, () -> { + writer.openBlock("protected readonly $L = [", "];", COMMAND_OUTPUT_KEYNODES, () -> { writeKeyNodes(outputMembersWithAttr); }); - } - writer.popState(); - writer.write(""); + writer.popState(); + writer.write(""); + + writer.write("protected readonly clientCommand: $L;", clientCommandLocalName); + writer.write( + "public readonly middlewareStack: MiddlewareStack<$L>;", + inputTypeName + " | __" + originalInputTypeName + + ", \n" + outputTypeName + " | __" + originalOutputTypeName + ); + writer.write(""); - generateCommandConstructor(); - writer.write(""); - generateCommandMiddlewareResolver(configType); + generateCommandConstructor(); + writer.write(""); + generateCommandMiddlewareResolver(configType); - // Hook for adding more methods to the command. - writer.pushState(COMMAND_BODY_EXTRA_SECTION).popState(); - }); + // Hook for adding more methods to the command. + writer.pushState(COMMAND_BODY_EXTRA_SECTION).popState(); + } + ); } private void generateCommandConstructor() { @@ -130,6 +158,8 @@ private void generateCommandConstructor() { // The constructor can be intercepted and changed. writer.pushState(COMMAND_CONSTRUCTOR_SECTION) .write("super();") + .write("this.clientCommand = new $L(this.input as any);", clientCommandLocalName) + .write("this.middlewareStack = this.clientCommand.middlewareStack;") .popState(); }); } @@ -155,52 +185,27 @@ private void generateCommandMiddlewareResolver(String configType) { .write("options?: $T", ApplicationProtocol.createDefaultHttpApplicationProtocol().getOptionsType()) .dedent(); writer.openBlock("): $L<$L, $L> {", "}", handler, inputTypeName, outputTypeName, () -> { - String marshallOptions = DocumentClientUtils.CLIENT_MARSHALL_OPTIONS; - String unmarshallOptions = DocumentClientUtils.CLIENT_UNMARSHALL_OPTIONS; - - writer.write("const { $L, $L } = configuration.$L || {};", marshallOptions, unmarshallOptions, - DocumentClientUtils.CLIENT_TRANSLATE_CONFIG_KEY); - - writer.addImport(symbol.getName(), "__" + symbol.getName(), "@aws-sdk/client-dynamodb"); - - String marshallInput = "marshallInput"; - String unmarshallOutput = "unmarshallOutput"; - String utilsFileLocation = String.format("./%s/%s", - DocumentClientUtils.CLIENT_COMMANDS_FOLDER, DocumentClientUtils.CLIENT_UTILS_FILE); - writer.addImport(marshallInput, marshallInput, utilsFileLocation); - writer.addImport(unmarshallOutput, unmarshallOutput, utilsFileLocation); - - String commandVarName = "command"; - writer.openBlock("const $L = new $L(", ");", commandVarName, "__" + symbol.getName(), - () -> { - if (inputMembersWithAttr.isEmpty()) { - writer.write("this.input,"); - } else { - writer.openBlock("$L(", ")", marshallInput, () -> { - writer.write("this.input,"); - writer.write(getFrom("this", COMMAND_INPUT_KEYNODES) + ","); - writer.write("$L,", marshallOptions); - }); - } - }); + + writer.addImport(clientCommandClassName, clientCommandLocalName, "@aws-sdk/client-dynamodb"); + + String commandVarName = "this.clientCommand"; + + // marshall middlewares + writer.openBlock("this.addMarshallingMiddleware(", ");", () -> { + writer.write("configuration"); + }); + + writer.write("const stack = clientStack.concat(this.middlewareStack as typeof clientStack);"); + String handlerVarName = "handler"; - writer.write("const $L = $L.resolveMiddleware(clientStack, configuration, options);", + writer.write("const $L = $L.resolveMiddleware(stack, configuration, options);", handlerVarName, commandVarName); writer.write(""); if (outputMembersWithAttr.isEmpty()) { writer.write("return $L;", handlerVarName); } else { - writer.openBlock("return async () => {", "};", () -> { - String dataVarName = "data"; - String outputVarName = "output"; - writer.write("const $L = await $L($L);", dataVarName, handlerVarName, commandVarName); - writer.openBlock("return {", "};", () -> { - writer.write("...$L,", dataVarName); - writer.write("$1L: $2L($3L.$1L, this.$4L, $5L),", outputVarName, unmarshallOutput, - dataVarName, COMMAND_OUTPUT_KEYNODES, unmarshallOptions); - }); - }); + writer.write("return async () => handler($L)", commandVarName); } }); } @@ -259,10 +264,8 @@ private void writeStructureKeyNode(StructureShape structureTarget) { private void generateInputAndOutputTypes() { writer.write(""); - String originalInputTypeName = symbol.expectProperty("inputType", Symbol.class).getName(); writeType(inputTypeName, originalInputTypeName, operationIndex.getInput(operation), inputMembersWithAttr); writer.write(""); - String originalOutputTypeName = symbol.expectProperty("outputType", Symbol.class).getName(); writeType(outputTypeName, originalOutputTypeName, operationIndex.getOutput(operation), outputMembersWithAttr); writer.write(""); } diff --git a/lib/lib-dynamodb/README.md b/lib/lib-dynamodb/README.md index 714592d455cf..e821136fa2ba 100644 --- a/lib/lib-dynamodb/README.md +++ b/lib/lib-dynamodb/README.md @@ -160,6 +160,79 @@ await ddbDocClient.put({ }); ``` +### Client and Command middleware stacks + +As with other AWS SDK for JavaScript v3 clients, you can apply middleware functions +both on the client itself and individual `Command`s. + +For individual `Command`s, here are examples of how to add middleware before and after +both marshalling and unmarshalling. We will use `QueryCommand` as an example. +Others follow the same pattern. + +```js +import { DynamoDBDocumentClient, QueryCommand } from "@aws-sdk/lib-dynamodb"; + +const client = new DynamoDBClient({ + /*...*/ +}); +const doc = DynamoDBDocumentClient.from(client); +const command = new QueryCommand({ + /*...*/ +}); +``` + +Before and after marshalling: + +```js +command.middlewareStack.addRelativeTo( + (next) => async (args) => { + console.log("pre-marshall", args.input); + return next(args); + }, + { + relation: "before", + toMiddleware: "DocumentMarshall", + } +); +command.middlewareStack.addRelativeTo( + (next) => async (args) => { + console.log("post-marshall", args.input); + return next(args); + }, + { + relation: "after", + toMiddleware: "DocumentMarshall", + } +); +``` + +Before and after unmarshalling: + +```js +command.middlewareStack.addRelativeTo( + (next) => async (args) => { + const result = await next(args); + console.log("pre-unmarshall", result.output.Items); + return result; + }, + { + relation: "after", // <- after for pre-unmarshall + toMiddleware: "DocumentUnmarshall", + } +); +command.middlewareStack.addRelativeTo( + (next) => async (args) => { + const result = await next(args); + console.log("post-unmarshall", result.output.Items); + return result; + }, + { + relation: "before", // <- before for post-unmarshall + toMiddleware: "DocumentUnmarshall", + } +); +``` + ### Destroying document client The `destroy()` call on document client is a no-op as document client does not diff --git a/lib/lib-dynamodb/src/baseCommand/DynamoDBDocumentClientCommand.spec.ts b/lib/lib-dynamodb/src/baseCommand/DynamoDBDocumentClientCommand.spec.ts new file mode 100644 index 000000000000..858d65b96b8f --- /dev/null +++ b/lib/lib-dynamodb/src/baseCommand/DynamoDBDocumentClientCommand.spec.ts @@ -0,0 +1,57 @@ +import { Handler, MiddlewareStack } from "@aws-sdk/types"; + +import { KeyNode } from "../commands/utils"; +import { DynamoDBDocumentClientCommand } from "./DynamoDBDocumentClientCommand"; + +class AnyCommand extends DynamoDBDocumentClientCommand<{}, {}, {}, {}, {}> { + public middlewareStack: MiddlewareStack<{}, {}>; + public input: {}; + protected inputKeyNodes: KeyNode[] = []; + protected outputKeyNodes: KeyNode[] = []; + + public argCaptor: [Function, object][] = []; + + protected readonly clientCommand = { + middlewareStack: { + argCaptor: this.argCaptor, + add(fn, config) { + this.argCaptor.push([fn, config]); + }, + }, + } as any; + protected readonly clientCommandName = "AnyCommand"; + + public constructor() { + super(); + } + + public resolveMiddleware(clientStack: MiddlewareStack, configuration: {}, options: any): Handler<{}, {}> { + this.addMarshallingMiddleware({} as any); + return null as any; + } +} + +describe("DynamoDBDocumentClientCommand", () => { + it("should not allow usage of the default middlewareStack", () => { + const command = new AnyCommand(); + command.resolveMiddleware(null as any, null as any, null as any); + { + const [middleware, options] = command.argCaptor[0]; + expect(middleware.toString()).toContain(`marshallInput`); + expect(options).toEqual({ + name: "DocumentMarshall", + override: true, + step: "initialize", + }); + } + { + const [middleware, options] = command.argCaptor[1]; + expect(middleware.toString()).toContain(`unmarshallOutput`); + expect(options).toEqual({ + name: "DocumentUnmarshall", + override: true, + step: "deserialize", + }); + } + }); +}); diff --git a/lib/lib-dynamodb/src/baseCommand/DynamoDBDocumentClientCommand.ts b/lib/lib-dynamodb/src/baseCommand/DynamoDBDocumentClientCommand.ts new file mode 100644 index 000000000000..a322542f323b --- /dev/null +++ b/lib/lib-dynamodb/src/baseCommand/DynamoDBDocumentClientCommand.ts @@ -0,0 +1,65 @@ +import { Command as $Command } from "@aws-sdk/smithy-client"; +import { + DeserializeHandler, + DeserializeHandlerArguments, + DeserializeHandlerOutput, + InitializeHandler, + InitializeHandlerArguments, + InitializeHandlerOutput, + MiddlewareStack, +} from "@aws-sdk/types"; + +import { KeyNode, marshallInput, unmarshallOutput } from "../commands/utils"; +import { DynamoDBDocumentClientResolvedConfig } from "../DynamoDBDocumentClient"; + +/** + * Base class for Commands in lib-dynamodb used to pass middleware to + * the underlying DynamoDBClient Commands. + */ +export abstract class DynamoDBDocumentClientCommand< + Input extends object, + Output extends object, + BaseInput extends object, + BaseOutput extends object, + ResolvedClientConfiguration +> extends $Command { + protected abstract readonly inputKeyNodes: KeyNode[]; + protected abstract readonly outputKeyNodes: KeyNode[]; + protected abstract clientCommand: $Command; + + public abstract middlewareStack: MiddlewareStack; + + protected addMarshallingMiddleware(configuration: DynamoDBDocumentClientResolvedConfig): void { + const { marshallOptions, unmarshallOptions } = configuration.translateConfig || {}; + + this.clientCommand.middlewareStack.add( + (next: InitializeHandler) => + async ( + args: InitializeHandlerArguments + ): Promise> => { + args.input = marshallInput(this.input, this.inputKeyNodes, marshallOptions); + return next(args); + }, + { + name: "DocumentMarshall", + step: "initialize", + override: true, + } + ); + this.clientCommand.middlewareStack.add( + (next: DeserializeHandler) => + async ( + args: DeserializeHandlerArguments + ): Promise> => { + const deserialized = await next(args); + deserialized.output = unmarshallOutput(deserialized.output, this.outputKeyNodes, unmarshallOptions); + return deserialized; + }, + { + name: "DocumentUnmarshall", + step: "deserialize", + override: true, + } + ); + } +} diff --git a/lib/lib-dynamodb/src/commands/BatchExecuteStatementCommand.ts b/lib/lib-dynamodb/src/commands/BatchExecuteStatementCommand.ts index 3140f7d3de54..26a412197d1d 100644 --- a/lib/lib-dynamodb/src/commands/BatchExecuteStatementCommand.ts +++ b/lib/lib-dynamodb/src/commands/BatchExecuteStatementCommand.ts @@ -6,11 +6,10 @@ import { BatchStatementRequest, BatchStatementResponse, } from "@aws-sdk/client-dynamodb"; -import { Command as $Command } from "@aws-sdk/smithy-client"; import { Handler, HttpHandlerOptions as __HttpHandlerOptions, MiddlewareStack } from "@aws-sdk/types"; import { NativeAttributeValue } from "@aws-sdk/util-dynamodb"; -import { marshallInput, unmarshallOutput } from "../commands/utils"; +import { DynamoDBDocumentClientCommand } from "../baseCommand/DynamoDBDocumentClientCommand"; import { DynamoDBDocumentClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../DynamoDBDocumentClient"; export type BatchExecuteStatementCommandInput = Omit<__BatchExecuteStatementCommandInput, "Statements"> & { @@ -34,16 +33,26 @@ export type BatchExecuteStatementCommandOutput = Omit<__BatchExecuteStatementCom * JavaScript objects passed in as parameters are marshalled into `AttributeValue` shapes * required by Amazon DynamoDB. Responses from DynamoDB are unmarshalled into plain JavaScript objects. */ -export class BatchExecuteStatementCommand extends $Command< +export class BatchExecuteStatementCommand extends DynamoDBDocumentClientCommand< BatchExecuteStatementCommandInput, BatchExecuteStatementCommandOutput, + __BatchExecuteStatementCommandInput, + __BatchExecuteStatementCommandOutput, DynamoDBDocumentClientResolvedConfig > { - private readonly inputKeyNodes = [{ key: "Statements", children: [{ key: "Parameters" }] }]; - private readonly outputKeyNodes = [{ key: "Responses", children: [{ key: "Item" }] }]; + protected readonly inputKeyNodes = [{ key: "Statements", children: [{ key: "Parameters" }] }]; + protected readonly outputKeyNodes = [{ key: "Responses", children: [{ key: "Item" }] }]; + + protected readonly clientCommand: __BatchExecuteStatementCommand; + public readonly middlewareStack: MiddlewareStack< + BatchExecuteStatementCommandInput | __BatchExecuteStatementCommandInput, + BatchExecuteStatementCommandOutput | __BatchExecuteStatementCommandOutput + >; constructor(readonly input: BatchExecuteStatementCommandInput) { super(); + this.clientCommand = new __BatchExecuteStatementCommand(this.input as any); + this.middlewareStack = this.clientCommand.middlewareStack; } /** @@ -54,16 +63,10 @@ export class BatchExecuteStatementCommand extends $Command< configuration: DynamoDBDocumentClientResolvedConfig, options?: __HttpHandlerOptions ): Handler { - const { marshallOptions, unmarshallOptions } = configuration.translateConfig || {}; - const command = new __BatchExecuteStatementCommand(marshallInput(this.input, this.inputKeyNodes, marshallOptions)); - const handler = command.resolveMiddleware(clientStack, configuration, options); + this.addMarshallingMiddleware(configuration); + const stack = clientStack.concat(this.middlewareStack as typeof clientStack); + const handler = this.clientCommand.resolveMiddleware(stack, configuration, options); - return async () => { - const data = await handler(command); - return { - ...data, - output: unmarshallOutput(data.output, this.outputKeyNodes, unmarshallOptions), - }; - }; + return async () => handler(this.clientCommand); } } diff --git a/lib/lib-dynamodb/src/commands/BatchGetCommand.ts b/lib/lib-dynamodb/src/commands/BatchGetCommand.ts index 7eb8191f09ad..7071449ea55d 100644 --- a/lib/lib-dynamodb/src/commands/BatchGetCommand.ts +++ b/lib/lib-dynamodb/src/commands/BatchGetCommand.ts @@ -5,11 +5,10 @@ import { BatchGetItemCommandOutput as __BatchGetItemCommandOutput, KeysAndAttributes, } from "@aws-sdk/client-dynamodb"; -import { Command as $Command } from "@aws-sdk/smithy-client"; import { Handler, HttpHandlerOptions as __HttpHandlerOptions, MiddlewareStack } from "@aws-sdk/types"; import { NativeAttributeValue } from "@aws-sdk/util-dynamodb"; -import { marshallInput, unmarshallOutput } from "../commands/utils"; +import { DynamoDBDocumentClientCommand } from "../baseCommand/DynamoDBDocumentClientCommand"; import { DynamoDBDocumentClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../DynamoDBDocumentClient"; export type BatchGetCommandInput = Omit<__BatchGetItemCommandInput, "RequestItems"> & { @@ -40,12 +39,14 @@ export type BatchGetCommandOutput = Omit<__BatchGetItemCommandOutput, "Responses * JavaScript objects passed in as parameters are marshalled into `AttributeValue` shapes * required by Amazon DynamoDB. Responses from DynamoDB are unmarshalled into plain JavaScript objects. */ -export class BatchGetCommand extends $Command< +export class BatchGetCommand extends DynamoDBDocumentClientCommand< BatchGetCommandInput, BatchGetCommandOutput, + __BatchGetItemCommandInput, + __BatchGetItemCommandOutput, DynamoDBDocumentClientResolvedConfig > { - private readonly inputKeyNodes = [ + protected readonly inputKeyNodes = [ { key: "RequestItems", children: { @@ -53,7 +54,7 @@ export class BatchGetCommand extends $Command< }, }, ]; - private readonly outputKeyNodes = [ + protected readonly outputKeyNodes = [ { key: "Responses", children: {} }, { key: "UnprocessedKeys", @@ -63,8 +64,16 @@ export class BatchGetCommand extends $Command< }, ]; + protected readonly clientCommand: __BatchGetItemCommand; + public readonly middlewareStack: MiddlewareStack< + BatchGetCommandInput | __BatchGetItemCommandInput, + BatchGetCommandOutput | __BatchGetItemCommandOutput + >; + constructor(readonly input: BatchGetCommandInput) { super(); + this.clientCommand = new __BatchGetItemCommand(this.input as any); + this.middlewareStack = this.clientCommand.middlewareStack; } /** @@ -75,16 +84,10 @@ export class BatchGetCommand extends $Command< configuration: DynamoDBDocumentClientResolvedConfig, options?: __HttpHandlerOptions ): Handler { - const { marshallOptions, unmarshallOptions } = configuration.translateConfig || {}; - const command = new __BatchGetItemCommand(marshallInput(this.input, this.inputKeyNodes, marshallOptions)); - const handler = command.resolveMiddleware(clientStack, configuration, options); + this.addMarshallingMiddleware(configuration); + const stack = clientStack.concat(this.middlewareStack as typeof clientStack); + const handler = this.clientCommand.resolveMiddleware(stack, configuration, options); - return async () => { - const data = await handler(command); - return { - ...data, - output: unmarshallOutput(data.output, this.outputKeyNodes, unmarshallOptions), - }; - }; + return async () => handler(this.clientCommand); } } diff --git a/lib/lib-dynamodb/src/commands/BatchWriteCommand.ts b/lib/lib-dynamodb/src/commands/BatchWriteCommand.ts index a86cc1616a9b..58a7fb410cc9 100644 --- a/lib/lib-dynamodb/src/commands/BatchWriteCommand.ts +++ b/lib/lib-dynamodb/src/commands/BatchWriteCommand.ts @@ -8,11 +8,10 @@ import { PutRequest, WriteRequest, } from "@aws-sdk/client-dynamodb"; -import { Command as $Command } from "@aws-sdk/smithy-client"; import { Handler, HttpHandlerOptions as __HttpHandlerOptions, MiddlewareStack } from "@aws-sdk/types"; import { NativeAttributeValue } from "@aws-sdk/util-dynamodb"; -import { marshallInput, unmarshallOutput } from "../commands/utils"; +import { DynamoDBDocumentClientCommand } from "../baseCommand/DynamoDBDocumentClientCommand"; import { DynamoDBDocumentClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../DynamoDBDocumentClient"; export type BatchWriteCommandInput = Omit<__BatchWriteItemCommandInput, "RequestItems"> & { @@ -61,12 +60,14 @@ export type BatchWriteCommandOutput = Omit< * JavaScript objects passed in as parameters are marshalled into `AttributeValue` shapes * required by Amazon DynamoDB. Responses from DynamoDB are unmarshalled into plain JavaScript objects. */ -export class BatchWriteCommand extends $Command< +export class BatchWriteCommand extends DynamoDBDocumentClientCommand< BatchWriteCommandInput, BatchWriteCommandOutput, + __BatchWriteItemCommandInput, + __BatchWriteItemCommandOutput, DynamoDBDocumentClientResolvedConfig > { - private readonly inputKeyNodes = [ + protected readonly inputKeyNodes = [ { key: "RequestItems", children: { @@ -77,7 +78,7 @@ export class BatchWriteCommand extends $Command< }, }, ]; - private readonly outputKeyNodes = [ + protected readonly outputKeyNodes = [ { key: "UnprocessedItems", children: { @@ -95,8 +96,16 @@ export class BatchWriteCommand extends $Command< }, ]; + protected readonly clientCommand: __BatchWriteItemCommand; + public readonly middlewareStack: MiddlewareStack< + BatchWriteCommandInput | __BatchWriteItemCommandInput, + BatchWriteCommandOutput | __BatchWriteItemCommandOutput + >; + constructor(readonly input: BatchWriteCommandInput) { super(); + this.clientCommand = new __BatchWriteItemCommand(this.input as any); + this.middlewareStack = this.clientCommand.middlewareStack; } /** @@ -107,16 +116,10 @@ export class BatchWriteCommand extends $Command< configuration: DynamoDBDocumentClientResolvedConfig, options?: __HttpHandlerOptions ): Handler { - const { marshallOptions, unmarshallOptions } = configuration.translateConfig || {}; - const command = new __BatchWriteItemCommand(marshallInput(this.input, this.inputKeyNodes, marshallOptions)); - const handler = command.resolveMiddleware(clientStack, configuration, options); + this.addMarshallingMiddleware(configuration); + const stack = clientStack.concat(this.middlewareStack as typeof clientStack); + const handler = this.clientCommand.resolveMiddleware(stack, configuration, options); - return async () => { - const data = await handler(command); - return { - ...data, - output: unmarshallOutput(data.output, this.outputKeyNodes, unmarshallOptions), - }; - }; + return async () => handler(this.clientCommand); } } diff --git a/lib/lib-dynamodb/src/commands/DeleteCommand.ts b/lib/lib-dynamodb/src/commands/DeleteCommand.ts index 0d23617e65af..a81ae623ac4b 100644 --- a/lib/lib-dynamodb/src/commands/DeleteCommand.ts +++ b/lib/lib-dynamodb/src/commands/DeleteCommand.ts @@ -6,11 +6,10 @@ import { ExpectedAttributeValue, ItemCollectionMetrics, } from "@aws-sdk/client-dynamodb"; -import { Command as $Command } from "@aws-sdk/smithy-client"; import { Handler, HttpHandlerOptions as __HttpHandlerOptions, MiddlewareStack } from "@aws-sdk/types"; import { NativeAttributeValue } from "@aws-sdk/util-dynamodb"; -import { marshallInput, unmarshallOutput } from "../commands/utils"; +import { DynamoDBDocumentClientCommand } from "../baseCommand/DynamoDBDocumentClientCommand"; import { DynamoDBDocumentClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../DynamoDBDocumentClient"; export type DeleteCommandInput = Omit<__DeleteItemCommandInput, "Key" | "Expected" | "ExpressionAttributeValues"> & { @@ -39,12 +38,14 @@ export type DeleteCommandOutput = Omit<__DeleteItemCommandOutput, "Attributes" | * JavaScript objects passed in as parameters are marshalled into `AttributeValue` shapes * required by Amazon DynamoDB. Responses from DynamoDB are unmarshalled into plain JavaScript objects. */ -export class DeleteCommand extends $Command< +export class DeleteCommand extends DynamoDBDocumentClientCommand< DeleteCommandInput, DeleteCommandOutput, + __DeleteItemCommandInput, + __DeleteItemCommandOutput, DynamoDBDocumentClientResolvedConfig > { - private readonly inputKeyNodes = [ + protected readonly inputKeyNodes = [ { key: "Key" }, { key: "Expected", @@ -54,13 +55,21 @@ export class DeleteCommand extends $Command< }, { key: "ExpressionAttributeValues" }, ]; - private readonly outputKeyNodes = [ + protected readonly outputKeyNodes = [ { key: "Attributes" }, { key: "ItemCollectionMetrics", children: [{ key: "ItemCollectionKey" }] }, ]; + protected readonly clientCommand: __DeleteItemCommand; + public readonly middlewareStack: MiddlewareStack< + DeleteCommandInput | __DeleteItemCommandInput, + DeleteCommandOutput | __DeleteItemCommandOutput + >; + constructor(readonly input: DeleteCommandInput) { super(); + this.clientCommand = new __DeleteItemCommand(this.input as any); + this.middlewareStack = this.clientCommand.middlewareStack; } /** @@ -71,16 +80,10 @@ export class DeleteCommand extends $Command< configuration: DynamoDBDocumentClientResolvedConfig, options?: __HttpHandlerOptions ): Handler { - const { marshallOptions, unmarshallOptions } = configuration.translateConfig || {}; - const command = new __DeleteItemCommand(marshallInput(this.input, this.inputKeyNodes, marshallOptions)); - const handler = command.resolveMiddleware(clientStack, configuration, options); + this.addMarshallingMiddleware(configuration); + const stack = clientStack.concat(this.middlewareStack as typeof clientStack); + const handler = this.clientCommand.resolveMiddleware(stack, configuration, options); - return async () => { - const data = await handler(command); - return { - ...data, - output: unmarshallOutput(data.output, this.outputKeyNodes, unmarshallOptions), - }; - }; + return async () => handler(this.clientCommand); } } diff --git a/lib/lib-dynamodb/src/commands/ExecuteStatementCommand.ts b/lib/lib-dynamodb/src/commands/ExecuteStatementCommand.ts index a43d85841511..98f99fce9fb9 100644 --- a/lib/lib-dynamodb/src/commands/ExecuteStatementCommand.ts +++ b/lib/lib-dynamodb/src/commands/ExecuteStatementCommand.ts @@ -4,11 +4,10 @@ import { ExecuteStatementCommandInput as __ExecuteStatementCommandInput, ExecuteStatementCommandOutput as __ExecuteStatementCommandOutput, } from "@aws-sdk/client-dynamodb"; -import { Command as $Command } from "@aws-sdk/smithy-client"; import { Handler, HttpHandlerOptions as __HttpHandlerOptions, MiddlewareStack } from "@aws-sdk/types"; import { NativeAttributeValue } from "@aws-sdk/util-dynamodb"; -import { marshallInput, unmarshallOutput } from "../commands/utils"; +import { DynamoDBDocumentClientCommand } from "../baseCommand/DynamoDBDocumentClientCommand"; import { DynamoDBDocumentClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../DynamoDBDocumentClient"; export type ExecuteStatementCommandInput = Omit<__ExecuteStatementCommandInput, "Parameters"> & { @@ -27,16 +26,26 @@ export type ExecuteStatementCommandOutput = Omit<__ExecuteStatementCommandOutput * JavaScript objects passed in as parameters are marshalled into `AttributeValue` shapes * required by Amazon DynamoDB. Responses from DynamoDB are unmarshalled into plain JavaScript objects. */ -export class ExecuteStatementCommand extends $Command< +export class ExecuteStatementCommand extends DynamoDBDocumentClientCommand< ExecuteStatementCommandInput, ExecuteStatementCommandOutput, + __ExecuteStatementCommandInput, + __ExecuteStatementCommandOutput, DynamoDBDocumentClientResolvedConfig > { - private readonly inputKeyNodes = [{ key: "Parameters" }]; - private readonly outputKeyNodes = [{ key: "Items" }, { key: "LastEvaluatedKey" }]; + protected readonly inputKeyNodes = [{ key: "Parameters" }]; + protected readonly outputKeyNodes = [{ key: "Items" }, { key: "LastEvaluatedKey" }]; + + protected readonly clientCommand: __ExecuteStatementCommand; + public readonly middlewareStack: MiddlewareStack< + ExecuteStatementCommandInput | __ExecuteStatementCommandInput, + ExecuteStatementCommandOutput | __ExecuteStatementCommandOutput + >; constructor(readonly input: ExecuteStatementCommandInput) { super(); + this.clientCommand = new __ExecuteStatementCommand(this.input as any); + this.middlewareStack = this.clientCommand.middlewareStack; } /** @@ -47,16 +56,10 @@ export class ExecuteStatementCommand extends $Command< configuration: DynamoDBDocumentClientResolvedConfig, options?: __HttpHandlerOptions ): Handler { - const { marshallOptions, unmarshallOptions } = configuration.translateConfig || {}; - const command = new __ExecuteStatementCommand(marshallInput(this.input, this.inputKeyNodes, marshallOptions)); - const handler = command.resolveMiddleware(clientStack, configuration, options); - - return async () => { - const data = await handler(command); - return { - ...data, - output: unmarshallOutput(data.output, this.outputKeyNodes, unmarshallOptions), - }; - }; + this.addMarshallingMiddleware(configuration); + const stack = clientStack.concat(this.middlewareStack as typeof clientStack); + const handler = this.clientCommand.resolveMiddleware(stack, configuration, options); + + return async () => handler(this.clientCommand); } } diff --git a/lib/lib-dynamodb/src/commands/ExecuteTransactionCommand.ts b/lib/lib-dynamodb/src/commands/ExecuteTransactionCommand.ts index f2fcd0d82ad6..e5ef0798332f 100644 --- a/lib/lib-dynamodb/src/commands/ExecuteTransactionCommand.ts +++ b/lib/lib-dynamodb/src/commands/ExecuteTransactionCommand.ts @@ -6,11 +6,10 @@ import { ItemResponse, ParameterizedStatement, } from "@aws-sdk/client-dynamodb"; -import { Command as $Command } from "@aws-sdk/smithy-client"; import { Handler, HttpHandlerOptions as __HttpHandlerOptions, MiddlewareStack } from "@aws-sdk/types"; import { NativeAttributeValue } from "@aws-sdk/util-dynamodb"; -import { marshallInput, unmarshallOutput } from "../commands/utils"; +import { DynamoDBDocumentClientCommand } from "../baseCommand/DynamoDBDocumentClientCommand"; import { DynamoDBDocumentClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../DynamoDBDocumentClient"; export type ExecuteTransactionCommandInput = Omit<__ExecuteTransactionCommandInput, "TransactStatements"> & { @@ -34,16 +33,26 @@ export type ExecuteTransactionCommandOutput = Omit<__ExecuteTransactionCommandOu * JavaScript objects passed in as parameters are marshalled into `AttributeValue` shapes * required by Amazon DynamoDB. Responses from DynamoDB are unmarshalled into plain JavaScript objects. */ -export class ExecuteTransactionCommand extends $Command< +export class ExecuteTransactionCommand extends DynamoDBDocumentClientCommand< ExecuteTransactionCommandInput, ExecuteTransactionCommandOutput, + __ExecuteTransactionCommandInput, + __ExecuteTransactionCommandOutput, DynamoDBDocumentClientResolvedConfig > { - private readonly inputKeyNodes = [{ key: "TransactStatements", children: [{ key: "Parameters" }] }]; - private readonly outputKeyNodes = [{ key: "Responses", children: [{ key: "Item" }] }]; + protected readonly inputKeyNodes = [{ key: "TransactStatements", children: [{ key: "Parameters" }] }]; + protected readonly outputKeyNodes = [{ key: "Responses", children: [{ key: "Item" }] }]; + + protected readonly clientCommand: __ExecuteTransactionCommand; + public readonly middlewareStack: MiddlewareStack< + ExecuteTransactionCommandInput | __ExecuteTransactionCommandInput, + ExecuteTransactionCommandOutput | __ExecuteTransactionCommandOutput + >; constructor(readonly input: ExecuteTransactionCommandInput) { super(); + this.clientCommand = new __ExecuteTransactionCommand(this.input as any); + this.middlewareStack = this.clientCommand.middlewareStack; } /** @@ -54,16 +63,10 @@ export class ExecuteTransactionCommand extends $Command< configuration: DynamoDBDocumentClientResolvedConfig, options?: __HttpHandlerOptions ): Handler { - const { marshallOptions, unmarshallOptions } = configuration.translateConfig || {}; - const command = new __ExecuteTransactionCommand(marshallInput(this.input, this.inputKeyNodes, marshallOptions)); - const handler = command.resolveMiddleware(clientStack, configuration, options); + this.addMarshallingMiddleware(configuration); + const stack = clientStack.concat(this.middlewareStack as typeof clientStack); + const handler = this.clientCommand.resolveMiddleware(stack, configuration, options); - return async () => { - const data = await handler(command); - return { - ...data, - output: unmarshallOutput(data.output, this.outputKeyNodes, unmarshallOptions), - }; - }; + return async () => handler(this.clientCommand); } } diff --git a/lib/lib-dynamodb/src/commands/GetCommand.ts b/lib/lib-dynamodb/src/commands/GetCommand.ts index b1594d11f02b..c6f046f7f7c5 100644 --- a/lib/lib-dynamodb/src/commands/GetCommand.ts +++ b/lib/lib-dynamodb/src/commands/GetCommand.ts @@ -4,11 +4,10 @@ import { GetItemCommandInput as __GetItemCommandInput, GetItemCommandOutput as __GetItemCommandOutput, } from "@aws-sdk/client-dynamodb"; -import { Command as $Command } from "@aws-sdk/smithy-client"; import { Handler, HttpHandlerOptions as __HttpHandlerOptions, MiddlewareStack } from "@aws-sdk/types"; import { NativeAttributeValue } from "@aws-sdk/util-dynamodb"; -import { marshallInput, unmarshallOutput } from "../commands/utils"; +import { DynamoDBDocumentClientCommand } from "../baseCommand/DynamoDBDocumentClientCommand"; import { DynamoDBDocumentClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../DynamoDBDocumentClient"; export type GetCommandInput = Omit<__GetItemCommandInput, "Key"> & { @@ -26,12 +25,26 @@ export type GetCommandOutput = Omit<__GetItemCommandOutput, "Item"> & { * JavaScript objects passed in as parameters are marshalled into `AttributeValue` shapes * required by Amazon DynamoDB. Responses from DynamoDB are unmarshalled into plain JavaScript objects. */ -export class GetCommand extends $Command { - private readonly inputKeyNodes = [{ key: "Key" }]; - private readonly outputKeyNodes = [{ key: "Item" }]; +export class GetCommand extends DynamoDBDocumentClientCommand< + GetCommandInput, + GetCommandOutput, + __GetItemCommandInput, + __GetItemCommandOutput, + DynamoDBDocumentClientResolvedConfig +> { + protected readonly inputKeyNodes = [{ key: "Key" }]; + protected readonly outputKeyNodes = [{ key: "Item" }]; + + protected readonly clientCommand: __GetItemCommand; + public readonly middlewareStack: MiddlewareStack< + GetCommandInput | __GetItemCommandInput, + GetCommandOutput | __GetItemCommandOutput + >; constructor(readonly input: GetCommandInput) { super(); + this.clientCommand = new __GetItemCommand(this.input as any); + this.middlewareStack = this.clientCommand.middlewareStack; } /** @@ -42,16 +55,10 @@ export class GetCommand extends $Command { - const { marshallOptions, unmarshallOptions } = configuration.translateConfig || {}; - const command = new __GetItemCommand(marshallInput(this.input, this.inputKeyNodes, marshallOptions)); - const handler = command.resolveMiddleware(clientStack, configuration, options); - - return async () => { - const data = await handler(command); - return { - ...data, - output: unmarshallOutput(data.output, this.outputKeyNodes, unmarshallOptions), - }; - }; + this.addMarshallingMiddleware(configuration); + const stack = clientStack.concat(this.middlewareStack as typeof clientStack); + const handler = this.clientCommand.resolveMiddleware(stack, configuration, options); + + return async () => handler(this.clientCommand); } } diff --git a/lib/lib-dynamodb/src/commands/PutCommand.ts b/lib/lib-dynamodb/src/commands/PutCommand.ts index f76e7436f850..c08e5d376c79 100644 --- a/lib/lib-dynamodb/src/commands/PutCommand.ts +++ b/lib/lib-dynamodb/src/commands/PutCommand.ts @@ -6,11 +6,10 @@ import { PutItemCommandInput as __PutItemCommandInput, PutItemCommandOutput as __PutItemCommandOutput, } from "@aws-sdk/client-dynamodb"; -import { Command as $Command } from "@aws-sdk/smithy-client"; import { Handler, HttpHandlerOptions as __HttpHandlerOptions, MiddlewareStack } from "@aws-sdk/types"; import { NativeAttributeValue } from "@aws-sdk/util-dynamodb"; -import { marshallInput, unmarshallOutput } from "../commands/utils"; +import { DynamoDBDocumentClientCommand } from "../baseCommand/DynamoDBDocumentClientCommand"; import { DynamoDBDocumentClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../DynamoDBDocumentClient"; export type PutCommandInput = Omit<__PutItemCommandInput, "Item" | "Expected" | "ExpressionAttributeValues"> & { @@ -39,8 +38,14 @@ export type PutCommandOutput = Omit<__PutItemCommandOutput, "Attributes" | "Item * JavaScript objects passed in as parameters are marshalled into `AttributeValue` shapes * required by Amazon DynamoDB. Responses from DynamoDB are unmarshalled into plain JavaScript objects. */ -export class PutCommand extends $Command { - private readonly inputKeyNodes = [ +export class PutCommand extends DynamoDBDocumentClientCommand< + PutCommandInput, + PutCommandOutput, + __PutItemCommandInput, + __PutItemCommandOutput, + DynamoDBDocumentClientResolvedConfig +> { + protected readonly inputKeyNodes = [ { key: "Item" }, { key: "Expected", @@ -50,13 +55,21 @@ export class PutCommand extends $Command; + constructor(readonly input: PutCommandInput) { super(); + this.clientCommand = new __PutItemCommand(this.input as any); + this.middlewareStack = this.clientCommand.middlewareStack; } /** @@ -67,16 +80,10 @@ export class PutCommand extends $Command { - const { marshallOptions, unmarshallOptions } = configuration.translateConfig || {}; - const command = new __PutItemCommand(marshallInput(this.input, this.inputKeyNodes, marshallOptions)); - const handler = command.resolveMiddleware(clientStack, configuration, options); + this.addMarshallingMiddleware(configuration); + const stack = clientStack.concat(this.middlewareStack as typeof clientStack); + const handler = this.clientCommand.resolveMiddleware(stack, configuration, options); - return async () => { - const data = await handler(command); - return { - ...data, - output: unmarshallOutput(data.output, this.outputKeyNodes, unmarshallOptions), - }; - }; + return async () => handler(this.clientCommand); } } diff --git a/lib/lib-dynamodb/src/commands/QueryCommand.ts b/lib/lib-dynamodb/src/commands/QueryCommand.ts index 2e5fb97ff788..f5e6c1941822 100644 --- a/lib/lib-dynamodb/src/commands/QueryCommand.ts +++ b/lib/lib-dynamodb/src/commands/QueryCommand.ts @@ -5,11 +5,10 @@ import { QueryCommandInput as __QueryCommandInput, QueryCommandOutput as __QueryCommandOutput, } from "@aws-sdk/client-dynamodb"; -import { Command as $Command } from "@aws-sdk/smithy-client"; import { Handler, HttpHandlerOptions as __HttpHandlerOptions, MiddlewareStack } from "@aws-sdk/types"; import { NativeAttributeValue } from "@aws-sdk/util-dynamodb"; -import { marshallInput, unmarshallOutput } from "../commands/utils"; +import { DynamoDBDocumentClientCommand } from "../baseCommand/DynamoDBDocumentClientCommand"; import { DynamoDBDocumentClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../DynamoDBDocumentClient"; export type QueryCommandInput = Omit< @@ -44,12 +43,14 @@ export type QueryCommandOutput = Omit<__QueryCommandOutput, "Items" | "LastEvalu * JavaScript objects passed in as parameters are marshalled into `AttributeValue` shapes * required by Amazon DynamoDB. Responses from DynamoDB are unmarshalled into plain JavaScript objects. */ -export class QueryCommand extends $Command< +export class QueryCommand extends DynamoDBDocumentClientCommand< QueryCommandInput, QueryCommandOutput, + __QueryCommandInput, + __QueryCommandOutput, DynamoDBDocumentClientResolvedConfig > { - private readonly inputKeyNodes = [ + protected readonly inputKeyNodes = [ { key: "KeyConditions", children: { @@ -65,10 +66,18 @@ export class QueryCommand extends $Command< { key: "ExclusiveStartKey" }, { key: "ExpressionAttributeValues" }, ]; - private readonly outputKeyNodes = [{ key: "Items" }, { key: "LastEvaluatedKey" }]; + protected readonly outputKeyNodes = [{ key: "Items" }, { key: "LastEvaluatedKey" }]; + + protected readonly clientCommand: __QueryCommand; + public readonly middlewareStack: MiddlewareStack< + QueryCommandInput | __QueryCommandInput, + QueryCommandOutput | __QueryCommandOutput + >; constructor(readonly input: QueryCommandInput) { super(); + this.clientCommand = new __QueryCommand(this.input as any); + this.middlewareStack = this.clientCommand.middlewareStack; } /** @@ -79,16 +88,10 @@ export class QueryCommand extends $Command< configuration: DynamoDBDocumentClientResolvedConfig, options?: __HttpHandlerOptions ): Handler { - const { marshallOptions, unmarshallOptions } = configuration.translateConfig || {}; - const command = new __QueryCommand(marshallInput(this.input, this.inputKeyNodes, marshallOptions)); - const handler = command.resolveMiddleware(clientStack, configuration, options); + this.addMarshallingMiddleware(configuration); + const stack = clientStack.concat(this.middlewareStack as typeof clientStack); + const handler = this.clientCommand.resolveMiddleware(stack, configuration, options); - return async () => { - const data = await handler(command); - return { - ...data, - output: unmarshallOutput(data.output, this.outputKeyNodes, unmarshallOptions), - }; - }; + return async () => handler(this.clientCommand); } } diff --git a/lib/lib-dynamodb/src/commands/ScanCommand.ts b/lib/lib-dynamodb/src/commands/ScanCommand.ts index 4c536ee3394c..9276722bf41a 100644 --- a/lib/lib-dynamodb/src/commands/ScanCommand.ts +++ b/lib/lib-dynamodb/src/commands/ScanCommand.ts @@ -5,11 +5,10 @@ import { ScanCommandInput as __ScanCommandInput, ScanCommandOutput as __ScanCommandOutput, } from "@aws-sdk/client-dynamodb"; -import { Command as $Command } from "@aws-sdk/smithy-client"; import { Handler, HttpHandlerOptions as __HttpHandlerOptions, MiddlewareStack } from "@aws-sdk/types"; import { NativeAttributeValue } from "@aws-sdk/util-dynamodb"; -import { marshallInput, unmarshallOutput } from "../commands/utils"; +import { DynamoDBDocumentClientCommand } from "../baseCommand/DynamoDBDocumentClientCommand"; import { DynamoDBDocumentClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../DynamoDBDocumentClient"; export type ScanCommandInput = Omit< @@ -38,8 +37,14 @@ export type ScanCommandOutput = Omit<__ScanCommandOutput, "Items" | "LastEvaluat * JavaScript objects passed in as parameters are marshalled into `AttributeValue` shapes * required by Amazon DynamoDB. Responses from DynamoDB are unmarshalled into plain JavaScript objects. */ -export class ScanCommand extends $Command { - private readonly inputKeyNodes = [ +export class ScanCommand extends DynamoDBDocumentClientCommand< + ScanCommandInput, + ScanCommandOutput, + __ScanCommandInput, + __ScanCommandOutput, + DynamoDBDocumentClientResolvedConfig +> { + protected readonly inputKeyNodes = [ { key: "ScanFilter", children: { @@ -49,10 +54,18 @@ export class ScanCommand extends $Command; constructor(readonly input: ScanCommandInput) { super(); + this.clientCommand = new __ScanCommand(this.input as any); + this.middlewareStack = this.clientCommand.middlewareStack; } /** @@ -63,16 +76,10 @@ export class ScanCommand extends $Command { - const { marshallOptions, unmarshallOptions } = configuration.translateConfig || {}; - const command = new __ScanCommand(marshallInput(this.input, this.inputKeyNodes, marshallOptions)); - const handler = command.resolveMiddleware(clientStack, configuration, options); + this.addMarshallingMiddleware(configuration); + const stack = clientStack.concat(this.middlewareStack as typeof clientStack); + const handler = this.clientCommand.resolveMiddleware(stack, configuration, options); - return async () => { - const data = await handler(command); - return { - ...data, - output: unmarshallOutput(data.output, this.outputKeyNodes, unmarshallOptions), - }; - }; + return async () => handler(this.clientCommand); } } diff --git a/lib/lib-dynamodb/src/commands/TransactGetCommand.ts b/lib/lib-dynamodb/src/commands/TransactGetCommand.ts index e59684c50a7d..f64175369e3b 100644 --- a/lib/lib-dynamodb/src/commands/TransactGetCommand.ts +++ b/lib/lib-dynamodb/src/commands/TransactGetCommand.ts @@ -7,11 +7,10 @@ import { TransactGetItemsCommandInput as __TransactGetItemsCommandInput, TransactGetItemsCommandOutput as __TransactGetItemsCommandOutput, } from "@aws-sdk/client-dynamodb"; -import { Command as $Command } from "@aws-sdk/smithy-client"; import { Handler, HttpHandlerOptions as __HttpHandlerOptions, MiddlewareStack } from "@aws-sdk/types"; import { NativeAttributeValue } from "@aws-sdk/util-dynamodb"; -import { marshallInput, unmarshallOutput } from "../commands/utils"; +import { DynamoDBDocumentClientCommand } from "../baseCommand/DynamoDBDocumentClientCommand"; import { DynamoDBDocumentClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../DynamoDBDocumentClient"; export type TransactGetCommandInput = Omit<__TransactGetItemsCommandInput, "TransactItems"> & { @@ -39,16 +38,26 @@ export type TransactGetCommandOutput = Omit<__TransactGetItemsCommandOutput, "Re * JavaScript objects passed in as parameters are marshalled into `AttributeValue` shapes * required by Amazon DynamoDB. Responses from DynamoDB are unmarshalled into plain JavaScript objects. */ -export class TransactGetCommand extends $Command< +export class TransactGetCommand extends DynamoDBDocumentClientCommand< TransactGetCommandInput, TransactGetCommandOutput, + __TransactGetItemsCommandInput, + __TransactGetItemsCommandOutput, DynamoDBDocumentClientResolvedConfig > { - private readonly inputKeyNodes = [{ key: "TransactItems", children: [{ key: "Get", children: [{ key: "Key" }] }] }]; - private readonly outputKeyNodes = [{ key: "Responses", children: [{ key: "Item" }] }]; + protected readonly inputKeyNodes = [{ key: "TransactItems", children: [{ key: "Get", children: [{ key: "Key" }] }] }]; + protected readonly outputKeyNodes = [{ key: "Responses", children: [{ key: "Item" }] }]; + + protected readonly clientCommand: __TransactGetItemsCommand; + public readonly middlewareStack: MiddlewareStack< + TransactGetCommandInput | __TransactGetItemsCommandInput, + TransactGetCommandOutput | __TransactGetItemsCommandOutput + >; constructor(readonly input: TransactGetCommandInput) { super(); + this.clientCommand = new __TransactGetItemsCommand(this.input as any); + this.middlewareStack = this.clientCommand.middlewareStack; } /** @@ -59,16 +68,10 @@ export class TransactGetCommand extends $Command< configuration: DynamoDBDocumentClientResolvedConfig, options?: __HttpHandlerOptions ): Handler { - const { marshallOptions, unmarshallOptions } = configuration.translateConfig || {}; - const command = new __TransactGetItemsCommand(marshallInput(this.input, this.inputKeyNodes, marshallOptions)); - const handler = command.resolveMiddleware(clientStack, configuration, options); + this.addMarshallingMiddleware(configuration); + const stack = clientStack.concat(this.middlewareStack as typeof clientStack); + const handler = this.clientCommand.resolveMiddleware(stack, configuration, options); - return async () => { - const data = await handler(command); - return { - ...data, - output: unmarshallOutput(data.output, this.outputKeyNodes, unmarshallOptions), - }; - }; + return async () => handler(this.clientCommand); } } diff --git a/lib/lib-dynamodb/src/commands/TransactWriteCommand.ts b/lib/lib-dynamodb/src/commands/TransactWriteCommand.ts index 051cc9f4ae3e..7f5c05f9e2d1 100644 --- a/lib/lib-dynamodb/src/commands/TransactWriteCommand.ts +++ b/lib/lib-dynamodb/src/commands/TransactWriteCommand.ts @@ -10,11 +10,10 @@ import { TransactWriteItemsCommandOutput as __TransactWriteItemsCommandOutput, Update, } from "@aws-sdk/client-dynamodb"; -import { Command as $Command } from "@aws-sdk/smithy-client"; import { Handler, HttpHandlerOptions as __HttpHandlerOptions, MiddlewareStack } from "@aws-sdk/types"; import { NativeAttributeValue } from "@aws-sdk/util-dynamodb"; -import { marshallInput, unmarshallOutput } from "../commands/utils"; +import { DynamoDBDocumentClientCommand } from "../baseCommand/DynamoDBDocumentClientCommand"; import { DynamoDBDocumentClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../DynamoDBDocumentClient"; export type TransactWriteCommandInput = Omit<__TransactWriteItemsCommandInput, "TransactItems"> & { @@ -56,12 +55,14 @@ export type TransactWriteCommandOutput = Omit<__TransactWriteItemsCommandOutput, * JavaScript objects passed in as parameters are marshalled into `AttributeValue` shapes * required by Amazon DynamoDB. Responses from DynamoDB are unmarshalled into plain JavaScript objects. */ -export class TransactWriteCommand extends $Command< +export class TransactWriteCommand extends DynamoDBDocumentClientCommand< TransactWriteCommandInput, TransactWriteCommandOutput, + __TransactWriteItemsCommandInput, + __TransactWriteItemsCommandOutput, DynamoDBDocumentClientResolvedConfig > { - private readonly inputKeyNodes = [ + protected readonly inputKeyNodes = [ { key: "TransactItems", children: [ @@ -72,7 +73,7 @@ export class TransactWriteCommand extends $Command< ], }, ]; - private readonly outputKeyNodes = [ + protected readonly outputKeyNodes = [ { key: "ItemCollectionMetrics", children: { @@ -81,8 +82,16 @@ export class TransactWriteCommand extends $Command< }, ]; + protected readonly clientCommand: __TransactWriteItemsCommand; + public readonly middlewareStack: MiddlewareStack< + TransactWriteCommandInput | __TransactWriteItemsCommandInput, + TransactWriteCommandOutput | __TransactWriteItemsCommandOutput + >; + constructor(readonly input: TransactWriteCommandInput) { super(); + this.clientCommand = new __TransactWriteItemsCommand(this.input as any); + this.middlewareStack = this.clientCommand.middlewareStack; } /** @@ -93,16 +102,10 @@ export class TransactWriteCommand extends $Command< configuration: DynamoDBDocumentClientResolvedConfig, options?: __HttpHandlerOptions ): Handler { - const { marshallOptions, unmarshallOptions } = configuration.translateConfig || {}; - const command = new __TransactWriteItemsCommand(marshallInput(this.input, this.inputKeyNodes, marshallOptions)); - const handler = command.resolveMiddleware(clientStack, configuration, options); + this.addMarshallingMiddleware(configuration); + const stack = clientStack.concat(this.middlewareStack as typeof clientStack); + const handler = this.clientCommand.resolveMiddleware(stack, configuration, options); - return async () => { - const data = await handler(command); - return { - ...data, - output: unmarshallOutput(data.output, this.outputKeyNodes, unmarshallOptions), - }; - }; + return async () => handler(this.clientCommand); } } diff --git a/lib/lib-dynamodb/src/commands/UpdateCommand.ts b/lib/lib-dynamodb/src/commands/UpdateCommand.ts index 51cb8a5142c7..ef42d3a6c471 100644 --- a/lib/lib-dynamodb/src/commands/UpdateCommand.ts +++ b/lib/lib-dynamodb/src/commands/UpdateCommand.ts @@ -7,11 +7,10 @@ import { UpdateItemCommandInput as __UpdateItemCommandInput, UpdateItemCommandOutput as __UpdateItemCommandOutput, } from "@aws-sdk/client-dynamodb"; -import { Command as $Command } from "@aws-sdk/smithy-client"; import { Handler, HttpHandlerOptions as __HttpHandlerOptions, MiddlewareStack } from "@aws-sdk/types"; import { NativeAttributeValue } from "@aws-sdk/util-dynamodb"; -import { marshallInput, unmarshallOutput } from "../commands/utils"; +import { DynamoDBDocumentClientCommand } from "../baseCommand/DynamoDBDocumentClientCommand"; import { DynamoDBDocumentClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../DynamoDBDocumentClient"; export type UpdateCommandInput = Omit< @@ -49,12 +48,14 @@ export type UpdateCommandOutput = Omit<__UpdateItemCommandOutput, "Attributes" | * JavaScript objects passed in as parameters are marshalled into `AttributeValue` shapes * required by Amazon DynamoDB. Responses from DynamoDB are unmarshalled into plain JavaScript objects. */ -export class UpdateCommand extends $Command< +export class UpdateCommand extends DynamoDBDocumentClientCommand< UpdateCommandInput, UpdateCommandOutput, + __UpdateItemCommandInput, + __UpdateItemCommandOutput, DynamoDBDocumentClientResolvedConfig > { - private readonly inputKeyNodes = [ + protected readonly inputKeyNodes = [ { key: "Key" }, { key: "AttributeUpdates", @@ -70,13 +71,21 @@ export class UpdateCommand extends $Command< }, { key: "ExpressionAttributeValues" }, ]; - private readonly outputKeyNodes = [ + protected readonly outputKeyNodes = [ { key: "Attributes" }, { key: "ItemCollectionMetrics", children: [{ key: "ItemCollectionKey" }] }, ]; + protected readonly clientCommand: __UpdateItemCommand; + public readonly middlewareStack: MiddlewareStack< + UpdateCommandInput | __UpdateItemCommandInput, + UpdateCommandOutput | __UpdateItemCommandOutput + >; + constructor(readonly input: UpdateCommandInput) { super(); + this.clientCommand = new __UpdateItemCommand(this.input as any); + this.middlewareStack = this.clientCommand.middlewareStack; } /** @@ -87,16 +96,10 @@ export class UpdateCommand extends $Command< configuration: DynamoDBDocumentClientResolvedConfig, options?: __HttpHandlerOptions ): Handler { - const { marshallOptions, unmarshallOptions } = configuration.translateConfig || {}; - const command = new __UpdateItemCommand(marshallInput(this.input, this.inputKeyNodes, marshallOptions)); - const handler = command.resolveMiddleware(clientStack, configuration, options); + this.addMarshallingMiddleware(configuration); + const stack = clientStack.concat(this.middlewareStack as typeof clientStack); + const handler = this.clientCommand.resolveMiddleware(stack, configuration, options); - return async () => { - const data = await handler(command); - return { - ...data, - output: unmarshallOutput(data.output, this.outputKeyNodes, unmarshallOptions), - }; - }; + return async () => handler(this.clientCommand); } } diff --git a/packages/util-dynamodb/src/marshall.ts b/packages/util-dynamodb/src/marshall.ts index e1c8622869c4..8139f583a07f 100644 --- a/packages/util-dynamodb/src/marshall.ts +++ b/packages/util-dynamodb/src/marshall.ts @@ -45,6 +45,7 @@ export function marshall(data: unknown, options?: marshallOptions): AttributeVal export function marshall(data: unknown, options?: marshallOptions) { const attributeValue: AttributeValue = convertToAttr(data, options); const [key, value] = Object.entries(attributeValue)[0]; + switch (key) { case "M": case "L":