Skip to content

Commit f0ff3b7

Browse files
authored
feat: paginator factory applied to codegen (#1114)
* feat: paginator factory * feat: paginator use pushState * feat: paginator, clean up syntax * feat: paginator, add dependency
1 parent 9485a73 commit f0ff3b7

File tree

1 file changed

+41
-63
lines changed

1 file changed

+41
-63
lines changed

smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/PaginationGenerator.java

Lines changed: 41 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import software.amazon.smithy.model.knowledge.PaginatedIndex;
2929
import software.amazon.smithy.model.knowledge.PaginationInfo;
3030
import software.amazon.smithy.model.knowledge.TopDownIndex;
31+
import software.amazon.smithy.model.shapes.MemberShape;
3132
import software.amazon.smithy.model.shapes.OperationShape;
3233
import software.amazon.smithy.model.shapes.ServiceShape;
3334
import software.amazon.smithy.model.traits.PaginatedTrait;
@@ -41,6 +42,7 @@ final class PaginationGenerator implements Runnable {
4142
Paths.get(CodegenUtils.SOURCE_FOLDER, PAGINATION_FOLDER, "Interfaces.ts").toString();
4243

4344
private final TypeScriptWriter writer;
45+
private final String aggregatedClientName;
4446
private final PaginationInfo paginatedInfo;
4547

4648
private final Symbol serviceSymbol;
@@ -49,8 +51,6 @@ final class PaginationGenerator implements Runnable {
4951
private final Symbol outputSymbol;
5052

5153
private final String operationName;
52-
private final String methodName;
53-
private final String aggregatedClientName;
5454
private final String paginationType;
5555

5656
PaginationGenerator(
@@ -63,18 +63,16 @@ final class PaginationGenerator implements Runnable {
6363
) {
6464

6565
this.writer = writer;
66+
this.aggregatedClientName = aggregatedClientName;
6667

6768
this.serviceSymbol = symbolProvider.toSymbol(service);
6869
this.operationSymbol = symbolProvider.toSymbol(operation);
6970
this.inputSymbol = symbolProvider.toSymbol(operation).expectProperty("inputType", Symbol.class);
7071
this.outputSymbol = symbolProvider.toSymbol(operation).expectProperty("outputType", Symbol.class);
7172

7273
this.operationName = operation.getId().getName();
73-
this.aggregatedClientName = aggregatedClientName;
7474

75-
// e.g. listObjects
76-
this.methodName = Character.toLowerCase(operationName.charAt(0)) + operationName.substring(1);
77-
this.paginationType = this.aggregatedClientName + "PaginationConfiguration";
75+
this.paginationType = aggregatedClientName + "PaginationConfiguration";
7876

7977
PaginatedIndex paginatedIndex = PaginatedIndex.of(model);
8078
Optional<PaginationInfo> paginationInfo = paginatedIndex.getPaginationInfo(service, operation);
@@ -103,7 +101,6 @@ public void run() {
103101
writer.addRelativeImport(paginationType, paginationType,
104102
Paths.get(".", PAGINATION_INTERFACE_FILE.replace(".ts", "")));
105103

106-
writeCommandRequest();
107104
writePager();
108105
}
109106

@@ -155,10 +152,6 @@ static void writeIndex(
155152
writer.toString());
156153
}
157154

158-
private String destructurePath(String path) {
159-
return "." + path.replace(".", "!.");
160-
}
161-
162155
private void writePager() {
163156
String serviceTypeName = serviceSymbol.getName();
164157
String inputTypeName = inputSymbol.getName();
@@ -167,57 +160,42 @@ private void writePager() {
167160
String inputTokenName = paginatedInfo.getPaginatedTrait().getInputToken().get();
168161
String outputTokenName = paginatedInfo.getPaginatedTrait().getOutputToken().get();
169162

170-
writer.writeDocs("@public")
171-
.openBlock(
172-
"export async function* paginate$L(config: $L, input: $L, ...additionalArguments: any): Paginator<$L>{",
173-
"}", operationName, paginationType, inputTypeName, outputTypeName, () -> {
174-
String destructuredInputTokenName = destructurePath(inputTokenName);
175-
writer.write("// ToDo: replace with actual type instead of typeof input$L", destructuredInputTokenName);
176-
writer.write("let token: typeof input$L | undefined = config.startingToken || undefined;",
177-
destructuredInputTokenName);
178-
179-
writer.write("let hasNext = true;");
180-
writer.write("let page: $L;", outputTypeName);
181-
writer.openBlock("while (hasNext) {", "}", () -> {
182-
writer.write("input$L = token;", destructuredInputTokenName);
183-
184-
if (paginatedInfo.getPageSizeMember().isPresent()) {
185-
String pageSize = paginatedInfo.getPageSizeMember().get().getMemberName();
186-
writer.write("input[$S] = config.pageSize;", pageSize);
187-
}
188-
189-
writer.openBlock("if (config.client instanceof $L) {", "}", serviceTypeName, () -> {
190-
writer.write("page = await makePagedClientRequest(config.client, input, ...additionalArguments);");
191-
});
192-
writer.openBlock("else {", "}", () -> {
193-
writer.write("throw new Error(\"Invalid client, expected $L | $L\");",
194-
aggregatedClientName, serviceTypeName);
195-
});
196-
197-
writer.write("yield page;");
198-
writer.write("const prevToken = token;");
199-
writer.write("token = page$L;", destructurePath(outputTokenName));
200-
writer.write("hasNext = !!(token && (!config.stopOnSameToken || token !== prevToken));");
201-
});
202-
203-
writer.write("// @ts-ignore");
204-
writer.write("return undefined;");
205-
});
206-
}
207-
208-
209-
/**
210-
* Paginated command that calls CommandClient().send({...}) under the hood. This is meant for client side (browser)
211-
* environments and does not generally expose the entire service.
212-
*/
213-
private void writeCommandRequest() {
214-
writer.writeDocs("@internal");
215-
writer.openBlock(
216-
"const makePagedClientRequest = async (client: $L, input: $L, ...args: any): Promise<$L> => {",
217-
"}", serviceSymbol.getName(), inputSymbol.getName(),
218-
outputSymbol.getName(), () -> {
219-
writer.write("// @ts-ignore");
220-
writer.write("return await client.send(new $L(input), ...args);", operationSymbol.getName());
221-
});
163+
writer.addDependency(TypeScriptDependency.SMITHY_CORE);
164+
writer.addImport("createPaginator", null, TypeScriptDependency.SMITHY_CORE);
165+
166+
writer.writeDocs("@public");
167+
168+
writer
169+
.pushState()
170+
.putContext("operation", operationName)
171+
.putContext("aggClient", aggregatedClientName)
172+
.putContext("inputType", inputTypeName)
173+
.putContext("outputType", outputTypeName)
174+
.putContext("paginationType", paginationType)
175+
.putContext("serviceTypeName", serviceTypeName)
176+
.putContext("operationName", operationSymbol.getName())
177+
.putContext("inputToken", inputTokenName)
178+
.putContext("outputToken", outputTokenName)
179+
.putContext(
180+
"pageSizeMember",
181+
paginatedInfo.getPageSizeMember().map(MemberShape::getMemberName).orElse("")
182+
)
183+
.write(
184+
"""
185+
export const paginate${operation:L}: (
186+
config: ${aggClient:L}PaginationConfiguration,
187+
input: ${inputType:L},
188+
...rest: any[]
189+
) => Paginator<${outputType:L}> =
190+
createPaginator<${paginationType:L}, ${inputType:L}, ${outputType:L}>(
191+
${serviceTypeName:L},
192+
${operationName:L},
193+
${inputToken:S},
194+
${outputToken:S},
195+
${pageSizeMember:S}
196+
);
197+
"""
198+
)
199+
.popState();
222200
}
223201
}

0 commit comments

Comments
 (0)