Skip to content

Commit

Permalink
feat(experimentalIdentityAndAuth): update code generation
Browse files Browse the repository at this point in the history
Make code generation changes for `experimentalIdentityAndAuth`.

Bug fixes:

- fix misused service name when importing the default auth scheme
  provider
- add generic type to resolve config function input and output

Updates:

- add remove methods to `HttpAuthScheme` builder
- update code generation for `ConfigField` (and more code sections)
- update `customizeSupportedHttpAuthSchemes()` to include model and
  settings
- add resolve functions codegen for `HttpAuthScheme`s
- update various `String` parameters to take `Symbol` instead
  • Loading branch information
Steven Yuan authored and syall committed Nov 21, 2023
1 parent 106487e commit 20acec0
Show file tree
Hide file tree
Showing 25 changed files with 1,491 additions and 406 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -213,13 +213,15 @@ private void generateHttpAuthSchemeConfig(
TypeScriptWriter writer,
LanguageTarget target
) {
SupportedHttpAuthSchemesIndex authIndex = new SupportedHttpAuthSchemesIndex(integrations);
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()
.name("default" + service.toShapeId().getName() + "HttpAuthSchemeProvider")
.name("default"
+ CodegenUtils.getServiceName(settings, model, symbolProvider)
+ "HttpAuthSchemeProvider")
.namespace(AuthUtils.AUTH_HTTP_PROVIDER_DEPENDENCY.getPackageName(), "/")
.build());
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
* Generates a bare-bones client and configuration for service using plugins.
*/
@SmithyInternalApi
final class ServiceBareBonesClientGenerator implements Runnable {
public final class ServiceBareBonesClientGenerator implements Runnable {

private final TypeScriptSettings settings;
private final Model model;
Expand Down Expand Up @@ -88,11 +88,11 @@ final class ServiceBareBonesClientGenerator implements Runnable {
resolvedConfigType = getResolvedConfigTypeName(symbol);
}

static String getConfigTypeName(Symbol symbol) {
public static String getConfigTypeName(Symbol symbol) {
return symbol.getName() + "Config";
}

static String getResolvedConfigTypeName(Symbol symbol) {
public static String getResolvedConfigTypeName(Symbol symbol) {
return symbol.getName() + "ResolvedConfig";
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,19 @@
import java.util.Map;
import java.util.TreeMap;
import software.amazon.smithy.codegen.core.CodegenException;
import software.amazon.smithy.codegen.core.Symbol;
import software.amazon.smithy.codegen.core.SymbolDependency;
import software.amazon.smithy.model.knowledge.ServiceIndex;
import software.amazon.smithy.model.knowledge.ServiceIndex.AuthSchemeMode;
import software.amazon.smithy.model.shapes.ServiceShape;
import software.amazon.smithy.model.shapes.ShapeId;
import software.amazon.smithy.model.traits.Trait;
import software.amazon.smithy.typescript.codegen.CodegenUtils;
import software.amazon.smithy.typescript.codegen.ConfigField;
import software.amazon.smithy.typescript.codegen.Dependency;
import software.amazon.smithy.typescript.codegen.auth.http.ConfigField;
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.ResolveConfigFunction;
import software.amazon.smithy.typescript.codegen.auth.http.SupportedHttpAuthSchemesIndex;
import software.amazon.smithy.utils.SmithyInternalApi;

Expand Down Expand Up @@ -110,7 +112,7 @@ public static Map<String, ConfigField> collectConfigFields(Collection<HttpAuthSc
if (configFields.containsKey(configField.name())) {
ConfigField existingConfigField = configFields.get(configField.name());
if (!configField.equals(existingConfigField)) {
throw new CodegenException("Contradicting `ConfigField` defintions for `"
throw new CodegenException("Contradicting `ConfigField` definitions for `"
+ configField.name()
+ "`; existing: "
+ existingConfigField
Expand All @@ -125,6 +127,34 @@ public static Map<String, ConfigField> collectConfigFields(Collection<HttpAuthSc
return configFields;
}

public static Map<Symbol, ResolveConfigFunction> collectResolveConfigFunctions(
Collection<HttpAuthScheme> httpAuthSchemes
) {
Map<Symbol, ResolveConfigFunction> resolveConfigFunctions = new HashMap<>();
for (HttpAuthScheme authScheme : httpAuthSchemes) {
if (authScheme == null) {
continue;
}
for (ResolveConfigFunction fn : authScheme.getResolveConfigFunctions()) {
if (resolveConfigFunctions.containsKey(fn.resolveConfigFunction())) {
ResolveConfigFunction existingFn =
resolveConfigFunctions.get(fn.resolveConfigFunction());
if (!fn.equals(existingFn)) {
throw new CodegenException("Contradicting `ResolveConfigFunction` definitions for `"
+ fn.resolveConfigFunction()
+ "`; existing: "
+ existingFn
+ ", conflict: "
+ fn);
}
} else {
resolveConfigFunctions.put(fn.resolveConfigFunction(), fn);
}
}
}
return resolveConfigFunctions;
}

public static Map<String, HttpAuthSchemeParameter> collectHttpAuthSchemeParameters(
Collection<HttpAuthScheme> httpAuthSchemes) {
Map<String, HttpAuthSchemeParameter> httpAuthSchemeParameters = new HashMap<>();
Expand All @@ -136,7 +166,7 @@ public static Map<String, HttpAuthSchemeParameter> collectHttpAuthSchemeParamete
if (httpAuthSchemeParameters.containsKey(param.name())) {
HttpAuthSchemeParameter existingParam = httpAuthSchemeParameters.get(param.name());
if (!param.equals(existingParam)) {
throw new CodegenException("Contradicting `HttpAuthSchemeParameter` defintions for `"
throw new CodegenException("Contradicting `HttpAuthSchemeParameter` definitions for `"
+ param.name()
+ "`; existing: "
+ existingParam
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package software.amazon.smithy.typescript.codegen.auth.http;

import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import software.amazon.smithy.codegen.core.Symbol;
import software.amazon.smithy.typescript.codegen.TypeScriptDependency;
import software.amazon.smithy.typescript.codegen.TypeScriptWriter;
import software.amazon.smithy.utils.SmithyBuilder;
import software.amazon.smithy.utils.SmithyInternalApi;
import software.amazon.smithy.utils.SmithyUnstableApi;
import software.amazon.smithy.utils.ToSmithyBuilder;

/**
* Definition of a Config field.
*
* Currently used to populate the ClientDefaults interface in `experimentalIdentityAndAuth`.
*
* @param name name of the config field
* @param type whether the config field is main or auxiliary
* @param inputType writer for the input type of the config field
* @param resolvedType writer for the resolved type of the config field
* @param docs writer for the docs of the config field
*/
@SmithyUnstableApi
public final record ConfigField(
String name,
Type type,
Symbol inputType,
Symbol resolvedType,
BiConsumer<TypeScriptWriter, ConfigField> configFieldWriter,
Optional<Consumer<TypeScriptWriter>> docs
) implements ToSmithyBuilder<ConfigField> {

/**
* Defines the type of the config field.
*/
@SmithyUnstableApi
public enum Type {
/**
* Specifies the property is important, e.g. {@code apiKey} for {@code @httpApiKeyAuth}
*/
MAIN,
/**
* Specifies the property is auxiliary, e.g. {@code region} for {@code @aws.auth#sigv4}
*/
AUXILIARY
}

public static Builder builder() {
return new Builder();
}

@Override
public Builder toBuilder() {
return builder()
.name(name)
.type(type)
.inputType(inputType)
.resolvedType(resolvedType)
.configFieldWriter(configFieldWriter)
.docs(docs.orElse(null));
}

public static final class Builder implements SmithyBuilder<ConfigField> {
private String name;
private Type type;
private Symbol inputType;
private Symbol resolvedType;
private Consumer<TypeScriptWriter> docs;
private BiConsumer<TypeScriptWriter, ConfigField> configFieldWriter;

@Override
public ConfigField build() {
if (configFieldWriter == null) {
configFieldWriter = type.equals(Type.MAIN)
? ConfigField::defaultMainConfigFieldWriter
: ConfigField::defaultAuxiliaryConfigFieldWriter;
}
return new ConfigField(
SmithyBuilder.requiredState("name", name),
SmithyBuilder.requiredState("type", type),
SmithyBuilder.requiredState("inputType", inputType),
SmithyBuilder.requiredState("resolvedType", resolvedType),
SmithyBuilder.requiredState("configFieldWriter", configFieldWriter),
Optional.ofNullable(docs));
}

public Builder name(String name) {
this.name = name;
return this;
}

public Builder type(Type type) {
this.type = type;
return this;
}

public Builder inputType(Symbol inputType) {
this.inputType = inputType;
return this;
}

public Builder resolvedType(Symbol resolvedType) {
this.resolvedType = resolvedType;
return this;
}

public Builder docs(Consumer<TypeScriptWriter> docs) {
this.docs = docs;
return this;
}

public Builder configFieldWriter(BiConsumer<TypeScriptWriter, ConfigField> configFieldWriter) {
this.configFieldWriter = configFieldWriter;
return this;
}
}

@SmithyInternalApi
public static void defaultMainConfigFieldWriter(
TypeScriptWriter w,
ConfigField configField
) {
w.addDependency(TypeScriptDependency.SMITHY_CORE);
w.addImport("memoizeIdentityProvider", null,
TypeScriptDependency.SMITHY_CORE);
w.addImport("isIdentityExpired", null,
TypeScriptDependency.SMITHY_CORE);
w.addImport("doesIdentityRequireRefresh", null,
TypeScriptDependency.SMITHY_CORE);
w.write("""
const $L = memoizeIdentityProvider(config.$L, isIdentityExpired, \
doesIdentityRequireRefresh);""",
configField.name(),
configField.name());
}

@SmithyInternalApi
public static void defaultAuxiliaryConfigFieldWriter(
TypeScriptWriter w,
ConfigField configField
) {
w.addDependency(TypeScriptDependency.UTIL_MIDDLEWARE);
w.addImport("normalizeProvider", null, TypeScriptDependency.UTIL_MIDDLEWARE);
w.write("const $L = config.$L ? normalizeProvider(config.$L) : undefined;",
configField.name(),
configField.name(),
configField.name());
}
}
Loading

0 comments on commit 20acec0

Please sign in to comment.