diff --git a/build.gradle.kts b/build.gradle.kts index 193d7b66005..a9fb341d72e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -68,7 +68,7 @@ subprojects { * Java * ==================================================== */ - if (subproject.name != "smithy-typescript-codegen-test") { + if (subproject.name == "smithy-typescript-codegen") { apply(plugin = "java-library") java { diff --git a/settings.gradle.kts b/settings.gradle.kts index 04e6e07c65d..ddef9f4bf86 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -19,6 +19,7 @@ import java.nio.charset.StandardCharsets.UTF_8 rootProject.name = "smithy-typescript" include(":smithy-typescript-codegen") include(":smithy-typescript-codegen-test") +include(":smithy-typescript-ssdk-codegen-test-utils") file( java.nio.file.Paths.get(rootProject.projectDir.absolutePath, "local.properties")) diff --git a/smithy-typescript-codegen-test/build.gradle.kts b/smithy-typescript-codegen-test/build.gradle.kts index afe9982550d..62fc2cfc501 100644 --- a/smithy-typescript-codegen-test/build.gradle.kts +++ b/smithy-typescript-codegen-test/build.gradle.kts @@ -44,6 +44,7 @@ repositories { dependencies { implementation(project(":smithy-typescript-codegen")) + implementation(project(":smithy-typescript-ssdk-codegen-test-utils")) implementation("software.amazon.smithy:smithy-waiters:$smithyVersion") implementation("software.amazon.smithy:smithy-protocol-test-traits:$smithyVersion") } diff --git a/smithy-typescript-codegen-test/model/main.smithy b/smithy-typescript-codegen-test/model/main.smithy index 45517b267a0..e08c89f51b0 100644 --- a/smithy-typescript-codegen-test/model/main.smithy +++ b/smithy-typescript-codegen-test/model/main.smithy @@ -8,6 +8,7 @@ use smithy.waiters#waitable /// Provides weather forecasts. @fakeProtocol +@httpApiKeyAuth(name: "X-Api-Key", in: "header") @paginated(inputToken: "nextToken", outputToken: "nextToken", pageSize: "pageSize") service Weather { version: "2006-03-01", @@ -317,6 +318,7 @@ blob CityImageData @readonly @http(method: "GET", uri: "/cities/{cityId}/announcements") +@tags(["client-only"]) operation GetCityAnnouncements { input: GetCityAnnouncementsInput, output: GetCityAnnouncementsOutput, diff --git a/smithy-typescript-codegen-test/smithy-build.json b/smithy-typescript-codegen-test/smithy-build.json index 43d00c34209..b975f7b2320 100644 --- a/smithy-typescript-codegen-test/smithy-build.json +++ b/smithy-typescript-codegen-test/smithy-build.json @@ -1,5 +1,29 @@ { "version": "1.0", + "projections": { + "ssdk-test": { + "transforms": [ + { + "name": "excludeShapesByTag", + "args": { + "tags": ["client-only"] + } + } + ], + "plugins": { + "typescript-ssdk-codegen": { + "service": "example.weather#Weather", + "targetNamespace": "Weather", + "package": "weather", + "packageVersion": "0.0.1", + "packageJson": { + "license": "Apache-2.0" + }, + "disableDefaultValidation": true + } + } + } + }, "plugins": { "typescript-codegen": { "service": "example.weather#Weather", diff --git a/smithy-typescript-ssdk-codegen-test-utils/build.gradle.kts b/smithy-typescript-ssdk-codegen-test-utils/build.gradle.kts new file mode 100644 index 00000000000..0c50ba9650f --- /dev/null +++ b/smithy-typescript-ssdk-codegen-test-utils/build.gradle.kts @@ -0,0 +1,32 @@ +extra["displayName"] = "Smithy :: Typescript :: SSDK :: Codegen :: Test :: Utils" +extra["moduleName"] = "software.amazon.smithy.typescript.ssdk.codegen.test.utils" + +val smithyVersion: String by project + +buildscript { + val smithyVersion: String by project + + repositories { + mavenLocal() + mavenCentral() + } + dependencies { + "classpath"("software.amazon.smithy:smithy-cli:$smithyVersion") + } +} + +plugins { + val smithyGradleVersion: String by project + + id("software.amazon.smithy").version(smithyGradleVersion) +} + +repositories { + mavenLocal() + mavenCentral() +} + +dependencies { + implementation(project(":smithy-typescript-codegen")) + implementation("software.amazon.smithy:smithy-model:$smithyVersion") +} diff --git a/smithy-typescript-ssdk-codegen-test-utils/src/main/java/software/amazon/smithy/typescript/ssdk/codegen/test/utils/AddProtocols.java b/smithy-typescript-ssdk-codegen-test-utils/src/main/java/software/amazon/smithy/typescript/ssdk/codegen/test/utils/AddProtocols.java new file mode 100644 index 00000000000..d4de750d038 --- /dev/null +++ b/smithy-typescript-ssdk-codegen-test-utils/src/main/java/software/amazon/smithy/typescript/ssdk/codegen/test/utils/AddProtocols.java @@ -0,0 +1,20 @@ + package software.amazon.smithy.typescript.ssdk.codegen.test.utils; + + import java.util.List; + import software.amazon.smithy.typescript.codegen.integration.ProtocolGenerator; + import software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration; + import software.amazon.smithy.utils.ListUtils; + import software.amazon.smithy.utils.SmithyInternalApi; + + /** + * Adds fake protocols. + */ + @SmithyInternalApi + public class AddProtocols implements TypeScriptIntegration { + + @Override + public List getProtocolGenerators() { + return ListUtils.of(new TestProtocolGenerator()); + } + } + \ No newline at end of file diff --git a/smithy-typescript-ssdk-codegen-test-utils/src/main/java/software/amazon/smithy/typescript/ssdk/codegen/test/utils/TestProtocolGenerator.java b/smithy-typescript-ssdk-codegen-test-utils/src/main/java/software/amazon/smithy/typescript/ssdk/codegen/test/utils/TestProtocolGenerator.java new file mode 100644 index 00000000000..b5282c3a170 --- /dev/null +++ b/smithy-typescript-ssdk-codegen-test-utils/src/main/java/software/amazon/smithy/typescript/ssdk/codegen/test/utils/TestProtocolGenerator.java @@ -0,0 +1,155 @@ +package software.amazon.smithy.typescript.ssdk.codegen.test.utils; + +import java.util.List; +import java.util.Set; +import software.amazon.smithy.model.knowledge.HttpBinding; +import software.amazon.smithy.model.shapes.OperationShape; +import software.amazon.smithy.model.shapes.Shape; +import software.amazon.smithy.model.shapes.ShapeId; +import software.amazon.smithy.model.shapes.StructureShape; +import software.amazon.smithy.model.traits.TimestampFormatTrait.Format; +import software.amazon.smithy.typescript.codegen.TypeScriptDependency; +import software.amazon.smithy.typescript.codegen.TypeScriptWriter; +import software.amazon.smithy.typescript.codegen.integration.HttpBindingProtocolGenerator; +import software.amazon.smithy.utils.SmithyInternalApi; + + + /** + * Protocol for SSDK codegen testing. + */ +@SmithyInternalApi +class TestProtocolGenerator extends HttpBindingProtocolGenerator { + + TestProtocolGenerator() { + super(true); + } + + @Override + public ShapeId getProtocol() { + return ShapeId.from("example.weather#fakeProtocol"); + } + + @Override + public String getName() { + return "fakeProtocol"; + } + + @Override + protected String getDocumentContentType() { + return "application/json"; + } + + @Override + public Format getDocumentTimestampFormat() { + return Format.EPOCH_SECONDS; + } + + @Override + public boolean requiresNumericEpochSecondsInPayload() { + return true; + } + + @Override + public boolean enableSerdeElision() { + return true; + } + + @Override + public void deserializeErrorDocumentBody( + GenerationContext context, + StructureShape error, + List documentBindings + ) {} + + @Override + public void serializeErrorDocumentBody( + GenerationContext context, + StructureShape error, + List documentBindings + ) {} + + @Override + public void deserializeInputDocumentBody( + GenerationContext context, + OperationShape operation, + List documentBindings + ) {} + + @Override + public void serializeInputDocumentBody( + GenerationContext context, + OperationShape operation, + List documentBindings + ) {} + + @Override + public void deserializeOutputDocumentBody( + GenerationContext context, + OperationShape error, + List documentBindings + ) {} + + @Override + public void serializeOutputDocumentBody( + GenerationContext context, + OperationShape error, + List documentBindings + ) {} + + @Override + public void serializeInputEventDocumentPayload(GenerationContext context) {} + + @Override + public void generateDocumentBodyShapeSerializers(GenerationContext context, Set shapes) {} + + @Override + public void generateDocumentBodyShapeDeserializers(GenerationContext context, Set shapes) {} + + @Override + public void writeErrorCodeParser(GenerationContext context) { + TypeScriptWriter writer = context.getWriter(); + writer.write("const errorCode = parseErrorCode(output, parsedOutput.body);"); + } + + @Override + public void generateProtocolTests(GenerationContext context) {} + + @Override + public void generateSharedComponents(GenerationContext context) { + super.generateSharedComponents(context); + + TypeScriptWriter writer = context.getWriter(); + + // Include a JSON body parser used to deserialize documents from HTTP responses. + writer.addImport("SerdeContext", "__SerdeContext", TypeScriptDependency.SMITHY_TYPES); + writer.openBlock("const parseBody = (streamBody: any, context: __SerdeContext): " + + "any => collectBodyString(streamBody, context).then(encoded => {", "});", () -> { + writer.openBlock("if (encoded.length) {", "}", () -> { + writer.write("return JSON.parse(encoded);"); + }); + writer.write("return {};"); + }); + writer.write(""); + + // Include a JSON body parser. + writer.addImport("SerdeContext", "__SerdeContext", TypeScriptDependency.SMITHY_TYPES); + writer.openBlock("const parseErrorBody = async (errorBody: any, context: __SerdeContext) => {", + "}", () -> { + writer.write("const value = await parseBody(errorBody, context);"); + writer.write("value.message = value.message ?? value.Message;"); + writer.write("return value;"); + }); + writer.write(""); + + // Include an error code parser. + writer.openBlock("const parseErrorCode = (output: __HttpResponse, data: any): string | undefined => {", + "}", () -> { + writer.openBlock("if (output.headers[\"x-error\"]) {", "}", () -> { + writer.write("return output.headers[\"x-error\"];"); + }); + writer.openBlock("if (data.code !== undefined) {", "}", () -> { + writer.write("return data.code;"); + }); + }); + } +} diff --git a/smithy-typescript-ssdk-codegen-test-utils/src/main/resources/META-INF/services/software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration b/smithy-typescript-ssdk-codegen-test-utils/src/main/resources/META-INF/services/software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration new file mode 100644 index 00000000000..ac9c21fa612 --- /dev/null +++ b/smithy-typescript-ssdk-codegen-test-utils/src/main/resources/META-INF/services/software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration @@ -0,0 +1 @@ +software.amazon.smithy.typescript.ssdk.codegen.test.utils.AddProtocols