From fa0b8a5b6da1ee9aefb12e34b13a37dfb82b241e Mon Sep 17 00:00:00 2001 From: Sergi Pasoevi Date: Thu, 1 Aug 2024 15:28:23 +0100 Subject: [PATCH 1/2] chore(codegen): use pagination factory in ddb document client --- .../DocumentClientPaginationGenerator.java | 93 +++---------------- 1 file changed, 14 insertions(+), 79 deletions(-) diff --git a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/DocumentClientPaginationGenerator.java b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/DocumentClientPaginationGenerator.java index 83be25f02076..295a4f32bb6e 100644 --- a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/DocumentClientPaginationGenerator.java +++ b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/DocumentClientPaginationGenerator.java @@ -17,13 +17,9 @@ import java.nio.file.Path; import java.nio.file.Paths; -import java.util.Optional; -import software.amazon.smithy.codegen.core.CodegenException; import software.amazon.smithy.codegen.core.Symbol; import software.amazon.smithy.codegen.core.SymbolProvider; import software.amazon.smithy.model.Model; -import software.amazon.smithy.model.knowledge.PaginatedIndex; -import software.amazon.smithy.model.knowledge.PaginationInfo; import software.amazon.smithy.model.shapes.OperationShape; import software.amazon.smithy.model.shapes.ServiceShape; import software.amazon.smithy.typescript.codegen.TypeScriptDependency; @@ -36,14 +32,13 @@ final class DocumentClientPaginationGenerator implements Runnable { static final String PAGINATION_FOLDER = "pagination"; private final TypeScriptWriter writer; - private final PaginationInfo paginatedInfo; private final String operationTypeName; private final String inputTypeName; private final String outputTypeName; private final String operationName; - private final String methodName; + private final String paginationType; DocumentClientPaginationGenerator( @@ -65,14 +60,7 @@ final class DocumentClientPaginationGenerator implements Runnable { // e.g. listObjects this.operationName = operationTypeName.replace("Command", ""); - this.methodName = Character.toLowerCase(operationName.charAt(0)) + operationName.substring(1); this.paginationType = DocumentClientUtils.CLIENT_FULL_NAME + "PaginationConfiguration"; - - PaginatedIndex paginatedIndex = PaginatedIndex.of(model); - Optional paginationInfo = paginatedIndex.getPaginationInfo(service, operation); - this.paginatedInfo = paginationInfo.orElseThrow(() -> { - return new CodegenException("Expected Paginator to have pagination information."); - }); } @Override @@ -90,13 +78,13 @@ public void run() { // Import Pagination types writer.addImport("Paginator", "Paginator", TypeScriptDependency.SMITHY_TYPES); + writer.addImport("createPaginator", "createPaginator", TypeScriptDependency.SMITHY_CORE); writer.addRelativeImport(paginationType, paginationType, Paths.get(".", getInterfaceFilelocation().replace(".ts", ""))); writer.writeDocs("@public"); writer.write("export { Paginator }"); - writeCommandRequest(); writePager(); } @@ -134,71 +122,18 @@ static void generateServicePaginationInterfaces(TypeScriptWriter writer) { }); } - private String destructurePath(String path) { - return "." + path.replace(".", "!."); - } - private void writePager() { - String inputTokenName = paginatedInfo.getPaginatedTrait().getInputToken().get(); - String outputTokenName = paginatedInfo.getPaginatedTrait().getOutputToken().get(); - - writer.writeDocs("@public\n\n" - + String.format("@param %s - {@link %s}%n", inputTypeName, inputTypeName) - + String.format("@returns {@link %s}%n", outputTypeName) - ); - writer.openBlock( - "export async function* paginate$L(config: $L, input: $L, ...additionalArguments: any): Paginator<$L>{", - "}", operationName, paginationType, inputTypeName, outputTypeName, () -> { - String destructuredInputTokenName = destructurePath(inputTokenName); - writer.write("// ToDo: replace with actual type instead of typeof input$L", destructuredInputTokenName); - writer.write("let token: typeof input$L | undefined = config.startingToken || undefined;", - destructuredInputTokenName); - - writer.write("let hasNext = true;"); - writer.write("let page: $L;", outputTypeName); - writer.openBlock("while (hasNext) {", "}", () -> { - writer.write("input$L = token;", destructuredInputTokenName); - - if (paginatedInfo.getPageSizeMember().isPresent()) { - String pageSize = paginatedInfo.getPageSizeMember().get().getMemberName(); - writer.write("input[$S] = config.pageSize;", pageSize); - } - - writer.openBlock("if (config.client instanceof $L) {", "}", DocumentClientUtils.CLIENT_NAME, - () -> { - writer.write( - "page = await makePagedClientRequest(config.client, input, ...additionalArguments);"); - } - ); - writer.openBlock("else {", "}", () -> { - writer.write("throw new Error(\"Invalid client, expected $L | $L\");", - DocumentClientUtils.CLIENT_FULL_NAME, DocumentClientUtils.CLIENT_NAME); - }); - - writer.write("yield page;"); - writer.write("token = page$L;", destructurePath(outputTokenName)); - - writer.write("hasNext = !!(token);"); - }); - - writer.write("// @ts-ignore"); - writer.write("return undefined;"); - }); - } - - - /** - * Paginated command that calls CommandClient().send({...}) under the hood. This is meant for client side (browser) - * environments and does not generally expose the entire service. - */ - private void writeCommandRequest() { - writer.writeDocs("@internal"); - writer.openBlock( - "const makePagedClientRequest = async (client: $L, input: $L, ...args: any): Promise<$L> => {", - "}", DocumentClientUtils.CLIENT_NAME, inputTypeName, - outputTypeName, () -> { - writer.write("// @ts-ignore"); - writer.write("return await client.send(new $L(input), ...args);", operationTypeName); - }); + writer.writeDocs("@public"); + writer.write(""" +export const paginate$1L: ( + config: $2L, + input: $3L, + ...additionalArguments: any +) => Paginator<$4L> = createPaginator< + $2L, + $3L, + $4L +>(DynamoDBDocumentClient, $1LCommand, "ExclusiveStartKey", "LastEvaluatedKey", "Limit"); + """, operationName, paginationType, inputTypeName, outputTypeName); } } From d036757dd5caaba09d9c53806befe48b4b48b93a Mon Sep 17 00:00:00 2001 From: Sergi Pasoevi Date: Thu, 1 Aug 2024 15:33:27 +0100 Subject: [PATCH 2/2] chore(lib-dynamodb): codegen sync --- .../src/pagination/QueryPaginator.ts | 43 +++---------------- .../src/pagination/ScanPaginator.ts | 43 +++---------------- 2 files changed, 14 insertions(+), 72 deletions(-) diff --git a/lib/lib-dynamodb/src/pagination/QueryPaginator.ts b/lib/lib-dynamodb/src/pagination/QueryPaginator.ts index 699a84949a0a..5367e3f270fa 100644 --- a/lib/lib-dynamodb/src/pagination/QueryPaginator.ts +++ b/lib/lib-dynamodb/src/pagination/QueryPaginator.ts @@ -1,4 +1,5 @@ // smithy-typescript generated code +import { createPaginator } from "@smithy/core"; import { Paginator } from "@smithy/types"; import { QueryCommand, QueryCommandInput, QueryCommandOutput } from "../commands/QueryCommand"; @@ -9,45 +10,15 @@ import { DynamoDBDocumentPaginationConfiguration } from "./Interfaces"; * @public */ export { Paginator }; -/** - * @internal - */ -const makePagedClientRequest = async ( - client: DynamoDBDocumentClient, - input: QueryCommandInput, - ...args: any -): Promise => { - // @ts-ignore - return await client.send(new QueryCommand(input), ...args); -}; /** * @public - * - * @param QueryCommandInput - {@link QueryCommandInput} - * @returns {@link QueryCommandOutput} - * */ -export async function* paginateQuery( +export const paginateQuery: ( config: DynamoDBDocumentPaginationConfiguration, input: QueryCommandInput, ...additionalArguments: any -): Paginator { - // ToDo: replace with actual type instead of typeof input.ExclusiveStartKey - let token: typeof input.ExclusiveStartKey | undefined = config.startingToken || undefined; - let hasNext = true; - let page: QueryCommandOutput; - while (hasNext) { - input.ExclusiveStartKey = token; - input["Limit"] = config.pageSize; - if (config.client instanceof DynamoDBDocumentClient) { - page = await makePagedClientRequest(config.client, input, ...additionalArguments); - } else { - throw new Error("Invalid client, expected DynamoDBDocument | DynamoDBDocumentClient"); - } - yield page; - token = page.LastEvaluatedKey; - hasNext = !!token; - } - // @ts-ignore - return undefined; -} +) => Paginator = createPaginator< + DynamoDBDocumentPaginationConfiguration, + QueryCommandInput, + QueryCommandOutput +>(DynamoDBDocumentClient, QueryCommand, "ExclusiveStartKey", "LastEvaluatedKey", "Limit"); diff --git a/lib/lib-dynamodb/src/pagination/ScanPaginator.ts b/lib/lib-dynamodb/src/pagination/ScanPaginator.ts index fe67bc0f0cb5..237e3ac6d357 100644 --- a/lib/lib-dynamodb/src/pagination/ScanPaginator.ts +++ b/lib/lib-dynamodb/src/pagination/ScanPaginator.ts @@ -1,4 +1,5 @@ // smithy-typescript generated code +import { createPaginator } from "@smithy/core"; import { Paginator } from "@smithy/types"; import { ScanCommand, ScanCommandInput, ScanCommandOutput } from "../commands/ScanCommand"; @@ -9,45 +10,15 @@ import { DynamoDBDocumentPaginationConfiguration } from "./Interfaces"; * @public */ export { Paginator }; -/** - * @internal - */ -const makePagedClientRequest = async ( - client: DynamoDBDocumentClient, - input: ScanCommandInput, - ...args: any -): Promise => { - // @ts-ignore - return await client.send(new ScanCommand(input), ...args); -}; /** * @public - * - * @param ScanCommandInput - {@link ScanCommandInput} - * @returns {@link ScanCommandOutput} - * */ -export async function* paginateScan( +export const paginateScan: ( config: DynamoDBDocumentPaginationConfiguration, input: ScanCommandInput, ...additionalArguments: any -): Paginator { - // ToDo: replace with actual type instead of typeof input.ExclusiveStartKey - let token: typeof input.ExclusiveStartKey | undefined = config.startingToken || undefined; - let hasNext = true; - let page: ScanCommandOutput; - while (hasNext) { - input.ExclusiveStartKey = token; - input["Limit"] = config.pageSize; - if (config.client instanceof DynamoDBDocumentClient) { - page = await makePagedClientRequest(config.client, input, ...additionalArguments); - } else { - throw new Error("Invalid client, expected DynamoDBDocument | DynamoDBDocumentClient"); - } - yield page; - token = page.LastEvaluatedKey; - hasNext = !!token; - } - // @ts-ignore - return undefined; -} +) => Paginator = createPaginator< + DynamoDBDocumentPaginationConfiguration, + ScanCommandInput, + ScanCommandOutput +>(DynamoDBDocumentClient, ScanCommand, "ExclusiveStartKey", "LastEvaluatedKey", "Limit");