diff --git a/.changeset/large-trainers-cross.md b/.changeset/large-trainers-cross.md new file mode 100644 index 00000000000..4641567fed3 --- /dev/null +++ b/.changeset/large-trainers-cross.md @@ -0,0 +1,5 @@ +--- +"@smithy/experimental-identity-and-auth": patch +--- + +set identity&auth SRA active by default diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2b9e65ceeab..0e9dc6ab26b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -30,7 +30,7 @@ under development: Experimental Feature | Flag | Description ---------------------|-------------------------------|------------ -Identity & Auth | `experimentalIdentityAndAuth` | Standardize identity and auth integrations to match the Smithy specification (see [Authentication Traits](https://smithy.io/2.0/spec/authentication-traits.html)). Newer capabilities include support for multiple auth schemes, `@optionalAuth`, and standardized identity interfaces for authentication schemes both in code generation and TypeScript packages. In `smithy-typescript`, `@httpApiKeyAuth` will be updated to use the new standardized interfaces. In `aws-sdk-js-v3` (`smithy-typescript`'s largest customer), this will affect `@aws.auth#sigv4` and `@httpBearerAuth` implementations, but is planned to be completely backwards-compatible. +N/A | N/A | N/A ## Reporting Bugs/Feature Requests diff --git a/README.md b/README.md index 9264ce3099d..b10dda96c90 100644 --- a/README.md +++ b/README.md @@ -197,7 +197,7 @@ By default, the Smithy TypeScript code generators provide the code generation fr |`private`|No|Whether the package is `private` in `package.json`. The default value is `false`.| |`requiredMemberMode`|No|**NOT RECOMMENDED DUE TO BACKWARD COMPATIBILITY CONCERNS.** Sets whether members marked with the `@required` trait are allowed to be `undefined`. See more details on the risks in `TypeScriptSettings.RequiredMemberMode`. The default value is `nullable`.| |`createDefaultReadme`|No|Whether to generate a default `README.md` for the package. The default value is `false`.| -|`experimentalIdentityAndAuth`|No|Experimental feature that standardizes identity and auth integrations to match the Smithy specification (see [Authentication Traits](https://smithy.io/2.0/spec/authentication-traits.html)). See [the experimental features section for more details](CONTRIBUTING.md#experimental-features).| +|`useLegacyAuth`|No|**NOT RECOMMENDED, AVAILABLE ONLY FOR BACKWARD COMPATIBILITY CONCERNS.** Flag that enables using legacy auth. When in doubt, use the default identity and auth behavior (not configuring `useLegacyAuth`) as the golden path.| #### `typescript-client-codegen` plugin artifacts diff --git a/packages/experimental-identity-and-auth/src/integration/httpApiKeyAuth.integ.spec.ts b/packages/experimental-identity-and-auth/src/integration/httpApiKeyAuth.integ.spec.ts index 9ab8efa9805..496bd51236e 100644 --- a/packages/experimental-identity-and-auth/src/integration/httpApiKeyAuth.integ.spec.ts +++ b/packages/experimental-identity-and-auth/src/integration/httpApiKeyAuth.integ.spec.ts @@ -7,7 +7,7 @@ import { import { requireRequestsFrom } from "@smithy/util-test"; describe("@httpApiKeyAuth integration tests", () => { - // TODO(experimentalIdentityAndAuth): should match `HttpApiKeyAuthService` `@httpApiKeyAuth` trait + // Match `HttpApiKeyAuthService` `@httpApiKeyAuth` trait const MOCK_API_KEY_NAME = "Authorization"; const MOCK_API_KEY_SCHEME = "ApiKey"; const MOCK_API_KEY = "APIKEY_123"; diff --git a/scripts/build-generated-test-packages.js b/scripts/build-generated-test-packages.js index 65c378b8bb7..4797a7aa884 100644 --- a/scripts/build-generated-test-packages.js +++ b/scripts/build-generated-test-packages.js @@ -9,59 +9,39 @@ const { spawnProcess } = require("./utils/spawn-process"); const root = path.join(__dirname, ".."); -const testProjectDir = path.join( - root, - "smithy-typescript-codegen-test", -); +const testProjectDir = path.join(root, "smithy-typescript-codegen-test"); -const codegenTestDir = path.join( - testProjectDir, - "build", - "smithyprojections", - "smithy-typescript-codegen-test", -); +const codegenTestDir = path.join(testProjectDir, "build", "smithyprojections", "smithy-typescript-codegen-test"); -const weatherClientDir = path.join( - codegenTestDir, - "source", - "typescript-client-codegen" -); +const weatherClientDir = path.join(codegenTestDir, "source", "typescript-client-codegen"); const releasedClientDir = path.join( - testProjectDir, - "released-version-test", - "build", - "smithyprojections", - "released-version-test", - "source", - "typescript-codegen" + testProjectDir, + "released-version-test", + "build", + "smithyprojections", + "released-version-test", + "source", + "typescript-codegen" ); -// TODO(experimentalIdentityAndAuth): build generic client for integration tests -const weatherExperimentalIdentityAndAuthClientDir = path.join( - codegenTestDir, - "client-experimental-identity-and-auth", - "typescript-client-codegen" -); +// Build generic legacy auth client for integration tests +const weatherLegacyAuthClientDir = path.join(codegenTestDir, "client-legacy-auth", "typescript-client-codegen"); -const weatherSsdkDir = path.join( - codegenTestDir, - "ssdk-test", - "typescript-server-codegen" -) +const weatherSsdkDir = path.join(codegenTestDir, "ssdk-test", "typescript-server-codegen"); -// TODO(experimentalIdentityAndAuth): add `@httpApiKeyAuth` client for integration tests +// Build `@httpApiKeyAuth` client for integration tests const httpApiKeyAuthClientDir = path.join( - codegenTestDir, - "identity-and-auth-http-api-key-auth", - "typescript-client-codegen" + codegenTestDir, + "identity-and-auth-http-api-key-auth", + "typescript-client-codegen" ); -// TODO(experimentalIdentityAndAuth): add `@httpBearerAuth` client for integration tests +// Build `@httpBearerAuth` client for integration tests const httpBearerAuthClientDir = path.join( - codegenTestDir, - "identity-and-auth-http-bearer-auth", - "typescript-client-codegen" + codegenTestDir, + "identity-and-auth-http-bearer-auth", + "typescript-client-codegen" ); const nodeModulesDir = path.join(root, "node_modules"); @@ -82,10 +62,14 @@ const buildAndCopyToNodeModules = async (packageName, codegenDir, nodeModulesDir await spawnProcess("rm", ["-rf", packageName], { cwd: nodeModulesDir }); await spawnProcess("mkdir", ["-p", packageName], { cwd: nodeModulesDir }); const targetPackageDir = path.join(nodeModulesDir, packageName); - await spawnProcess("tar", ["-xf", "package.tgz", "-C", targetPackageDir, "--strip-components", "1"], { cwd: codegenDir }); + await spawnProcess("tar", ["-xf", "package.tgz", "-C", targetPackageDir, "--strip-components", "1"], { + cwd: codegenDir, + }); } } catch (e) { - console.log(`Building and copying package \`${packageName}\` in \`${codegenDir}\` to \`${nodeModulesDir}\` failed:`) + console.log( + `Building and copying package \`${packageName}\` in \`${codegenDir}\` to \`${nodeModulesDir}\` failed:` + ); console.log(e); process.exit(1); } @@ -94,12 +78,17 @@ const buildAndCopyToNodeModules = async (packageName, codegenDir, nodeModulesDir (async () => { await buildAndCopyToNodeModules("weather", weatherClientDir, nodeModulesDir); await buildAndCopyToNodeModules("weather-ssdk", weatherSsdkDir, nodeModulesDir); - // TODO(experimentalIdentityAndAuth): build generic client for integration tests - await buildAndCopyToNodeModules("@smithy/weather-experimental-identity-and-auth", weatherExperimentalIdentityAndAuthClientDir, nodeModulesDir); - // TODO(experimentalIdentityAndAuth): add `@httpApiKeyAuth` client for integration tests - await buildAndCopyToNodeModules("@smithy/identity-and-auth-http-api-key-auth-service", httpApiKeyAuthClientDir, nodeModulesDir); - // TODO(experimentalIdentityAndAuth): add `@httpBearerAuth` client for integration tests - await buildAndCopyToNodeModules("@smithy/identity-and-auth-http-bearer-auth-service", httpBearerAuthClientDir, nodeModulesDir); - // Test released version of smithy-typescript codegenerators, but - await buildAndCopyToNodeModules("released", releasedClientDir, undefined); + await buildAndCopyToNodeModules("@smithy/weather-legacy-auth", weatherLegacyAuthClientDir, nodeModulesDir); + await buildAndCopyToNodeModules( + "@smithy/identity-and-auth-http-api-key-auth-service", + httpApiKeyAuthClientDir, + nodeModulesDir + ); + await buildAndCopyToNodeModules( + "@smithy/identity-and-auth-http-bearer-auth-service", + httpBearerAuthClientDir, + nodeModulesDir + ); + // TODO(released-version-test): Test released version of smithy-typescript codegenerators, but currently is not working + // await buildAndCopyToNodeModules("released", releasedClientDir, undefined); })(); diff --git a/smithy-typescript-codegen-test/example-weather-customizations/src/main/java/example/weather/SupportWeatherSigV4Auth.java b/smithy-typescript-codegen-test/example-weather-customizations/src/main/java/example/weather/SupportWeatherSigV4Auth.java new file mode 100644 index 00000000000..9384e44ba63 --- /dev/null +++ b/smithy-typescript-codegen-test/example-weather-customizations/src/main/java/example/weather/SupportWeatherSigV4Auth.java @@ -0,0 +1,133 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package example.weather; + +import java.util.Optional; +import java.util.function.Consumer; +import software.amazon.smithy.codegen.core.Symbol; +import software.amazon.smithy.codegen.core.SymbolReference; +import software.amazon.smithy.model.shapes.ShapeId; +import software.amazon.smithy.typescript.codegen.ApplicationProtocol; +import software.amazon.smithy.typescript.codegen.LanguageTarget; +import software.amazon.smithy.typescript.codegen.TypeScriptDependency; +import software.amazon.smithy.typescript.codegen.TypeScriptSettings; +import software.amazon.smithy.typescript.codegen.TypeScriptWriter; +import software.amazon.smithy.typescript.codegen.auth.http.ConfigField; +import software.amazon.smithy.typescript.codegen.auth.http.HttpAuthOptionProperty; +import software.amazon.smithy.typescript.codegen.auth.http.HttpAuthScheme; +import software.amazon.smithy.typescript.codegen.auth.http.HttpAuthSchemeParameter; +import software.amazon.smithy.typescript.codegen.auth.http.integration.HttpAuthTypeScriptIntegration; +import software.amazon.smithy.utils.SmithyInternalApi; + +@SmithyInternalApi +public final class SupportWeatherSigV4Auth implements HttpAuthTypeScriptIntegration { + static final Symbol AWS_CREDENTIAL_IDENTITY = Symbol.builder() + .name("AwsCredentialIdentity") + .namespace(TypeScriptDependency.SMITHY_TYPES.getPackageName(), "/") + .addDependency(TypeScriptDependency.SMITHY_TYPES) + .build(); + static final Symbol AWS_CREDENTIAL_IDENTITY_PROVIDER = Symbol.builder() + .name("AwsCredentialIdentityProvider") + .namespace(TypeScriptDependency.SMITHY_TYPES.getPackageName(), "/") + .addDependency(TypeScriptDependency.SMITHY_TYPES) + .build(); + static final ConfigField CREDENTIALS_CONFIG_FIELD = ConfigField.builder() + .name("credentials") + .type(ConfigField.Type.MAIN) + .docs(w -> w.write("The credentials used to sign requests.")) + .inputType(Symbol.builder() + .name("AwsCredentialIdentity | AwsCredentialIdentityProvider") + .addReference(AWS_CREDENTIAL_IDENTITY) + .addReference(AWS_CREDENTIAL_IDENTITY_PROVIDER) + .build()) + .resolvedType(Symbol.builder() + .name("AwsCredentialIdentityProvider") + .addReference(AWS_CREDENTIAL_IDENTITY) + .addReference(AWS_CREDENTIAL_IDENTITY_PROVIDER) + .build()) + .configFieldWriter(ConfigField::defaultMainConfigFieldWriter) + .build(); + private static final Consumer AWS_SIGV4_AUTH_SIGNER = w -> { + w.addDependency(TypeScriptDependency.EXPERIMENTAL_IDENTITY_AND_AUTH); + w.addImport("SigV4Signer", null, TypeScriptDependency.EXPERIMENTAL_IDENTITY_AND_AUTH); + w.write("new SigV4Signer()"); + }; + private static final SymbolReference PROVIDER = SymbolReference.builder() + .symbol(Symbol.builder() + .name("Provider") + .namespace(TypeScriptDependency.SMITHY_TYPES.getPackageName(), "/") + .addDependency(TypeScriptDependency.SMITHY_TYPES) + .build()) + .alias("__Provider") + .build(); + + @Override + public boolean matchesSettings(TypeScriptSettings settings) { + return !settings.useLegacyAuth(); + } + + @Override + public Optional getHttpAuthScheme() { + return Optional.of(HttpAuthScheme.builder() + .schemeId(ShapeId.from("aws.auth#sigv4")) + .applicationProtocol(ApplicationProtocol.createDefaultHttpApplicationProtocol()) + .putDefaultSigner(LanguageTarget.SHARED, AWS_SIGV4_AUTH_SIGNER) + .addConfigField(CREDENTIALS_CONFIG_FIELD) + .addConfigField(ConfigField.builder() + .name("region") + .type(ConfigField.Type.AUXILIARY) + .docs(w -> w.write("The AWS region to which this client will send requests.")) + .inputType(Symbol.builder() + .name("string | __Provider") + .addReference(PROVIDER) + .build()) + .resolvedType(Symbol.builder() + .name("__Provider") + .addReference(PROVIDER) + .build()) + .configFieldWriter(ConfigField::defaultAuxiliaryConfigFieldWriter) + .build()) + .addHttpAuthSchemeParameter(HttpAuthSchemeParameter.builder() + .name("region") + .type(w -> w.write("string")) + .source(w -> { + w.addDependency(TypeScriptDependency.UTIL_MIDDLEWARE); + w.addImport("normalizeProvider", null, TypeScriptDependency.UTIL_MIDDLEWARE); + w.openBlock("await normalizeProvider(config.region)() || (() => {", "})()", () -> { + w.write("throw new Error(\"expected `region` to be configured for `aws.auth#sigv4`\");"); + }); + }) + .build()) + .addHttpAuthOptionProperty(HttpAuthOptionProperty.builder() + .name("name") + .type(HttpAuthOptionProperty.Type.SIGNING) + .source(s -> w -> { + w.write("$S", s.trait().toNode().expectObjectNode().getMember("name")); + }) + .build()) + .addHttpAuthOptionProperty(HttpAuthOptionProperty.builder() + .name("region") + .type(HttpAuthOptionProperty.Type.SIGNING) + .source(t -> w -> { + w.write("authParameters.region"); + }) + .build()) + .propertiesExtractor(s -> w -> w + .write(""" + (config, context) => { + return { + /** + * @internal + */ + signingProperties: { + ...config, + ...context, + }, + }; + },""")) + .build()); + } +} diff --git a/smithy-typescript-codegen-test/example-weather-customizations/src/main/resources/META-INF/services/software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration b/smithy-typescript-codegen-test/example-weather-customizations/src/main/resources/META-INF/services/software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration index 93c3c677e46..17504f263bd 100644 --- a/smithy-typescript-codegen-test/example-weather-customizations/src/main/resources/META-INF/services/software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration +++ b/smithy-typescript-codegen-test/example-weather-customizations/src/main/resources/META-INF/services/software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration @@ -1 +1,2 @@ example.weather.ExampleWeatherCustomEndpointsRuntimeConfig +example.weather.SupportWeatherSigV4Auth diff --git a/smithy-typescript-codegen-test/model/weather/main.smithy b/smithy-typescript-codegen-test/model/weather/main.smithy index e8abc79201c..6446b1c9eb5 100644 --- a/smithy-typescript-codegen-test/model/weather/main.smithy +++ b/smithy-typescript-codegen-test/model/weather/main.smithy @@ -34,7 +34,7 @@ service Weather { GetCurrentTime // util-stream.integ.spec.ts Invoke - // experimentalIdentityAndAuth + // Identity and Auth OnlyHttpApiKeyAuth OnlyHttpApiKeyAuthOptional OnlyHttpBearerAuth diff --git a/smithy-typescript-codegen-test/released-version-test/build.gradle.kts b/smithy-typescript-codegen-test/released-version-test/build.gradle.kts index a46cf794210..38e874f58a0 100644 --- a/smithy-typescript-codegen-test/released-version-test/build.gradle.kts +++ b/smithy-typescript-codegen-test/released-version-test/build.gradle.kts @@ -3,6 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +// TODO(released-version-test): Test released version of smithy-typescript codegenerators, but currently is extremely flaky +/* plugins { java id("software.amazon.smithy.gradle.smithy-base") @@ -27,3 +29,4 @@ dependencies { } tasks["jar"].enabled = false +*/ \ No newline at end of file diff --git a/smithy-typescript-codegen-test/smithy-build.json b/smithy-typescript-codegen-test/smithy-build.json index a5251a5e386..704f8eb617b 100644 --- a/smithy-typescript-codegen-test/smithy-build.json +++ b/smithy-typescript-codegen-test/smithy-build.json @@ -29,7 +29,7 @@ } } }, - "client-experimental-identity-and-auth": { + "client-identity-and-auth": { "transforms": [ { "name": "includeServices", @@ -41,17 +41,16 @@ "plugins": { "typescript-client-codegen": { "service": "example.weather#Weather", - "package": "@smithy/weather-experimental-identity-and-auth", + "package": "weather", "packageVersion": "0.0.1", "packageJson": { "license": "Apache-2.0", "private": true - }, - "experimentalIdentityAndAuth": true + } } } }, - "control-experimental-identity-and-auth": { + "client-legacy-auth": { "transforms": [ { "name": "includeServices", @@ -63,12 +62,13 @@ "plugins": { "typescript-client-codegen": { "service": "example.weather#Weather", - "package": "weather", + "package": "@smithy/weather-legacy-auth", "packageVersion": "0.0.1", "packageJson": { "license": "Apache-2.0", "private": true - } + }, + "useLegacyAuth": true } } }, @@ -89,8 +89,7 @@ "packageJson": { "license": "Apache-2.0", "private": true - }, - "experimentalIdentityAndAuth": true + } } } }, @@ -111,8 +110,7 @@ "packageJson": { "license": "Apache-2.0", "private": true - }, - "experimentalIdentityAndAuth": true + } } } } diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/CommandGenerator.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/CommandGenerator.java index 0f4011f1966..aa3305e2f2d 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/CommandGenerator.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/CommandGenerator.java @@ -30,6 +30,7 @@ import java.util.Optional; import java.util.Set; import java.util.TreeSet; +import java.util.function.Consumer; import java.util.function.Function; import java.util.stream.Collectors; import software.amazon.smithy.build.FileManifest; @@ -56,7 +57,9 @@ import software.amazon.smithy.typescript.codegen.sections.CommandBodyExtraCodeSection; import software.amazon.smithy.typescript.codegen.sections.CommandConstructorCodeSection; import software.amazon.smithy.typescript.codegen.sections.CommandPropertiesCodeSection; +import software.amazon.smithy.typescript.codegen.sections.PreCommandClassCodeSection; import software.amazon.smithy.typescript.codegen.sections.SmithyContextCodeSection; +import software.amazon.smithy.typescript.codegen.util.CommandWriterConsumer; import software.amazon.smithy.typescript.codegen.validation.SensitiveDataFinder; import software.amazon.smithy.utils.SmithyInternalApi; @@ -154,6 +157,17 @@ private void generateClientCommand() { ); } + // Section of items like TypeScript @ts-ignore + writer.injectSection(PreCommandClassCodeSection.builder() + .settings(settings) + .model(model) + .service(service) + .operation(operation) + .symbolProvider(symbolProvider) + .runtimeClientPlugins(runtimePlugins) + .protocolGenerator(protocolGenerator) + .applicationProtocol(applicationProtocol) + .build()); writer.openBlock( "export class $L extends $$Command.classBuilder<$T, $T, $L, ServiceInputTypes, ServiceOutputTypes>()", ".build() {", // class open bracket. @@ -459,10 +473,7 @@ private void addCommandSpecificPlugins() { // Construct additional parameters string Map paramsMap = plugin.getAdditionalPluginFunctionParameters( model, service, operation); - List additionalParameters = CodegenUtils.getFunctionParametersList(paramsMap); - String additionalParamsString = additionalParameters.isEmpty() - ? "" - : ", { " + String.join(", ", additionalParameters) + " }"; + // Construct writer context Map symbolMap = new HashMap<>(); @@ -474,7 +485,33 @@ private void addCommandSpecificPlugins() { } writer.pushState(); writer.putContext(symbolMap); - writer.write("$pluginFn:T(config" + additionalParamsString + "),"); + writer.openBlock("$pluginFn:T(config", "),", () -> { + List additionalParameters = CodegenUtils.getFunctionParametersList(paramsMap); + Map clientAddParamsWriterConsumers = + plugin.getOperationAddParamsWriterConsumers(); + if (additionalParameters.isEmpty() && clientAddParamsWriterConsumers.isEmpty()) { + return; + } + writer.openBlock(", { ", " }", () -> { + writer + .pushState() + .putContext("params", additionalParameters) + .writeInline("${#params}${value:L}, ${/params}") + .popState(); + clientAddParamsWriterConsumers.forEach((key, consumer) -> { + writer.writeInline("$L: $C,", key, (Consumer) (w -> { + consumer.accept(w, CommandConstructorCodeSection.builder() + .settings(settings) + .model(model) + .service(service) + .symbolProvider(symbolProvider) + .runtimeClientPlugins(runtimePlugins) + .applicationProtocol(applicationProtocol) + .build()); + })); + }); + }); + }); writer.popState(); }); } diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/DirectedTypeScriptCodegen.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/DirectedTypeScriptCodegen.java index f70ab9cc58b..fea50a6e42d 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/DirectedTypeScriptCodegen.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/DirectedTypeScriptCodegen.java @@ -102,6 +102,11 @@ public TypeScriptCodegenContext createContext(CreateContextDirective { + LOGGER.info(() -> "Mutating plugins from TypeScriptIntegration: " + integration.name()); + integration.mutateClientPlugins(runtimePlugins); + }); + ProtocolGenerator protocolGenerator = resolveProtocolGenerator( directive.integrations(), directive.model(), @@ -236,9 +241,7 @@ private void generateClient(GenerateServiceDirective new ServiceBareBonesClientGenerator( settings, model, symbolProvider, writer, integrations, runtimePlugins, applicationProtocol).run()); - if (directive.settings().getExperimentalIdentityAndAuth()) { - // feat(experimentalIdentityAndAuth): allow configuring custom HttpAuthSchemeProviderGenerator - LOGGER.fine("experimentalIdentityAndAuth: Generating auth scheme resolver"); + if (!directive.settings().useLegacyAuth()) { new HttpAuthSchemeProviderGenerator( delegator, settings, diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/RuntimeConfigGenerator.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/RuntimeConfigGenerator.java index bc1ba5a35fd..9fce5fa7693 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/RuntimeConfigGenerator.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/RuntimeConfigGenerator.java @@ -195,10 +195,9 @@ void generate(LanguageTarget target) { integration.getRuntimeConfigWriters(settings, model, symbolProvider, target) ); } - // feat(experimentalIdentityAndAuth): add config writers for httpAuthScheme and httpAuthSchemes // Needs a separate integration point since not all the information is accessible in // {@link TypeScriptIntegration#getRuntimeConfigWriters()} - if (applicationProtocol.isHttpProtocol() && settings.getExperimentalIdentityAndAuth()) { + if (applicationProtocol.isHttpProtocol() && !settings.useLegacyAuth()) { generateHttpAuthSchemeConfig(configs, writer, target); } int indentation = target.equals(LanguageTarget.SHARED) ? 1 : 2; @@ -229,7 +228,6 @@ private void generateHttpAuthSchemeConfig( ) { SupportedHttpAuthSchemesIndex authIndex = new SupportedHttpAuthSchemesIndex(integrations, model, settings); - // feat(experimentalIdentityAndAuth): write the default imported HttpAuthSchemeProvider if (target.equals(LanguageTarget.SHARED)) { configs.put("httpAuthSchemeProvider", w -> { w.write("$T", Symbol.builder() @@ -241,7 +239,6 @@ private void generateHttpAuthSchemeConfig( }); } - // feat(experimentalIdentityAndAuth): gather HttpAuthSchemes to generate ServiceIndex serviceIndex = ServiceIndex.of(model); TopDownIndex topDownIndex = TopDownIndex.of(model); Map allEffectiveHttpAuthSchemes = @@ -268,7 +265,6 @@ private void generateHttpAuthSchemeConfig( return; } - // feat(experimentalIdentityAndAuth): write the default httpAuthSchemes configs.put("httpAuthSchemes", w -> { w.addDependency(TypeScriptDependency.SMITHY_TYPES); w.addImport("IdentityProviderConfig", null, TypeScriptDependency.SMITHY_TYPES); diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/ServiceBareBonesClientGenerator.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/ServiceBareBonesClientGenerator.java index 3d5feebe53f..e872e05b59a 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/ServiceBareBonesClientGenerator.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/ServiceBareBonesClientGenerator.java @@ -41,6 +41,7 @@ import software.amazon.smithy.typescript.codegen.sections.ClientConstructorCodeSection; import software.amazon.smithy.typescript.codegen.sections.ClientDestroyCodeSection; import software.amazon.smithy.typescript.codegen.sections.ClientPropertiesCodeSection; +import software.amazon.smithy.typescript.codegen.util.ClientWriterConsumer; import software.amazon.smithy.utils.OptionalUtils; import software.amazon.smithy.utils.SmithyInternalApi; @@ -63,13 +64,13 @@ public final class ServiceBareBonesClientGenerator implements Runnable { private final ApplicationProtocol applicationProtocol; ServiceBareBonesClientGenerator( - TypeScriptSettings settings, - Model model, - SymbolProvider symbolProvider, - TypeScriptWriter writer, - List integrations, - List runtimePlugins, - ApplicationProtocol applicationProtocol + TypeScriptSettings settings, + Model model, + SymbolProvider symbolProvider, + TypeScriptWriter writer, + List integrations, + List runtimePlugins, + ApplicationProtocol applicationProtocol ) { this.settings = settings; this.model = model; @@ -438,10 +439,6 @@ private void generateConstructor() { // Construct additional parameters string Map paramsMap = plugin.getAdditionalPluginFunctionParameters( model, service, null); - List additionalParameters = CodegenUtils.getFunctionParametersList(paramsMap); - String additionalParamsString = additionalParameters.isEmpty() - ? "" - : ", { " + String.join(", ", additionalParameters) + " }"; // Construct writer context Map symbolMap = new HashMap<>(); @@ -453,11 +450,39 @@ private void generateConstructor() { } writer.pushState(); writer.putContext(symbolMap); - writer.write("this.middlewareStack.use($pluginFn:T(this.config" + additionalParamsString + "));"); + writer.openBlock("this.middlewareStack.use($pluginFn:T(this.config", "));", () -> { + List additionalParameters = CodegenUtils.getFunctionParametersList(paramsMap); + Map clientAddParamsWriterConsumers = + plugin.getClientAddParamsWriterConsumers(); + + if (additionalParameters.isEmpty() && clientAddParamsWriterConsumers.isEmpty()) { + return; + } + + writer.openBlock(", {", " }", () -> { + writer + .pushState() + .putContext("params", additionalParameters) + .writeInline("${#params}${value:L}, ${/params}") + .popState(); + clientAddParamsWriterConsumers.forEach((key, consumer) -> { + writer.writeInline("$L: $C,", key, (Consumer) (w -> { + consumer.accept(w, ClientBodyExtraCodeSection.builder() + .settings(settings) + .model(model) + .service(service) + .symbolProvider(symbolProvider) + .integrations(integrations) + .runtimeClientPlugins(runtimePlugins) + .applicationProtocol(applicationProtocol) + .build()); + })); + }); + }); + }); writer.popState(); }); } - writer.popState(); }); } diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/TypeScriptDependency.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/TypeScriptDependency.java index dbdbab0a99b..0faaff2c523 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/TypeScriptDependency.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/TypeScriptDependency.java @@ -124,7 +124,6 @@ public enum TypeScriptDependency implements Dependency { // Conditionally added when @aws.auth#sigv4 is used SIGNATURE_V4("dependencies", "@smithy/signature-v4", false), - // feat(experimentalIdentityAndAuth): Conditionally added dependencies for `experimentalIdentityAndAuth`. // This package should never have a major version, and should only use minor and patch versions in development. // Exports are located between @smithy/types and @smithy/core @Deprecated EXPERIMENTAL_IDENTITY_AND_AUTH("dependencies", "@smithy/experimental-identity-and-auth", false), diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/TypeScriptSettings.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/TypeScriptSettings.java index a64da907a3d..0ed8bff53d7 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/TypeScriptSettings.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/TypeScriptSettings.java @@ -57,7 +57,7 @@ public final class TypeScriptSettings { private static final String PRIVATE = "private"; private static final String PACKAGE_MANAGER = "packageManager"; private static final String CREATE_DEFAULT_README = "createDefaultReadme"; - private static final String EXPERIMENTAL_IDENTITY_AND_AUTH = "experimentalIdentityAndAuth"; + private static final String USE_LEGACY_AUTH = "useLegacyAuth"; private static final String GENERATE_TYPEDOC = "generateTypeDoc"; private String packageName; @@ -75,7 +75,7 @@ public final class TypeScriptSettings { RequiredMemberMode.NULLABLE; private PackageManager packageManager = PackageManager.YARN; private boolean createDefaultReadme = false; - private boolean experimentalIdentityAndAuth = false; + private boolean useLegacyAuth = false; private boolean generateTypeDoc = false; @Deprecated @@ -110,8 +110,8 @@ public static TypeScriptSettings from(Model model, ObjectNode config, ArtifactTy settings.setPrivate(config.getBooleanMember(PRIVATE).map(BooleanNode::getValue).orElse(false)); settings.setCreateDefaultReadme( config.getBooleanMember(CREATE_DEFAULT_README).map(BooleanNode::getValue).orElse(false)); - settings.setExperimentalIdentityAndAuth( - config.getBooleanMemberOrDefault(EXPERIMENTAL_IDENTITY_AND_AUTH, false)); + settings.useLegacyAuth( + config.getBooleanMemberOrDefault(USE_LEGACY_AUTH, false)); settings.setGenerateTypeDoc( config.getBooleanMember(GENERATE_TYPEDOC).map(BooleanNode::getValue).orElse(false)); settings.setPackageManager( @@ -360,28 +360,27 @@ public void setPackageManager(PackageManager packageManager) { } /** - * Returns whether to use experimental identity and auth. + * Returns whether to use legacy auth integrations. * - * @return if experimental identity and auth should used. Default: false + * @return if legacy auth should used. Default: false */ - public boolean getExperimentalIdentityAndAuth() { - return experimentalIdentityAndAuth; + public boolean useLegacyAuth() { + return useLegacyAuth; } /** - * Sets whether experimental identity and auth should be used. + * Sets whether legacy auth should be used. * - * @param experimentalIdentityAndAuth whether experimental identity and auth should be used. + * @param useLegacyAuth whether legacy auth should be used. */ - public void setExperimentalIdentityAndAuth(boolean experimentalIdentityAndAuth) { - if (experimentalIdentityAndAuth) { + public void useLegacyAuth(boolean useLegacyAuth) { + if (useLegacyAuth) { LOGGER.warning(""" - Experimental identity and auth is in development, and is subject to \ - breaking changes. Behavior may NOT have the same feature parity as \ - non-experimental behavior. This setting is also subject to removal \ - when the feature is completed."""); + Legacy auth is considered deprecated and is no longer in development, + and should only be used for backward compatibility concerns. Consider + migrating to the default identity and auth behavior."""); } - this.experimentalIdentityAndAuth = experimentalIdentityAndAuth; + this.useLegacyAuth = useLegacyAuth; } /** @@ -490,7 +489,7 @@ public enum ArtifactType { CLIENT(SymbolVisitor::new, Arrays.asList(PACKAGE, PACKAGE_DESCRIPTION, PACKAGE_JSON, PACKAGE_VERSION, PACKAGE_MANAGER, SERVICE, PROTOCOL, PRIVATE, REQUIRED_MEMBER_MODE, - CREATE_DEFAULT_README, EXPERIMENTAL_IDENTITY_AND_AUTH, GENERATE_TYPEDOC)), + CREATE_DEFAULT_README, USE_LEGACY_AUTH, GENERATE_TYPEDOC)), SSDK((m, s) -> new ServerSymbolVisitor(m, new SymbolVisitor(m, s)), Arrays.asList(PACKAGE, PACKAGE_DESCRIPTION, PACKAGE_JSON, PACKAGE_VERSION, PACKAGE_MANAGER, SERVICE, PROTOCOL, PRIVATE, REQUIRED_MEMBER_MODE, diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/ConfigField.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/ConfigField.java index 50a53478544..e99965ab3a1 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/ConfigField.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/ConfigField.java @@ -19,7 +19,7 @@ /** * Definition of a Config field. * - * Currently used to populate the ClientDefaults interface in `experimentalIdentityAndAuth`. + * Currently used to populate the ClientDefaults interface. * * @param name name of the config field * @param type whether the config field is main or auxiliary diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/HttpAuthScheme.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/HttpAuthScheme.java index 2078c34171a..ce5607b1c3d 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/HttpAuthScheme.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/HttpAuthScheme.java @@ -22,7 +22,7 @@ import software.amazon.smithy.utils.ToSmithyBuilder; /** - * feat(experimentalIdentityAndAuth): Defines an HttpAuthScheme used in code generation. + * Defines an HttpAuthScheme used in code generation. * * HttpAuthScheme defines everything needed to generate an HttpAuthSchemeProvider, * HttpAuthOptions, and registered HttpAuthSchemes in the IdentityProviderConfiguration. diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/HttpAuthSchemeParameter.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/HttpAuthSchemeParameter.java index 7c7c58d89bb..e83fed5bdf5 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/HttpAuthSchemeParameter.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/HttpAuthSchemeParameter.java @@ -14,7 +14,7 @@ /** * Definition of an HttpAuthSchemeParameter. * - * Currently this is used to generate the the HttpAuthSchemeParameters interface in `experimentalIdentityAndAuth`. + * Currently this is used to generate the the HttpAuthSchemeParameters interface. * * @param name name of the auth scheme parameter * @param type writer for the type of the auth scheme parameter diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/HttpAuthSchemeProviderGenerator.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/HttpAuthSchemeProviderGenerator.java index fa629113874..32bdc2c8218 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/HttpAuthSchemeProviderGenerator.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/HttpAuthSchemeProviderGenerator.java @@ -41,7 +41,7 @@ import software.amazon.smithy.utils.StringUtils; /** - * feat(experimentalIdentityAndAuth): Generator for {@code HttpAuthSchemeProvider} and corresponding interfaces. + * Generator for {@code HttpAuthSchemeProvider} and corresponding interfaces. * * Code generated includes: * diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/SupportedHttpAuthSchemesIndex.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/SupportedHttpAuthSchemesIndex.java index 333d2f70c76..cc51c7b2c04 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/SupportedHttpAuthSchemesIndex.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/SupportedHttpAuthSchemesIndex.java @@ -20,9 +20,6 @@ * * Integrations may mutate this index to customize {@link HttpAuthScheme} * implementations. - * - * This class is currently under the `experimentalIdentityAgitndAuth` experimental - * flag, and is subject to breaking changes. */ @SmithyInternalApi public final class SupportedHttpAuthSchemesIndex { diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/integration/AddHttpAuthSchemePlugin.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/integration/AddHttpAuthSchemePlugin.java index bcb0db1a66d..30b4775b0eb 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/integration/AddHttpAuthSchemePlugin.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/integration/AddHttpAuthSchemePlugin.java @@ -33,8 +33,7 @@ import software.amazon.smithy.typescript.codegen.integration.RuntimeClientPlugin; import software.amazon.smithy.typescript.codegen.integration.RuntimeClientPlugin.Convention; import software.amazon.smithy.typescript.codegen.sections.ClientBodyExtraCodeSection; -import software.amazon.smithy.utils.CodeInterceptor; -import software.amazon.smithy.utils.CodeSection; +import software.amazon.smithy.typescript.codegen.util.ClientWriterConsumer; import software.amazon.smithy.utils.SmithyInternalApi; /** @@ -43,15 +42,19 @@ @SmithyInternalApi public final class AddHttpAuthSchemePlugin implements HttpAuthTypeScriptIntegration { /** - * Integration should only be used if `experimentalIdentityAndAuth` flag is true. + * Integration should be skipped if the `useLegacyAuth` flag is true. */ @Override public boolean matchesSettings(TypeScriptSettings settings) { - return settings.getExperimentalIdentityAndAuth(); + return !settings.useLegacyAuth(); } @Override public List getClientPlugins() { + Map httpAuthSchemeParametersProvider = Map.of( + "httpAuthSchemeParametersProvider", AddHttpAuthSchemePlugin::httpAuthSchemeParametersProvider, + "identityProviderConfigProvider", AddHttpAuthSchemePlugin::identityProviderConfigProvider + ); return List.of( RuntimeClientPlugin.builder() .servicePredicate((m, s) -> s.hasTrait(EndpointRuleSetTrait.ID)) @@ -59,14 +62,7 @@ public List getClientPlugins() { TypeScriptDependency.SMITHY_CORE.dependency, "HttpAuthSchemeEndpointRuleSet", Convention.HAS_MIDDLEWARE) - .additionalPluginFunctionParamsSupplier((model, service, operation) -> Map.of( - "httpAuthSchemeParametersProvider", Symbol.builder() - .name("this.getDefaultHttpAuthSchemeParametersProvider()") - .build(), - "identityProviderConfigProvider", Symbol.builder() - .name("this.getIdentityProviderConfigProvider()") - .build() - )) + .withAdditionalClientParams(httpAuthSchemeParametersProvider) .build(), RuntimeClientPlugin.builder() .servicePredicate((m, s) -> !s.hasTrait(EndpointRuleSetTrait.ID)) @@ -74,14 +70,7 @@ public List getClientPlugins() { TypeScriptDependency.SMITHY_CORE.dependency, "HttpAuthScheme", Convention.HAS_MIDDLEWARE) - .additionalPluginFunctionParamsSupplier((model, service, operation) -> Map.of( - "httpAuthSchemeParametersProvider", Symbol.builder() - .name("this.getDefaultHttpAuthSchemeParametersProvider()") - .build(), - "identityProviderConfigProvider", Symbol.builder() - .name("this.getIdentityProviderConfigProvider()") - .build() - )) + .withAdditionalClientParams(httpAuthSchemeParametersProvider) .build(), RuntimeClientPlugin.builder() .inputConfig(Symbol.builder() @@ -100,74 +89,10 @@ public List getClientPlugins() { ); } - @Override - public List> interceptors( - TypeScriptCodegenContext codegenContext - ) { - return List.of(CodeInterceptor.appender(ClientBodyExtraCodeSection.class, (w, s) -> { - if (!s.getSettings().generateClient() - || !s.getSettings().getExperimentalIdentityAndAuth() - || !s.getApplicationProtocol().isHttpProtocol()) { - return; - } - - /* - private getDefaultHttpAuthSchemeParametersProvider() { - return defaultWeatherHttpAuthSchemeParametersProvider; - } - */ - w.openBlock("private getDefaultHttpAuthSchemeParametersProvider() {", "}", () -> { - String httpAuthSchemeParametersProviderName = "default" - + CodegenUtils.getServiceName(s.getSettings(), s.getModel(), s.getSymbolProvider()) - + "HttpAuthSchemeParametersProvider"; - w.addImport(httpAuthSchemeParametersProviderName, null, AuthUtils.AUTH_HTTP_PROVIDER_DEPENDENCY); - w.write("return " + httpAuthSchemeParametersProviderName + ";"); - }); - - /* - private getIdentityProviderConfigProvider() { - return async (config: WeatherClientResolvedConfig) => new DefaultIdentityProviderConfig({ - "aws.auth#sigv4": config.credentials, - "smithy.api#httpApiKeyAuth": config.apiKey, - "smithy.api#httpBearerAuth": config.token, - }); - } - */ - w.openBlock("private getIdentityProviderConfigProvider() {", "}", () -> { - w.addDependency(TypeScriptDependency.SMITHY_CORE); - w.addImport("DefaultIdentityProviderConfig", null, TypeScriptDependency.SMITHY_CORE); - w.openBlock(""" - return async (config: $LResolvedConfig) => \ - new DefaultIdentityProviderConfig({""", "});", - s.getSymbolProvider().toSymbol(s.getService()).getName(), - () -> { - SupportedHttpAuthSchemesIndex authIndex = new SupportedHttpAuthSchemesIndex( - s.getIntegrations(), - s.getModel(), - s.getSettings()); - ServiceIndex serviceIndex = ServiceIndex.of(s.getModel()); - TopDownIndex topDownIndex = TopDownIndex.of(s.getModel()); - Map httpAuthSchemes = AuthUtils.getAllEffectiveNoAuthAwareAuthSchemes( - s.getService(), serviceIndex, authIndex, topDownIndex); - for (HttpAuthScheme scheme : httpAuthSchemes.values()) { - if (scheme == null) { - continue; - } - for (ConfigField configField : scheme.getConfigFields()) { - if (configField.type().equals(ConfigField.Type.MAIN)) { - w.write("$S: config.$L,", scheme.getSchemeId().toString(), configField.name()); - } - } - } - }); - }); - })); - } - @Override public void customize(TypeScriptCodegenContext codegenContext) { if (!codegenContext.settings().generateClient() - || !codegenContext.settings().getExperimentalIdentityAndAuth() + || codegenContext.settings().useLegacyAuth() || !codegenContext.applicationProtocol().isHttpProtocol()) { return; } @@ -217,6 +142,71 @@ public void customize(TypeScriptCodegenContext codegenContext) { }); } + /** + * Writes the httpAuthSchemeParametersProvider for input to middleware additional parameters. + * Example: + * ```typescript + * defaultWeatherHttpAuthSchemeParametersProvider; + * ``` + */ + private static void httpAuthSchemeParametersProvider(TypeScriptWriter w, + ClientBodyExtraCodeSection clientBodySection) { + String httpAuthSchemeParametersProviderName = "default" + + CodegenUtils.getServiceName( + clientBodySection.getSettings(), + clientBodySection.getModel(), + clientBodySection.getSymbolProvider() + ) + + "HttpAuthSchemeParametersProvider"; + w.addImport(httpAuthSchemeParametersProviderName, null, AuthUtils.AUTH_HTTP_PROVIDER_DEPENDENCY); + w.writeInline(httpAuthSchemeParametersProviderName); + } + + /** + * Writes the identityProviderConfigProvider for input to middleware additional parameters. + * Example: + * ```typescript + * async (config: WeatherClientResolvedConfig) => new DefaultIdentityProviderConfig({ + * "aws.auth#sigv4": config.credentials, + * "smithy.api#httpApiKeyAuth": config.apiKey, + * "smithy.api#httpBearerAuth": config.token, + * }) + * ``` + */ + private static void identityProviderConfigProvider(TypeScriptWriter w, + ClientBodyExtraCodeSection s) { + w.addDependency(TypeScriptDependency.SMITHY_CORE); + w.addImport("DefaultIdentityProviderConfig", null, TypeScriptDependency.SMITHY_CORE); + w.openBlock(""" + async (config: $LResolvedConfig) => \ + new DefaultIdentityProviderConfig({""", "})", + s.getSymbolProvider().toSymbol(s.getService()).getName(), + () -> { + SupportedHttpAuthSchemesIndex authIndex = new SupportedHttpAuthSchemesIndex( + s.getIntegrations(), + s.getModel(), + s.getSettings()); + ServiceIndex serviceIndex = ServiceIndex.of(s.getModel()); + TopDownIndex topDownIndex = TopDownIndex.of(s.getModel()); + Map httpAuthSchemes = AuthUtils.getAllEffectiveNoAuthAwareAuthSchemes( + s.getService(), serviceIndex, authIndex, topDownIndex); + for (HttpAuthScheme scheme : httpAuthSchemes.values()) { + if (scheme == null) { + continue; + } + for (ConfigField configField : scheme.getConfigFields()) { + if (configField.type().equals(ConfigField.Type.MAIN)) { + w.writeInline( + "$S: config.$L,", + scheme.getSchemeId().toString(), + configField.name() + ); + } + } + } + }); + } + /* export interface HttpAuthSchemeInputConfig { httpAuthSchemes?: HttpAuthScheme[]; @@ -260,14 +250,14 @@ private void generateHttpAuthSchemeInputConfigInterface( w.addDependency(TypeScriptDependency.SMITHY_TYPES); w.addImport("HttpAuthScheme", null, TypeScriptDependency.SMITHY_TYPES); w.writeDocs(""" - experimentalIdentityAndAuth: Configuration of HttpAuthSchemes for a client which provides \ + Configuration of HttpAuthSchemes for a client which provides \ default identity providers and signers per auth scheme. @internal"""); w.write("httpAuthSchemes?: HttpAuthScheme[];\n"); String httpAuthSchemeProviderName = serviceName + "HttpAuthSchemeProvider"; w.writeDocs(""" - experimentalIdentityAndAuth: Configuration of an HttpAuthSchemeProvider for a client which \ + Configuration of an HttpAuthSchemeProvider for a client which \ resolves which HttpAuthScheme to use. @internal"""); w.write("httpAuthSchemeProvider?: $L;\n", httpAuthSchemeProviderName); @@ -326,14 +316,14 @@ private void generateHttpAuthSchemeResolvedConfigInterface( w.addDependency(TypeScriptDependency.SMITHY_TYPES); w.addImport("HttpAuthScheme", null, TypeScriptDependency.SMITHY_TYPES); w.writeDocs(""" - experimentalIdentityAndAuth: Configuration of HttpAuthSchemes for a client which provides \ + Configuration of HttpAuthSchemes for a client which provides \ default identity providers and signers per auth scheme. @internal"""); w.write("readonly httpAuthSchemes: HttpAuthScheme[];\n"); String httpAuthSchemeProviderName = serviceName + "HttpAuthSchemeProvider"; w.writeDocs(""" - experimentalIdentityAndAuth: Configuration of an HttpAuthSchemeProvider for a client which \ + Configuration of an HttpAuthSchemeProvider for a client which \ resolves which HttpAuthScheme to use. @internal"""); w.write("readonly httpAuthSchemeProvider: $L;\n", httpAuthSchemeProviderName); diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/integration/AddHttpSigningPlugin.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/integration/AddHttpSigningPlugin.java index fbdc5c99223..9b8a43e258d 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/integration/AddHttpSigningPlugin.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/integration/AddHttpSigningPlugin.java @@ -16,17 +16,15 @@ /** * Add middleware for {@code httpSigningMiddleware}. - * - * This is the experimental behavior for `experimentalIdentityAndAuth`. */ @SmithyInternalApi public class AddHttpSigningPlugin implements TypeScriptIntegration { /** - * Integration should only be used if `experimentalIdentityAndAuth` flag is true. + * Integration should be skipped if the `useLegacyAuth` flag is true. */ @Override public boolean matchesSettings(TypeScriptSettings settings) { - return settings.getExperimentalIdentityAndAuth(); + return !settings.useLegacyAuth(); } @Override diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/integration/HttpAuthExtensionConfigurationInterface.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/integration/HttpAuthExtensionConfigurationInterface.java index db90da40c42..c91190a0b43 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/integration/HttpAuthExtensionConfigurationInterface.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/integration/HttpAuthExtensionConfigurationInterface.java @@ -13,8 +13,6 @@ /** * Adds the corresponding interface and functions for {@code HttpAuthExtensionConfiguration}. - * - * This is experimental for `experimentalIdentityAndAuth`. */ @SmithyInternalApi public class HttpAuthExtensionConfigurationInterface implements ExtensionConfigurationInterface { diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/integration/HttpAuthRuntimeExtensionIntegration.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/integration/HttpAuthRuntimeExtensionIntegration.java index ea39877ae3b..d3a0481d914 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/integration/HttpAuthRuntimeExtensionIntegration.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/integration/HttpAuthRuntimeExtensionIntegration.java @@ -28,18 +28,16 @@ /** * Adds {@link HttpAuthExtensionConfigurationInterface} to a client. - * - * This is the experimental behavior for `experimentalIdentityAndAuth`. */ @SmithyInternalApi public class HttpAuthRuntimeExtensionIntegration implements TypeScriptIntegration { /** - * Integration should only be used if `experimentalIdentityAndAuth` flag is true. + * Integration should be skipped if the `useLegacyAuth` flag is true. */ @Override public boolean matchesSettings(TypeScriptSettings settings) { - return settings.getExperimentalIdentityAndAuth(); + return !settings.useLegacyAuth(); } @Override diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/integration/HttpAuthTypeScriptIntegration.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/integration/HttpAuthTypeScriptIntegration.java index 77d4006972a..bbd936eef52 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/integration/HttpAuthTypeScriptIntegration.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/integration/HttpAuthTypeScriptIntegration.java @@ -14,15 +14,13 @@ import software.amazon.smithy.utils.SmithyInternalApi; /** - * Java SPI for customizing TypeScript code generation for `experimentalIdentityAndAuth`. - * - * This should NOT be used as it is highly susceptible to breaking changes. + * Java SPI for customizing TypeScript code generation for Identity and Authentication. */ @SmithyInternalApi public interface HttpAuthTypeScriptIntegration extends TypeScriptIntegration { /** - * feat(experimentalIdentityAndAuth): Register an {@link HttpAuthScheme} that is used to generate the - * {@code HttpAuthSchemeProvider} and corresponding config field and runtime config values. + * Register an {@link HttpAuthScheme} that is used to generate the {@code HttpAuthSchemeProvider} + * and corresponding config field and runtime config values. * @return an empty optional. */ default Optional getHttpAuthScheme() { @@ -30,8 +28,8 @@ default Optional getHttpAuthScheme() { } /** - * feat(experimentalIdentityAndAuth): Mutate an {@link SupportedHttpAuthSchemesIndex} to mutate registered - * {@link HttpAuthScheme}s, e.g. default {@code IdentityProvider}s and {@code HttpSigner}s. + * Mutate an {@link SupportedHttpAuthSchemesIndex} to mutate registered {@link HttpAuthScheme}s, + * e.g. default {@code IdentityProvider}s and {@code HttpSigner}s. * @param supportedHttpAuthSchemesIndex index to mutate. * @param model model * @param settings settings diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/integration/SupportHttpApiKeyAuth.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/integration/SupportHttpApiKeyAuth.java index 00b32335122..8ce8d9db999 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/integration/SupportHttpApiKeyAuth.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/integration/SupportHttpApiKeyAuth.java @@ -23,8 +23,6 @@ /** * Support for @httpApiKeyAuth. - * - * This is the experimental behavior for `experimentalIdentityAndAuth`. */ @SmithyInternalApi public class SupportHttpApiKeyAuth implements HttpAuthTypeScriptIntegration { @@ -51,11 +49,11 @@ public class SupportHttpApiKeyAuth implements HttpAuthTypeScriptIntegration { .build(); /** - * Integration should only be used if `experimentalIdentityAndAuth` flag is true. + * Integration should be skipped if the `useLegacyAuth` flag is true. */ @Override public boolean matchesSettings(TypeScriptSettings settings) { - return settings.getExperimentalIdentityAndAuth(); + return !settings.useLegacyAuth(); } @Override diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/integration/SupportHttpBearerAuth.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/integration/SupportHttpBearerAuth.java index f5ff5d94482..0879f3e7c5d 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/integration/SupportHttpBearerAuth.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/integration/SupportHttpBearerAuth.java @@ -21,8 +21,6 @@ /** * Support for @httpBearerAuth. - * - * This is the experimental behavior for `experimentalIdentityAndAuth`. */ @SmithyInternalApi public final class SupportHttpBearerAuth implements HttpAuthTypeScriptIntegration { @@ -44,11 +42,11 @@ public final class SupportHttpBearerAuth implements HttpAuthTypeScriptIntegratio .build(); /** - * Integration should only be used if `experimentalIdentityAndAuth` flag is true. + * Integration should be skipped if the `useLegacyAuth` flag is true. */ @Override public boolean matchesSettings(TypeScriptSettings settings) { - return settings.getExperimentalIdentityAndAuth(); + return !settings.useLegacyAuth(); } @Override diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/integration/SupportNoAuth.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/integration/SupportNoAuth.java index 5025c26b18c..0c86191c808 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/integration/SupportNoAuth.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/auth/http/integration/SupportNoAuth.java @@ -32,11 +32,11 @@ public final class SupportNoAuth implements HttpAuthTypeScriptIntegration { .build()); /** - * Integration should only be used if `experimentalIdentityAndAuth` flag is true. + * Integration should be skipped if the `useLegacyAuth` flag is true. */ @Override public boolean matchesSettings(TypeScriptSettings settings) { - return settings.getExperimentalIdentityAndAuth(); + return !settings.useLegacyAuth(); } @Override diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/AddEventStreamDependency.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/AddEventStreamDependency.java index 03144e11a93..ab8df8808a2 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/AddEventStreamDependency.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/AddEventStreamDependency.java @@ -44,6 +44,13 @@ @SmithyInternalApi public final class AddEventStreamDependency implements TypeScriptIntegration { + @Override + public List runAfter() { + return List.of( + new AddBuiltinPlugins().name() + ); + } + @Override public List getClientPlugins() { return ListUtils.of( diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/AddHttpApiKeyAuthPlugin.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/AddHttpApiKeyAuthPlugin.java index 40e8cf54ed6..a40cf61acbb 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/AddHttpApiKeyAuthPlugin.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/AddHttpApiKeyAuthPlugin.java @@ -30,7 +30,7 @@ /** * Add config and middleware to support a service with the @httpApiKeyAuth trait. * - * This is the existing control behavior for `experimentalIdentityAndAuth`. + * This is legacy auth behavior, and is no longer in development. */ @SmithyInternalApi public final class AddHttpApiKeyAuthPlugin implements TypeScriptIntegration { @@ -38,11 +38,11 @@ public final class AddHttpApiKeyAuthPlugin implements TypeScriptIntegration { public static final String INTEGRATION_NAME = "HttpApiKeyAuth"; /** - * Integration should only be used if `experimentalIdentityAndAuth` flag is false. + * Integration should be used only if the `useLegacyAuth` flag is true. */ @Override public boolean matchesSettings(TypeScriptSettings settings) { - return !settings.getExperimentalIdentityAndAuth(); + return settings.useLegacyAuth(); } /** diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/RuntimeClientPlugin.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/RuntimeClientPlugin.java index c48f730c4ad..04adc6cb21a 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/RuntimeClientPlugin.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/RuntimeClientPlugin.java @@ -15,6 +15,7 @@ package software.amazon.smithy.typescript.codegen.integration; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Objects; @@ -29,6 +30,8 @@ import software.amazon.smithy.model.shapes.ServiceShape; import software.amazon.smithy.typescript.codegen.TypeScriptDependency; import software.amazon.smithy.typescript.codegen.TypeScriptSettings; +import software.amazon.smithy.typescript.codegen.util.ClientWriterConsumer; +import software.amazon.smithy.typescript.codegen.util.CommandWriterConsumer; import software.amazon.smithy.utils.SmithyBuilder; import software.amazon.smithy.utils.SmithyUnstableApi; import software.amazon.smithy.utils.StringUtils; @@ -56,6 +59,8 @@ public final class RuntimeClientPlugin implements ToSmithyBuilder servicePredicate; private final OperationPredicate operationPredicate; private final SettingsPredicate settingsPredicate; + private final Map writeAdditionalClientParams; + private final Map writeAdditionalOperationParams; private RuntimeClientPlugin(Builder builder) { inputConfig = builder.inputConfig; @@ -68,6 +73,8 @@ private RuntimeClientPlugin(Builder builder) { operationPredicate = builder.operationPredicate; servicePredicate = builder.servicePredicate; settingsPredicate = builder.settingsPredicate; + writeAdditionalClientParams = builder.writeAdditionalClientParams; + writeAdditionalOperationParams = builder.writeAdditionalOperationParams; boolean allNull = (inputConfig == null) && (resolvedConfig == null) && (resolveFunction == null); boolean allSet = (inputConfig != null) && (resolvedConfig != null) && (resolveFunction != null); @@ -258,7 +265,30 @@ public Map getAdditionalPluginFunctionParameters( if (additionalPluginFunctionParamsSupplier != null) { return additionalPluginFunctionParamsSupplier.apply(model, service, operation); } - return new HashMap(); + return new HashMap<>(); + } + + /** + * Gets a list of additional parameters to be supplied to the + * plugin function. These parameters are to be supplied to plugin + * function as second argument. The map is empty if there are + * no additional parameters. + * + * @param model Model the operation belongs to. + * @param service Service the operation belongs to. + * @param operation Operation to test against. + * @return Returns the optionally present map of parameters. The key is the key + * for a parameter, and value is the value for a parameter. + */ + public Map getAdditionalPluginFunctionParameterWriterConsumers( + Model model, + ServiceShape service, + OperationShape operation + ) { + if (additionalPluginFunctionParamsSupplier != null) { + return additionalPluginFunctionParamsSupplier.apply(model, service, operation); + } + return new HashMap<>(); } /** @@ -326,6 +356,22 @@ public boolean matchesSettings(Model model, ServiceShape service, TypeScriptSett return settingsPredicate.test(model, service, settings); } + /** + * @return the map of additional client level plugin params and their writer consumers used + * to populate the param values. + */ + public Map getClientAddParamsWriterConsumers() { + return this.writeAdditionalClientParams; + } + + /** + * @return the map of additional operation level plugin params and their writer consumers used + * to populate the param values. + */ + public Map getOperationAddParamsWriterConsumers() { + return this.writeAdditionalOperationParams; + } + public static Builder builder() { return new Builder(); } @@ -398,6 +444,8 @@ public static final class Builder implements SmithyBuilder private BiPredicate servicePredicate = (model, service) -> true; private OperationPredicate operationPredicate = (model, service, operation) -> false; private SettingsPredicate settingsPredicate = (model, service, settings) -> true; + private Map writeAdditionalClientParams = Collections.emptyMap(); + private Map writeAdditionalOperationParams = Collections.emptyMap(); @Override public RuntimeClientPlugin build() { @@ -746,6 +794,24 @@ public Builder servicePredicate(BiPredicate servicePredicat return this; } + /** + * Enables access to the writer for adding imports/dependencies. + */ + public Builder withAdditionalClientParams(Map writeAdditionalClientParams) { + this.writeAdditionalClientParams = writeAdditionalClientParams; + return this; + } + + /** + * Enables access to the writer for adding imports/dependencies. + */ + public Builder withAdditionalOperationParams( + Map writeAdditionalOperationParams + ) { + this.writeAdditionalOperationParams = writeAdditionalOperationParams; + return this; + } + /** * Configures various aspects of the builder based on naming conventions * defined by the provided {@link Convention} values. diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/TypeScriptIntegration.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/TypeScriptIntegration.java index 83dd240eee1..75dda21d0e1 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/TypeScriptIntegration.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/TypeScriptIntegration.java @@ -64,6 +64,13 @@ default List getClientPlugins() { return Collections.emptyList(); } + /** + * Mutates in place the loaded list of plugins to apply to the generated client. + */ + default void mutateClientPlugins(List plugins) { + // defaults to no mutation + } + /** * Gets a list of protocol generators to register. * diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/sections/PreCommandClassCodeSection.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/sections/PreCommandClassCodeSection.java new file mode 100644 index 00000000000..06b3aa6317f --- /dev/null +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/sections/PreCommandClassCodeSection.java @@ -0,0 +1,135 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package software.amazon.smithy.typescript.codegen.sections; + +import java.util.List; +import java.util.Optional; +import software.amazon.smithy.codegen.core.SymbolProvider; +import software.amazon.smithy.model.Model; +import software.amazon.smithy.model.shapes.OperationShape; +import software.amazon.smithy.model.shapes.ServiceShape; +import software.amazon.smithy.typescript.codegen.ApplicationProtocol; +import software.amazon.smithy.typescript.codegen.TypeScriptSettings; +import software.amazon.smithy.typescript.codegen.integration.ProtocolGenerator; +import software.amazon.smithy.typescript.codegen.integration.RuntimeClientPlugin; +import software.amazon.smithy.utils.CodeSection; +import software.amazon.smithy.utils.SmithyBuilder; +import software.amazon.smithy.utils.SmithyUnstableApi; + +@SmithyUnstableApi +public final class PreCommandClassCodeSection implements CodeSection { + private final TypeScriptSettings settings; + private final Model model; + private final ServiceShape service; + private final OperationShape operation; + private final SymbolProvider symbolProvider; + private final List runtimeClientPlugins; + private final ProtocolGenerator protocolGenerator; + private final ApplicationProtocol applicationProtocol; + + private PreCommandClassCodeSection(Builder builder) { + settings = SmithyBuilder.requiredState("settings", builder.settings); + model = SmithyBuilder.requiredState("model", builder.model); + service = SmithyBuilder.requiredState("service", builder.service); + operation = SmithyBuilder.requiredState("operation", builder.operation); + symbolProvider = SmithyBuilder.requiredState("symbolProvider", builder.symbolProvider); + runtimeClientPlugins = SmithyBuilder.requiredState("runtimeClientPlugins", builder.runtimeClientPlugins); + protocolGenerator = builder.protocolGenerator; + applicationProtocol = SmithyBuilder.requiredState("applicationProtocol", builder.applicationProtocol); + } + + public static Builder builder() { + return new Builder(); + } + + public TypeScriptSettings getSettings() { + return settings; + } + + public Model getModel() { + return model; + } + + public ServiceShape getService() { + return service; + } + + public OperationShape getOperation() { + return operation; + } + + public SymbolProvider getSymbolProvider() { + return symbolProvider; + } + + public List getRuntimeClientPlugins() { + return runtimeClientPlugins; + } + + public Optional getProtocolGenerator() { + return Optional.ofNullable(protocolGenerator); + } + + public ApplicationProtocol getApplicationProtocol() { + return applicationProtocol; + } + + public static class Builder implements SmithyBuilder { + private TypeScriptSettings settings; + private Model model; + private ServiceShape service; + private OperationShape operation; + private SymbolProvider symbolProvider; + private List runtimeClientPlugins; + private ProtocolGenerator protocolGenerator; + private ApplicationProtocol applicationProtocol; + + @Override + public PreCommandClassCodeSection build() { + return new PreCommandClassCodeSection(this); + } + + public Builder settings(TypeScriptSettings settings) { + this.settings = settings; + return this; + } + + public Builder model(Model model) { + this.model = model; + return this; + } + + public Builder service(ServiceShape service) { + this.service = service; + return this; + } + + public Builder operation(OperationShape operation) { + this.operation = operation; + return this; + } + + public Builder symbolProvider(SymbolProvider symbolProvider) { + this.symbolProvider = symbolProvider; + return this; + } + + public Builder runtimeClientPlugins(List runtimeClientPlugins) { + this.runtimeClientPlugins = runtimeClientPlugins; + return this; + } + + public Builder protocolGenerator(ProtocolGenerator protocolGenerator) { + this.protocolGenerator = protocolGenerator; + return this; + } + + public Builder applicationProtocol(ApplicationProtocol applicationProtocol) { + this.applicationProtocol = applicationProtocol; + return this; + } + } +} diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/util/ClientWriterConsumer.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/util/ClientWriterConsumer.java new file mode 100644 index 00000000000..62290dcfe7b --- /dev/null +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/util/ClientWriterConsumer.java @@ -0,0 +1,20 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package software.amazon.smithy.typescript.codegen.util; + +import software.amazon.smithy.typescript.codegen.TypeScriptWriter; +import software.amazon.smithy.typescript.codegen.sections.ClientBodyExtraCodeSection; +import software.amazon.smithy.utils.SmithyInternalApi; + +/** + * The writer consumer for a RuntimeClientPlugin. May be used to add imports and dependencies + * used by the plugin at the client level. + */ +@FunctionalInterface +@SmithyInternalApi +public interface ClientWriterConsumer { + void accept(TypeScriptWriter writer, ClientBodyExtraCodeSection section); +} diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/util/CommandWriterConsumer.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/util/CommandWriterConsumer.java new file mode 100644 index 00000000000..1eed5a9db8a --- /dev/null +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/util/CommandWriterConsumer.java @@ -0,0 +1,20 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package software.amazon.smithy.typescript.codegen.util; + +import software.amazon.smithy.typescript.codegen.TypeScriptWriter; +import software.amazon.smithy.typescript.codegen.sections.CommandConstructorCodeSection; +import software.amazon.smithy.utils.SmithyInternalApi; + +/** + * The writer consumer for a RuntimeClientPlugin. May be used to add imports and dependencies + * used by the plugin at the command level. + */ +@FunctionalInterface +@SmithyInternalApi +public interface CommandWriterConsumer { + void accept(TypeScriptWriter writer, CommandConstructorCodeSection section); +} diff --git a/smithy-typescript-codegen/src/test/java/software/amazon/smithy/typescript/codegen/integration/AddHttpApiKeyAuthPluginTest.java b/smithy-typescript-codegen/src/test/java/software/amazon/smithy/typescript/codegen/integration/AddHttpApiKeyAuthPluginTest.java index 231936fc864..c28295d8708 100644 --- a/smithy-typescript-codegen/src/test/java/software/amazon/smithy/typescript/codegen/integration/AddHttpApiKeyAuthPluginTest.java +++ b/smithy-typescript-codegen/src/test/java/software/amazon/smithy/typescript/codegen/integration/AddHttpApiKeyAuthPluginTest.java @@ -32,20 +32,20 @@ public class AddHttpApiKeyAuthPluginTest { @Test public void httpApiKeyAuthClientOnService() { testInjects("http-api-key-auth-trait.smithy", - ", { in: 'header', name: 'Authorization', scheme: 'ApiKey' }"); + "in: 'header', name: 'Authorization', scheme: 'ApiKey'"); } @Test public void httpApiKeyAuthClientOnOperation() { testInjects("http-api-key-auth-trait-on-operation.smithy", - ", { in: 'header', name: 'Authorization', scheme: 'ApiKey' }"); + "in: 'header', name: 'Authorization', scheme: 'ApiKey'"); } // This should be identical to the httpApiKeyAuthClient test except for the parameters provided // to the middleware. @Test public void httpApiKeyAuthClientNoScheme() { - testInjects("http-api-key-auth-trait-no-scheme.smithy", ", { in: 'header', name: 'Authorization' }"); + testInjects("http-api-key-auth-trait-no-scheme.smithy", "in: 'header', name: 'Authorization'"); } private void testInjects(String filename, String extra) { @@ -60,8 +60,10 @@ private void testInjects(String filename, String extra) { // Ensure that the GetFoo operation imports the middleware and uses it with all the options. assertThat(manifest.getFileString(CodegenUtils.SOURCE_FOLDER + "/commands/GetFooCommand.ts").get(), containsString("from \"../middleware/HttpApiKeyAuth\"")); - assertThat(manifest.getFileString(CodegenUtils.SOURCE_FOLDER + "/commands/GetFooCommand.ts").get(), - containsString("getHttpApiKeyAuthPlugin(config" + extra + ")")); + + String generatedGetFooCommand = manifest.getFileString(CodegenUtils.SOURCE_FOLDER + "/commands/GetFooCommand.ts").get(); + assertThat(generatedGetFooCommand, containsString("getHttpApiKeyAuthPlugin(config")); + assertThat(generatedGetFooCommand, containsString(extra)); // Ensure that the GetBar operation does not import the middleware or use it. assertThat(manifest.getFileString(CodegenUtils.SOURCE_FOLDER + "/commands/GetBarCommand.ts").get(), @@ -93,6 +95,7 @@ private MockManifest generate(String filename) .withMember("service", Node.from("smithy.example#Example")) .withMember("package", Node.from("example")) .withMember("packageVersion", Node.from("1.0.0")) + .withMember("useLegacyAuth", Node.from(true)) .build()) .build();