diff --git a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddAwsAuthPlugin.java b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddAwsAuthPlugin.java index 59e2ee9f1881..5843a3a50db1 100644 --- a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddAwsAuthPlugin.java +++ b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddAwsAuthPlugin.java @@ -24,6 +24,7 @@ import java.util.Set; import java.util.function.Consumer; import software.amazon.smithy.aws.traits.ServiceTrait; +import software.amazon.smithy.aws.traits.auth.SigV4Trait; import software.amazon.smithy.codegen.core.SymbolProvider; import software.amazon.smithy.model.Model; import software.amazon.smithy.model.knowledge.TopDownIndex; @@ -44,6 +45,7 @@ /** * Configure clients with AWS auth configurations and plugin. */ +// TODO: Think about AWS Auth supported for only some operations and not all, when not AWS service, with say @auth([]) public final class AddAwsAuthPlugin implements TypeScriptIntegration { @Override @@ -54,6 +56,9 @@ public void addConfigInterfaceFields( TypeScriptWriter writer ) { ServiceShape service = settings.getService(model); + if (!serviceUsesAwsAuth(service)) { + return; + } if (!areAllOptionalAuthOperations(model, service)) { writer.addImport("Credentials", "__Credentials", TypeScriptDependency.AWS_SDK_TYPES.packageName); writer.writeDocs("Default credentials provider; Not available in browser runtime.") @@ -66,13 +71,13 @@ public List getClientPlugins() { return ListUtils.of( RuntimeClientPlugin.builder() .withConventions(AwsDependency.MIDDLEWARE_SIGNING.dependency, "AwsAuth", HAS_CONFIG) - .servicePredicate((m, s) -> !areAllOptionalAuthOperations(m, s)) + .servicePredicate((m, s) -> serviceUsesAwsAuth(s) && !areAllOptionalAuthOperations(m, s)) .build(), RuntimeClientPlugin.builder() .withConventions(AwsDependency.MIDDLEWARE_SIGNING.dependency, "AwsAuth", HAS_MIDDLEWARE) // See operationUsesAwsAuth() below for AwsAuth Middleware customizations. .servicePredicate( - (m, s) -> !testServiceId(s, "STS") && !hasOptionalAuthOperation(m, s) + (m, s) -> !testServiceId(s, "STS") && serviceUsesAwsAuth(s) && !hasOptionalAuthOperation(m, s) ).build(), RuntimeClientPlugin.builder() .withConventions(AwsDependency.MIDDLEWARE_SIGNING.dependency, "AwsAuth", HAS_MIDDLEWARE) @@ -89,7 +94,7 @@ public Map> getRuntimeConfigWriters( LanguageTarget target ) { ServiceShape service = settings.getService(model); - if (areAllOptionalAuthOperations(model, service)) { + if (!serviceUsesAwsAuth(service) || areAllOptionalAuthOperations(model, service)) { return Collections.emptyMap(); } switch (target) { @@ -119,6 +124,10 @@ private static boolean testServiceId(Shape serviceShape, String expectedId) { return serviceShape.getTrait(ServiceTrait.class).map(ServiceTrait::getSdkId).orElse("").equals(expectedId); } + private static boolean serviceUsesAwsAuth(Shape serviceShape) { + return serviceShape.hasTrait(SigV4Trait.class); + } + private static boolean operationUsesAwsAuth(Model model, ServiceShape service, OperationShape operation) { // STS doesn't need auth for AssumeRoleWithWebIdentity, AssumeRoleWithSAML. // Remove when optionalAuth model update is published in 0533102932. @@ -130,8 +139,8 @@ private static boolean operationUsesAwsAuth(Model model, ServiceShape service, O } // optionalAuth trait doesn't require authentication. - if (hasOptionalAuthOperation(model, service)) { - return !operation.getTrait(OptionalAuthTrait.class).isPresent(); + if (serviceUsesAwsAuth(service) && hasOptionalAuthOperation(model, service)) { + return !operation.hasTrait(OptionalAuthTrait.class); } return false; } @@ -140,7 +149,7 @@ private static boolean hasOptionalAuthOperation(Model model, ServiceShape servic TopDownIndex topDownIndex = TopDownIndex.of(model); Set operations = topDownIndex.getContainedOperations(service); for (OperationShape operation : operations) { - if (operation.getTrait(OptionalAuthTrait.class).isPresent()) { + if (operation.hasTrait(OptionalAuthTrait.class)) { return true; } } @@ -151,7 +160,7 @@ private static boolean areAllOptionalAuthOperations(Model model, ServiceShape se TopDownIndex topDownIndex = TopDownIndex.of(model); Set operations = topDownIndex.getContainedOperations(service); for (OperationShape operation : operations) { - if (!operation.getTrait(OptionalAuthTrait.class).isPresent()) { + if (!operation.hasTrait(OptionalAuthTrait.class)) { return false; } } diff --git a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddAwsRuntimeConfig.java b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddAwsRuntimeConfig.java index 1d230838034d..7f7abfc4893a 100644 --- a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddAwsRuntimeConfig.java +++ b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddAwsRuntimeConfig.java @@ -15,6 +15,8 @@ package software.amazon.smithy.aws.typescript.codegen; +import static software.amazon.smithy.aws.typescript.codegen.AwsTraitsUtils.isAwsService; + import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -82,10 +84,12 @@ public void addConfigInterfaceFields( writer.addImport("Provider", "__Provider", TypeScriptDependency.AWS_SDK_TYPES.packageName); writer.addImport("Logger", "__Logger", TypeScriptDependency.AWS_SDK_TYPES.packageName); - writer.writeDocs("Unique service identifier.\n@internal") - .write("serviceId?: string;\n"); - writer.writeDocs("The AWS region to which this client will send requests") - .write("region?: string | __Provider;\n"); + if (isAwsService(settings, model)) { + writer.writeDocs("Unique service identifier.\n@internal") + .write("serviceId?: string;\n"); + writer.writeDocs("The AWS region to which this client will send requests") + .write("region?: string | __Provider;\n"); + } writer.writeDocs("Value for how many times a request will be made at most in case of retry.") .write("maxAttempts?: number | __Provider;\n"); writer.writeDocs("Optional logger for logging debug/info/warn/error.") @@ -114,11 +118,14 @@ public Map> getRuntimeConfigWriters( + "trait was found on " + service.getId()); } } - runtimeConfigs.putAll(getDefaultConfig(target)); + runtimeConfigs.putAll(getDefaultConfig(target, settings, model)); return runtimeConfigs; } - private Map> getDefaultConfig(LanguageTarget target) { + private Map> getDefaultConfig(LanguageTarget target, TypeScriptSettings settings, + Model model) { + Map> defaultConfigs = new HashMap(); + boolean isAwsService = isAwsService(settings, model); switch (target) { case SHARED: return MapUtils.of( @@ -128,40 +135,45 @@ private Map> getDefaultConfig(LanguageTarget } ); case BROWSER: - return MapUtils.of( - "region", writer -> { - writer.addDependency(TypeScriptDependency.INVALID_DEPENDENCY); - writer.addImport("invalidProvider", "invalidProvider", - TypeScriptDependency.INVALID_DEPENDENCY.packageName); - writer.write("region: invalidProvider(\"Region is missing\"),"); - }, - "maxAttempts", writer -> { - writer.addDependency(TypeScriptDependency.MIDDLEWARE_RETRY); - writer.addImport("DEFAULT_MAX_ATTEMPTS", "DEFAULT_MAX_ATTEMPTS", - TypeScriptDependency.MIDDLEWARE_RETRY.packageName); - writer.write("maxAttempts: DEFAULT_MAX_ATTEMPTS,"); - } - ); + if (isAwsService) { + defaultConfigs.put("region", writer -> { + writer.addDependency(TypeScriptDependency.INVALID_DEPENDENCY); + writer.addImport("invalidProvider", "invalidProvider", + TypeScriptDependency.INVALID_DEPENDENCY.packageName); + writer.write("region: invalidProvider(\"Region is missing\"),"); + }); + } + defaultConfigs.put("maxAttempts", writer -> { + writer.addDependency(TypeScriptDependency.MIDDLEWARE_RETRY); + writer.addImport("DEFAULT_MAX_ATTEMPTS", "DEFAULT_MAX_ATTEMPTS", + TypeScriptDependency.MIDDLEWARE_RETRY.packageName); + writer.write("maxAttempts: DEFAULT_MAX_ATTEMPTS,"); + }); + return defaultConfigs; case NODE: - return MapUtils.of( - "region", writer -> { - writer.addDependency(AwsDependency.NODE_CONFIG_PROVIDER); - writer.addImport("loadConfig", "loadNodeConfig", - AwsDependency.NODE_CONFIG_PROVIDER.packageName); - writer.addDependency(TypeScriptDependency.CONFIG_RESOLVER); - writer.addImport("NODE_REGION_CONFIG_OPTIONS", "NODE_REGION_CONFIG_OPTIONS", - TypeScriptDependency.CONFIG_RESOLVER.packageName); - writer.addImport("NODE_REGION_CONFIG_FILE_OPTIONS", "NODE_REGION_CONFIG_FILE_OPTIONS", - TypeScriptDependency.CONFIG_RESOLVER.packageName); - writer.write( + if (isAwsService) { + defaultConfigs.put("region", writer -> { + writer.addDependency(AwsDependency.NODE_CONFIG_PROVIDER); + writer.addImport("loadConfig", "loadNodeConfig", + AwsDependency.NODE_CONFIG_PROVIDER.packageName); + writer.addDependency(TypeScriptDependency.CONFIG_RESOLVER); + writer.addImport("NODE_REGION_CONFIG_OPTIONS", "NODE_REGION_CONFIG_OPTIONS", + TypeScriptDependency.CONFIG_RESOLVER.packageName); + writer.addImport("NODE_REGION_CONFIG_FILE_OPTIONS", "NODE_REGION_CONFIG_FILE_OPTIONS", + TypeScriptDependency.CONFIG_RESOLVER.packageName); + writer.write( "region: loadNodeConfig(NODE_REGION_CONFIG_OPTIONS, NODE_REGION_CONFIG_FILE_OPTIONS),"); - }, - "maxAttempts", writer -> { - writer.addImport("NODE_MAX_ATTEMPT_CONFIG_OPTIONS", "NODE_MAX_ATTEMPT_CONFIG_OPTIONS", - TypeScriptDependency.MIDDLEWARE_RETRY.packageName); - writer.write("maxAttempts: loadNodeConfig(NODE_MAX_ATTEMPT_CONFIG_OPTIONS),"); - } - ); + }); + } + defaultConfigs.put("maxAttempts", writer -> { + writer.addDependency(AwsDependency.NODE_CONFIG_PROVIDER); + writer.addImport("loadConfig", "loadNodeConfig", + AwsDependency.NODE_CONFIG_PROVIDER.packageName); + writer.addImport("NODE_MAX_ATTEMPT_CONFIG_OPTIONS", "NODE_MAX_ATTEMPT_CONFIG_OPTIONS", + TypeScriptDependency.MIDDLEWARE_RETRY.packageName); + writer.write("maxAttempts: loadNodeConfig(NODE_MAX_ATTEMPT_CONFIG_OPTIONS),"); + }); + return defaultConfigs; default: return Collections.emptyMap(); } diff --git a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddBuiltinPlugins.java b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddBuiltinPlugins.java index a2fc0e61a928..9f91b15ee334 100644 --- a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddBuiltinPlugins.java +++ b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddBuiltinPlugins.java @@ -15,6 +15,7 @@ package software.amazon.smithy.aws.typescript.codegen; +import static software.amazon.smithy.aws.typescript.codegen.AwsTraitsUtils.isAwsService; import static software.amazon.smithy.typescript.codegen.integration.RuntimeClientPlugin.Convention.HAS_CONFIG; import static software.amazon.smithy.typescript.codegen.integration.RuntimeClientPlugin.Convention.HAS_MIDDLEWARE; @@ -44,6 +45,7 @@ public List getClientPlugins() { return ListUtils.of( RuntimeClientPlugin.builder() .withConventions(TypeScriptDependency.CONFIG_RESOLVER.dependency, "Region", HAS_CONFIG) + .servicePredicate((m, s) -> isAwsService(s)) .build(), RuntimeClientPlugin.builder() .withConventions(TypeScriptDependency.CONFIG_RESOLVER.dependency, "Endpoints", HAS_CONFIG) diff --git a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddUserAgentDependency.java b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddUserAgentDependency.java index 485c9f198913..9158c06914d8 100644 --- a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddUserAgentDependency.java +++ b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddUserAgentDependency.java @@ -15,6 +15,8 @@ package software.amazon.smithy.aws.typescript.codegen; +import static software.amazon.smithy.aws.typescript.codegen.AwsTraitsUtils.isAwsService; + import java.util.Collections; import java.util.List; import java.util.Map; @@ -33,12 +35,15 @@ /** * Add client plubins and configs to support injecting user agent. */ +// TODO: Looks to add this back for non-AWS service clients, by fixing the dependency on ClientSharedValues.serviceId public class AddUserAgentDependency implements TypeScriptIntegration { @Override public List getClientPlugins() { return ListUtils.of( RuntimeClientPlugin.builder() - .withConventions(AwsDependency.MIDDLEWARE_USER_AGENT.dependency, "UserAgent").build()); + .withConventions(AwsDependency.MIDDLEWARE_USER_AGENT.dependency, "UserAgent") + .servicePredicate((m, s) -> isAwsService(s)) + .build()); } @Override @@ -48,6 +53,9 @@ public void addConfigInterfaceFields( SymbolProvider symbolProvider, TypeScriptWriter writer ) { + if (!isAwsService(settings, model)) { + return; + } writer.addImport("Provider", "Provider", TypeScriptDependency.AWS_SDK_TYPES.packageName); writer.addImport("UserAgent", "__UserAgent", TypeScriptDependency.AWS_SDK_TYPES.packageName); writer.writeDocs("The provider populating default tracking information to be sent with `user-agent`, " @@ -62,6 +70,9 @@ public Map> getRuntimeConfigWriters( SymbolProvider symbolProvider, LanguageTarget target ) { + if (!isAwsService(settings, model)) { + return Collections.emptyMap(); + } switch (target) { case NODE: return MapUtils.of( diff --git a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AwsEndpointGeneratorIntegration.java b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AwsEndpointGeneratorIntegration.java index d5656e79293e..64c26c3a6f1e 100644 --- a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AwsEndpointGeneratorIntegration.java +++ b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AwsEndpointGeneratorIntegration.java @@ -15,6 +15,8 @@ package software.amazon.smithy.aws.typescript.codegen; +import static software.amazon.smithy.aws.typescript.codegen.AwsTraitsUtils.isAwsService; + import java.util.Collections; import java.util.Map; import java.util.function.BiConsumer; @@ -39,7 +41,7 @@ public void writeAdditionalFiles( SymbolProvider symbolProvider, BiConsumer> writerFactory ) { - if (!settings.generateClient()) { + if (!settings.generateClient() || !isAwsService(settings, model)) { return; } @@ -55,7 +57,7 @@ public void addConfigInterfaceFields( SymbolProvider symbolProvider, TypeScriptWriter writer ) { - if (!settings.generateClient()) { + if (!settings.generateClient() || !isAwsService(settings, model)) { return; } @@ -71,7 +73,7 @@ public Map> getRuntimeConfigWriters( SymbolProvider symbolProvider, LanguageTarget target ) { - if (!settings.generateClient()) { + if (!settings.generateClient() || !isAwsService(settings, model)) { return Collections.emptyMap(); } diff --git a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AwsPackageFixturesGeneratorIntegration.java b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AwsPackageFixturesGeneratorIntegration.java index 4a3d7ace4134..3d6188e146d8 100644 --- a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AwsPackageFixturesGeneratorIntegration.java +++ b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AwsPackageFixturesGeneratorIntegration.java @@ -15,6 +15,8 @@ package software.amazon.smithy.aws.typescript.codegen; +import static software.amazon.smithy.aws.typescript.codegen.AwsTraitsUtils.isAwsService; + import java.util.Arrays; import java.util.Calendar; import java.util.function.BiConsumer; @@ -56,7 +58,8 @@ public void writeAdditionalFiles( writer.write(resource); }); - if (!settings.generateClient()) { + // TODO: May need to generate a different/modified README.md for these cases + if (!settings.generateClient() || !isAwsService(settings, model)) { return; } diff --git a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AwsServiceIdIntegration.java b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AwsServiceIdIntegration.java index fe00dc300c51..045391406265 100644 --- a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AwsServiceIdIntegration.java +++ b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AwsServiceIdIntegration.java @@ -44,6 +44,7 @@ public SymbolProvider decorateSymbolProvider( return symbol; } + // TODO: Should this WARNING be avoided somehow if client is not for an AWS service? // If the SDK service ID trait is present, use that, otherwise fall back to // the default naming strategy for the service. return shape.getTrait(ServiceTrait.class) diff --git a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AwsTraitsUtils.java b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AwsTraitsUtils.java new file mode 100644 index 000000000000..9d0e37fb9155 --- /dev/null +++ b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AwsTraitsUtils.java @@ -0,0 +1,37 @@ +/* + * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.smithy.aws.typescript.codegen; + +import software.amazon.smithy.aws.traits.ServiceTrait; +import software.amazon.smithy.model.Model; +import software.amazon.smithy.model.shapes.ServiceShape; +import software.amazon.smithy.typescript.codegen.TypeScriptSettings; + +/** + * Utility methods related to AWS traits. + */ +final class AwsTraitsUtils { + + private AwsTraitsUtils() {} + + static boolean isAwsService(TypeScriptSettings settings, Model model) { + return isAwsService(settings.getService(model)); + } + + static boolean isAwsService(ServiceShape serviceShape) { + return serviceShape.hasTrait(ServiceTrait.class); + } +} diff --git a/codegen/smithy-aws-typescript-codegen/src/test/resources/software/amazon/smithy/aws/typescript/codegen/NotSame.smithy b/codegen/smithy-aws-typescript-codegen/src/test/resources/software/amazon/smithy/aws/typescript/codegen/NotSame.smithy index 24c748af32e3..3401b6f3c41c 100644 --- a/codegen/smithy-aws-typescript-codegen/src/test/resources/software/amazon/smithy/aws/typescript/codegen/NotSame.smithy +++ b/codegen/smithy-aws-typescript-codegen/src/test/resources/software/amazon/smithy/aws/typescript/codegen/NotSame.smithy @@ -4,6 +4,7 @@ use aws.protocols#restJson1 @aws.api#service(sdkId: "Not Same") @restJson1 +@aws.auth#sigv4(name: "notsame") service OriginalName { version: "2019-10-15", operations: [GetFoo] diff --git a/packages/config-resolver/src/EndpointsConfig.ts b/packages/config-resolver/src/EndpointsConfig.ts index 640d90bb54b6..579850c4bb5e 100644 --- a/packages/config-resolver/src/EndpointsConfig.ts +++ b/packages/config-resolver/src/EndpointsConfig.ts @@ -13,9 +13,9 @@ export interface EndpointsInputConfig { } interface PreviouslyResolved { - regionInfoProvider: RegionInfoProvider; + regionInfoProvider?: RegionInfoProvider; urlParser: UrlParser; - region: Provider; + region?: Provider; } export interface EndpointsResolvedConfig extends Required { @@ -45,6 +45,10 @@ const normalizeEndpoint = (input: EndpointsInputConfig & PreviouslyResolved): Pr }; const getEndPointFromRegion = async (input: EndpointsInputConfig & PreviouslyResolved) => { + if (input.region === undefined || input.regionInfoProvider === undefined) { + throw new Error("No endpoint specified and region is not defined"); + } + const { tls = true } = input; const region = await input.region();