From a5b374218ad1055b4afeb23578f2ca7011b1559f Mon Sep 17 00:00:00 2001 From: Alberto Date: Fri, 20 Dec 2024 11:40:00 -0500 Subject: [PATCH 01/20] feat(java): Include version headers in request options --- seed/ts-sdk/seed.yml | 2 ++ .../definition/api.yml | 1 + .../definition/service.yml | 10 ++++++++++ .../request-options-with-fern-versions/generators.yml | 1 + 4 files changed, 14 insertions(+) create mode 100644 test-definitions/fern/apis/request-options-with-fern-versions/definition/api.yml create mode 100644 test-definitions/fern/apis/request-options-with-fern-versions/definition/service.yml create mode 100644 test-definitions/fern/apis/request-options-with-fern-versions/generators.yml diff --git a/seed/ts-sdk/seed.yml b/seed/ts-sdk/seed.yml index bfd22dfc6a1..542c39a7e5a 100644 --- a/seed/ts-sdk/seed.yml +++ b/seed/ts-sdk/seed.yml @@ -233,6 +233,8 @@ fixtures: inlinePathParameters: true retainOriginalCasing: true outputFolder: inline-path-parameters-retain-original-casing + request-options-with-fern-versions: + - outputFolder: default scripts: - docker: fernapi/ts-seed commands: diff --git a/test-definitions/fern/apis/request-options-with-fern-versions/definition/api.yml b/test-definitions/fern/apis/request-options-with-fern-versions/definition/api.yml new file mode 100644 index 00000000000..f8b7c2a3c14 --- /dev/null +++ b/test-definitions/fern/apis/request-options-with-fern-versions/definition/api.yml @@ -0,0 +1 @@ +name: request-options-with-fern-versions diff --git a/test-definitions/fern/apis/request-options-with-fern-versions/definition/service.yml b/test-definitions/fern/apis/request-options-with-fern-versions/definition/service.yml new file mode 100644 index 00000000000..84171deab99 --- /dev/null +++ b/test-definitions/fern/apis/request-options-with-fern-versions/definition/service.yml @@ -0,0 +1,10 @@ +service: + auth: false + base-path: /service + endpoints: + ping: + method: GET + path: /ping + response: + type: string + status-code: 200 \ No newline at end of file diff --git a/test-definitions/fern/apis/request-options-with-fern-versions/generators.yml b/test-definitions/fern/apis/request-options-with-fern-versions/generators.yml new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/test-definitions/fern/apis/request-options-with-fern-versions/generators.yml @@ -0,0 +1 @@ +{} From f325dddbfce41a6fe4108760a436b0d65726aca2 Mon Sep 17 00:00:00 2001 From: Alberto Date: Fri, 20 Dec 2024 13:48:41 -0500 Subject: [PATCH 02/20] Implement client options header --- .../generators/ClientOptionsGenerator.java | 52 +++++++++++++++++++ seed/ts-sdk/seed.yml | 2 - .../definition/api.yml | 1 - .../definition/service.yml | 10 ---- .../generators.yml | 1 - 5 files changed, 52 insertions(+), 14 deletions(-) delete mode 100644 test-definitions/fern/apis/request-options-with-fern-versions/definition/api.yml delete mode 100644 test-definitions/fern/apis/request-options-with-fern-versions/definition/service.yml delete mode 100644 test-definitions/fern/apis/request-options-with-fern-versions/generators.yml diff --git a/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java b/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java index 517778966c2..faa9da36f2c 100644 --- a/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java +++ b/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java @@ -17,6 +17,8 @@ package com.fern.java.client.generators; import com.fern.generator.exec.model.config.GeneratorConfig; +import com.fern.ir.model.ir.ApiVersionScheme; +import com.fern.ir.model.ir.HeaderApiVersionScheme; import com.fern.ir.model.ir.PlatformHeaders; import com.fern.ir.model.variables.VariableDeclaration; import com.fern.ir.model.variables.VariableId; @@ -68,6 +70,9 @@ public final class ClientOptionsGenerator extends AbstractFileGenerator { Modifier.PRIVATE, Modifier.FINAL) .build(); + private static final FieldSpec API_VERSIONS_FIELD = FieldSpec.builder( + String.class, "version", Modifier.PRIVATE, Modifier.FINAL) + .build(); private static final FieldSpec OKHTTP_CLIENT_FIELD = FieldSpec.builder( OkHttpClient.class, "httpClient", Modifier.PRIVATE, Modifier.FINAL) .build(); @@ -208,6 +213,53 @@ public GeneratedClientOptions generateFile() { .build()) .addType(createBuilder(variableFields)) .build(); + + clientGeneratorContext + .getIr() + .getApiVersion() + .ifPresent(apiVersionScheme -> apiVersionScheme.visit(new ApiVersionScheme.Visitor() { + @Override + public Void visitHeader(HeaderApiVersionScheme headerApiVersionScheme) { + contructorBuilder.addParameter(ParameterSpec.builder( + ParameterizedTypeName.get( + ClassName.get(Optional.class), ClassName.get(String.class)), + API_VERSIONS_FIELD.name) + .build()); + + if (headerApiVersionScheme.getValue().getDefault().isPresent()) { + contructorBuilder.addStatement( + "this.$L = $L.orElse($S)", + API_VERSIONS_FIELD.name, + API_VERSIONS_FIELD.name, + headerApiVersionScheme + .getValue() + .getDefault() + .get() + .getName() + .getWireValue()); + } else { + contructorBuilder.addStatement( + "this.$L = $L", API_VERSIONS_FIELD.name, API_VERSIONS_FIELD.name); + } + + contructorBuilder.addStatement( + "this.$L.put($S, $L)", + HEADERS_FIELD.name, + headerApiVersionScheme.getHeader().getName().getWireValue(), + CodeBlock.of("this.$L", API_VERSIONS_FIELD.name)); + + clientOptionsBuilder.addField(API_VERSIONS_FIELD); + clientOptionsBuilder.addMethod(createGetter(API_VERSIONS_FIELD)); + + return null; + } + + @Override + public Void _visitUnknown(Object o) { + throw new IllegalArgumentException("Received unknown API versioning schema type in IR."); + } + })); + JavaFile environmentsFile = JavaFile.builder(className.packageName(), clientOptions).build(); diff --git a/seed/ts-sdk/seed.yml b/seed/ts-sdk/seed.yml index 542c39a7e5a..bfd22dfc6a1 100644 --- a/seed/ts-sdk/seed.yml +++ b/seed/ts-sdk/seed.yml @@ -233,8 +233,6 @@ fixtures: inlinePathParameters: true retainOriginalCasing: true outputFolder: inline-path-parameters-retain-original-casing - request-options-with-fern-versions: - - outputFolder: default scripts: - docker: fernapi/ts-seed commands: diff --git a/test-definitions/fern/apis/request-options-with-fern-versions/definition/api.yml b/test-definitions/fern/apis/request-options-with-fern-versions/definition/api.yml deleted file mode 100644 index f8b7c2a3c14..00000000000 --- a/test-definitions/fern/apis/request-options-with-fern-versions/definition/api.yml +++ /dev/null @@ -1 +0,0 @@ -name: request-options-with-fern-versions diff --git a/test-definitions/fern/apis/request-options-with-fern-versions/definition/service.yml b/test-definitions/fern/apis/request-options-with-fern-versions/definition/service.yml deleted file mode 100644 index 84171deab99..00000000000 --- a/test-definitions/fern/apis/request-options-with-fern-versions/definition/service.yml +++ /dev/null @@ -1,10 +0,0 @@ -service: - auth: false - base-path: /service - endpoints: - ping: - method: GET - path: /ping - response: - type: string - status-code: 200 \ No newline at end of file diff --git a/test-definitions/fern/apis/request-options-with-fern-versions/generators.yml b/test-definitions/fern/apis/request-options-with-fern-versions/generators.yml deleted file mode 100644 index 0967ef424bc..00000000000 --- a/test-definitions/fern/apis/request-options-with-fern-versions/generators.yml +++ /dev/null @@ -1 +0,0 @@ -{} From 01c040d267227aef2179779c0135d65aff40f962 Mon Sep 17 00:00:00 2001 From: Alberto Date: Fri, 20 Dec 2024 14:52:30 -0500 Subject: [PATCH 03/20] Correct implementation --- .../java/client/GeneratedClientOptions.java | 3 + .../generators/ClientOptionsGenerator.java | 165 +++++++++++------- .../com/seed/version/core/ClientOptions.java | 21 ++- 3 files changed, 120 insertions(+), 69 deletions(-) diff --git a/generators/java/sdk/src/main/java/com/fern/java/client/GeneratedClientOptions.java b/generators/java/sdk/src/main/java/com/fern/java/client/GeneratedClientOptions.java index 416fdb8d630..ce3d993d721 100644 --- a/generators/java/sdk/src/main/java/com/fern/java/client/GeneratedClientOptions.java +++ b/generators/java/sdk/src/main/java/com/fern/java/client/GeneratedClientOptions.java @@ -22,6 +22,7 @@ import com.squareup.javapoet.ClassName; import com.squareup.javapoet.MethodSpec; import java.util.Map; +import java.util.Optional; import org.immutables.value.Value; @Value.Immutable @@ -34,6 +35,8 @@ public abstract class GeneratedClientOptions extends AbstractGeneratedJavaFile { public abstract MethodSpec httpClientWithTimeout(); + public abstract Optional version(); + public abstract Map variableGetters(); public abstract ClassName builderClassName(); diff --git a/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java b/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java index faa9da36f2c..2215fdc16ef 100644 --- a/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java +++ b/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java @@ -27,6 +27,7 @@ import com.fern.java.client.GeneratedEnvironmentsClass; import com.fern.java.generators.AbstractFileGenerator; import com.fern.java.output.GeneratedJavaFile; +import com.google.common.collect.ImmutableList; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.CodeBlock; import com.squareup.javapoet.FieldSpec; @@ -102,6 +103,7 @@ public ClientOptionsGenerator( public GeneratedClientOptions generateFile() { MethodSpec environmentGetter = createGetter(environmentField); MethodSpec headersFromRequestOptions = headersFromRequestOptions(); + Optional versionsGetter = Optional.empty(); Optional headersFromIdempotentRequestOptions = headersFromIdempotentRequestOptions(); MethodSpec httpClientGetter = createGetter(OKHTTP_CLIENT_FIELD); Map variableFields = getVariableFields(); @@ -140,6 +142,52 @@ public GeneratedClientOptions generateFile() { platformHeadersPutString) .addStatement("this.$L = $L", HEADER_SUPPLIERS_FIELD.name, HEADER_SUPPLIERS_FIELD.name) .addStatement("this.$L = $L", OKHTTP_CLIENT_FIELD.name, OKHTTP_CLIENT_FIELD.name); + + if (clientGeneratorContext.getIr().getApiVersion().isPresent()) { + ApiVersionScheme apiVersionScheme = + clientGeneratorContext.getIr().getApiVersion().get(); + + apiVersionScheme.visit(new ApiVersionScheme.Visitor() { + @Override + public Void visitHeader(HeaderApiVersionScheme headerApiVersionScheme) { + contructorBuilder.addParameter(ParameterSpec.builder( + ParameterizedTypeName.get( + ClassName.get(Optional.class), ClassName.get(String.class)), + API_VERSIONS_FIELD.name) + .build()); + + if (headerApiVersionScheme.getValue().getDefault().isPresent()) { + contructorBuilder.addStatement( + "this.$L = $L.orElse($S)", + API_VERSIONS_FIELD.name, + API_VERSIONS_FIELD.name, + headerApiVersionScheme + .getValue() + .getDefault() + .get() + .getName() + .getWireValue()); + } else { + contructorBuilder.addStatement( + "this.$L = $L", API_VERSIONS_FIELD.name, API_VERSIONS_FIELD.name); + } + + contructorBuilder.addStatement( + "this.$L.put($S,$L)", + HEADERS_FIELD.name, + headerApiVersionScheme.getHeader().getName().getWireValue(), + CodeBlock.of("this.$L", API_VERSIONS_FIELD.name)); + + return null; + } + + @Override + public Void _visitUnknown(Object _o) { + throw new IllegalArgumentException("Received unknown API versioning schema type in IR."); + } + }); + } + variableFields .values() .forEach(fieldSpec -> contructorBuilder.addStatement("this.$N = $N", fieldSpec, fieldSpec)); @@ -154,6 +202,12 @@ public GeneratedClientOptions generateFile() { .addMethod(environmentGetter) .addMethod(headersFromRequestOptions); + if (clientGeneratorContext.getIr().getApiVersion().isPresent()) { + clientOptionsBuilder.addField(API_VERSIONS_FIELD); + versionsGetter = Optional.of(createGetter(API_VERSIONS_FIELD)); + clientOptionsBuilder.addMethod(versionsGetter.get()); + } + if (headersFromIdempotentRequestOptions.isPresent()) { clientOptionsBuilder.addMethod(headersFromIdempotentRequestOptions.get()); MethodSpec httpClientWithTimeoutGetter = MethodSpec.methodBuilder("httpClientWithTimeout") @@ -211,55 +265,9 @@ public GeneratedClientOptions generateFile() { .returns(builderClassName) .addStatement("return new $T()", builderClassName) .build()) - .addType(createBuilder(variableFields)) + .addType(createBuilder(clientGeneratorContext, variableFields)) .build(); - clientGeneratorContext - .getIr() - .getApiVersion() - .ifPresent(apiVersionScheme -> apiVersionScheme.visit(new ApiVersionScheme.Visitor() { - @Override - public Void visitHeader(HeaderApiVersionScheme headerApiVersionScheme) { - contructorBuilder.addParameter(ParameterSpec.builder( - ParameterizedTypeName.get( - ClassName.get(Optional.class), ClassName.get(String.class)), - API_VERSIONS_FIELD.name) - .build()); - - if (headerApiVersionScheme.getValue().getDefault().isPresent()) { - contructorBuilder.addStatement( - "this.$L = $L.orElse($S)", - API_VERSIONS_FIELD.name, - API_VERSIONS_FIELD.name, - headerApiVersionScheme - .getValue() - .getDefault() - .get() - .getName() - .getWireValue()); - } else { - contructorBuilder.addStatement( - "this.$L = $L", API_VERSIONS_FIELD.name, API_VERSIONS_FIELD.name); - } - - contructorBuilder.addStatement( - "this.$L.put($S, $L)", - HEADERS_FIELD.name, - headerApiVersionScheme.getHeader().getName().getWireValue(), - CodeBlock.of("this.$L", API_VERSIONS_FIELD.name)); - - clientOptionsBuilder.addField(API_VERSIONS_FIELD); - clientOptionsBuilder.addMethod(createGetter(API_VERSIONS_FIELD)); - - return null; - } - - @Override - public Void _visitUnknown(Object o) { - throw new IllegalArgumentException("Received unknown API versioning schema type in IR."); - } - })); - JavaFile environmentsFile = JavaFile.builder(className.packageName(), clientOptions).build(); @@ -271,6 +279,7 @@ public Void _visitUnknown(Object o) { .httpClientWithTimeout(httpClientWithTimeoutGetter) .builderClassName(builderClassName) .putAllVariableGetters(variableGetters) + .version(versionsGetter) .build(); } @@ -307,8 +316,8 @@ private MethodSpec.Builder constructHeadersMethod() { .addStatement("return values"); } - private TypeSpec createBuilder(Map variableFields) { - return TypeSpec.classBuilder(builderClassName) + private TypeSpec createBuilder(ClientGeneratorContext context, Map variableFields) { + TypeSpec.Builder builder = TypeSpec.classBuilder(builderClassName) .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) .addField(FieldSpec.builder(environmentField.type, environmentField.name) .addModifiers(Modifier.PRIVATE) @@ -323,9 +332,20 @@ private TypeSpec createBuilder(Map variableFields) { .addMethod(getEnvironmentBuilder()) .addMethod(getHeaderBuilder()) .addMethod(getHeaderSupplierBuilder()) - .addMethods(getVariableBuilders(variableFields)) - .addMethod(getBuildMethod(variableFields)) - .build(); + .addMethods(getVariableBuilders(variableFields)); + + if (context.getIr().getApiVersion().isPresent()) { + builder.addField(FieldSpec.builder( + ParameterizedTypeName.get(ClassName.get(Optional.class), ClassName.get(String.class)), + API_VERSIONS_FIELD.name, + Modifier.PRIVATE) + .build()); + builder.addMethod(getVersionBuilder()); + } + + builder.addMethod(getBuildMethod(context, variableFields)); + + return builder.build(); } private MethodSpec getEnvironmentBuilder() { @@ -360,6 +380,16 @@ private MethodSpec getHeaderSupplierBuilder() { .build(); } + private MethodSpec getVersionBuilder() { + return MethodSpec.methodBuilder(API_VERSIONS_FIELD.name) + .addModifiers(Modifier.PUBLIC) + .returns(builderClassName) + .addParameter(String.class, API_VERSIONS_FIELD.name) + .addStatement("this.$L = $T.of($L)", API_VERSIONS_FIELD.name, Optional.class, API_VERSIONS_FIELD.name) + .addStatement("return this") + .build(); + } + private Map getVariableFields() { return generatorContext.getIr().getVariables().stream() .collect(Collectors.toMap(VariableDeclaration::getId, variableDeclaration -> FieldSpec.builder( @@ -409,7 +439,20 @@ private Map getVariableGetters(Map variableFields) { + private MethodSpec getBuildMethod(ClientGeneratorContext context, Map variableFields) { + ImmutableList.Builder argsBuilder = ImmutableList.builder(); + argsBuilder.add( + className, environmentField.name, HEADERS_FIELD.name, HEADER_SUPPLIERS_FIELD.name, "okhttpClient"); + + String returnString = "return new $T($L, $L, $L, $L"; + + if (context.getIr().getApiVersion().isPresent()) { + argsBuilder.add(API_VERSIONS_FIELD.name); + returnString = "return new $T($L, $L, $L, $L, $L"; + } + + Object[] args = argsBuilder.build().toArray(); + if (variableFields.isEmpty()) { return MethodSpec.methodBuilder("build") .addModifiers(Modifier.PUBLIC) @@ -423,13 +466,7 @@ private MethodSpec getBuildMethod(Map variableFields) { .getRetryInterceptorClassName()) .add("\n .build()") .build()) - .addStatement( - "return new $T($L, $L, $L, $L)", - className, - environmentField.name, - HEADERS_FIELD.name, - HEADER_SUPPLIERS_FIELD.name, - "okhttpClient") + .addStatement(returnString + ")", args) .build(); } else { String variableArgs = variableFields.values().stream() @@ -447,13 +484,7 @@ private MethodSpec getBuildMethod(Map variableFields) { .getRetryInterceptorClassName()) .add("\n .build()") .build()) - .addStatement( - "return new $T($L, $L, $L, $L," + variableArgs + ")", - className, - environmentField.name, - HEADERS_FIELD.name, - HEADER_SUPPLIERS_FIELD.name, - "okhttpClient") + .addStatement(returnString + ", " + variableArgs + ")", args) .build(); } } diff --git a/seed/java-sdk/version/src/main/java/com/seed/version/core/ClientOptions.java b/seed/java-sdk/version/src/main/java/com/seed/version/core/ClientOptions.java index 3dc4d2a3475..a959c0a294e 100644 --- a/seed/java-sdk/version/src/main/java/com/seed/version/core/ClientOptions.java +++ b/seed/java-sdk/version/src/main/java/com/seed/version/core/ClientOptions.java @@ -5,6 +5,7 @@ import java.util.HashMap; import java.util.Map; +import java.util.Optional; import java.util.concurrent.TimeUnit; import java.util.function.Supplier; import okhttp3.OkHttpClient; @@ -18,11 +19,14 @@ public final class ClientOptions { private final OkHttpClient httpClient; + private final String version; + private ClientOptions( Environment environment, Map headers, Map> headerSuppliers, - OkHttpClient httpClient) { + OkHttpClient httpClient, + Optional version) { this.environment = environment; this.headers = new HashMap<>(); this.headers.putAll(headers); @@ -33,6 +37,8 @@ private ClientOptions( }); this.headerSuppliers = headerSuppliers; this.httpClient = httpClient; + this.version = version.orElse("2.0.0"); + this.headers.put("X-API-Version", this.version); } public Environment environment() { @@ -50,6 +56,10 @@ public Map headers(RequestOptions requestOptions) { return values; } + public String version() { + return this.version; + } + public OkHttpClient httpClient() { return this.httpClient; } @@ -78,6 +88,8 @@ public static final class Builder { private final Map> headerSuppliers = new HashMap<>(); + private Optional version; + public Builder environment(Environment environment) { this.environment = environment; return this; @@ -93,11 +105,16 @@ public Builder addHeader(String key, Supplier value) { return this; } + public Builder version(String version) { + this.version = Optional.of(version); + return this; + } + public ClientOptions build() { OkHttpClient okhttpClient = new OkHttpClient.Builder() .addInterceptor(new RetryInterceptor(3)) .build(); - return new ClientOptions(environment, headers, headerSuppliers, okhttpClient); + return new ClientOptions(environment, headers, headerSuppliers, okhttpClient, version); } } } From 6c2a11d40e35c836faccdebd172717d6ccffa8c6 Mon Sep 17 00:00:00 2001 From: Alberto Date: Mon, 6 Jan 2025 15:08:40 -0500 Subject: [PATCH 04/20] Generate api versions --- .../main/java/com/fern/java/client/Cli.java | 16 ++++++++---- .../client/ClientPoetClassNameFactory.java | 4 +++ .../com/seed/version/core/ApiVersions.java | 26 +++++++++++++++++++ 3 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 seed/java-sdk/version/src/main/java/com/seed/version/core/ApiVersions.java diff --git a/generators/java/sdk/src/main/java/com/fern/java/client/Cli.java b/generators/java/sdk/src/main/java/com/fern/java/client/Cli.java index a7c250fbdb3..b15c81bd7f6 100644 --- a/generators/java/sdk/src/main/java/com/fern/java/client/Cli.java +++ b/generators/java/sdk/src/main/java/com/fern/java/client/Cli.java @@ -8,6 +8,7 @@ import com.fern.ir.model.auth.AuthScheme; import com.fern.ir.model.auth.OAuthScheme; import com.fern.ir.model.commons.ErrorId; +import com.fern.ir.model.ir.HeaderApiVersionScheme; import com.fern.ir.model.ir.IntermediateRepresentation; import com.fern.java.AbstractGeneratorCli; import com.fern.java.AbstractPoetClassNameFactory; @@ -31,11 +32,7 @@ import com.fern.java.client.generators.SubpackageClientGenerator; import com.fern.java.client.generators.SuppliersGenerator; import com.fern.java.client.generators.TestGenerator; -import com.fern.java.generators.DateTimeDeserializerGenerator; -import com.fern.java.generators.ObjectMappersGenerator; -import com.fern.java.generators.PaginationCoreGenerator; -import com.fern.java.generators.StreamGenerator; -import com.fern.java.generators.TypesGenerator; +import com.fern.java.generators.*; import com.fern.java.generators.TypesGenerator.Result; import com.fern.java.output.GeneratedFile; import com.fern.java.output.GeneratedJavaFile; @@ -183,6 +180,15 @@ public GeneratedRootClient generateClient( GeneratedEnvironmentsClass generatedEnvironmentsClass = environmentGenerator.generateFile(); this.addGeneratedFile(generatedEnvironmentsClass); + ir.getApiVersion() + .flatMap(apiVersion -> apiVersion.getHeader().map(HeaderApiVersionScheme::getValue)) + .ifPresent(enumTypeDeclaration -> { + EnumGenerator apiVersionsGenerator = new EnumGenerator( + context.getPoetClassNameFactory().getApiVersionsClassName(), context, enumTypeDeclaration); + GeneratedJavaFile generatedApiVersions = apiVersionsGenerator.generateFile(); + this.addGeneratedFile(generatedApiVersions); + }); + RequestOptionsGenerator requestOptionsGenerator = new RequestOptionsGenerator( context, context.getPoetClassNameFactory().getRequestOptionsClassName()); GeneratedJavaFile generatedRequestOptions = requestOptionsGenerator.generateFile(); diff --git a/generators/java/sdk/src/main/java/com/fern/java/client/ClientPoetClassNameFactory.java b/generators/java/sdk/src/main/java/com/fern/java/client/ClientPoetClassNameFactory.java index 9b09c32a987..0247bf3a839 100644 --- a/generators/java/sdk/src/main/java/com/fern/java/client/ClientPoetClassNameFactory.java +++ b/generators/java/sdk/src/main/java/com/fern/java/client/ClientPoetClassNameFactory.java @@ -44,6 +44,10 @@ public ClassName getResponseBodyReaderClassName() { return ClassName.get(getCorePackage(), "ResponseBodyReader"); } + public ClassName getApiVersionsClassName() { + return ClassName.get(getCorePackage(), "ApiVersions"); + } + public ClassName getRequestOptionsClassName() { return ClassName.get(getCorePackage(), "RequestOptions"); } diff --git a/seed/java-sdk/version/src/main/java/com/seed/version/core/ApiVersions.java b/seed/java-sdk/version/src/main/java/com/seed/version/core/ApiVersions.java new file mode 100644 index 00000000000..6882b1de180 --- /dev/null +++ b/seed/java-sdk/version/src/main/java/com/seed/version/core/ApiVersions.java @@ -0,0 +1,26 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.version.core; + +import com.fasterxml.jackson.annotation.JsonValue; + +public enum ApiVersions { + _1_0_0("1.0.0"), + + _2_0_0("2.0.0"), + + LATEST("latest"); + + private final String value; + + ApiVersions(String value) { + this.value = value; + } + + @JsonValue + @java.lang.Override + public String toString() { + return this.value; + } +} From 236a164186cca95b745478b10ffb2f81506b9819 Mon Sep 17 00:00:00 2001 From: Alberto Date: Mon, 6 Jan 2025 15:24:01 -0500 Subject: [PATCH 05/20] update test definition --- test-definitions/fern/apis/version/definition/api.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test-definitions/fern/apis/version/definition/api.yml b/test-definitions/fern/apis/version/definition/api.yml index 8a52c2ad5e6..5b85d1c8086 100644 --- a/test-definitions/fern/apis/version/definition/api.yml +++ b/test-definitions/fern/apis/version/definition/api.yml @@ -3,6 +3,8 @@ version: header: X-API-Version default: "2.0.0" values: - - "1.0.0" - - "2.0.0" + - name: v1 + value: "1.0.0" + - name: v2 + value: "2.0.0" - "latest" \ No newline at end of file From 5286cc27f0b363a9c1ca752713fff0bcfe8aa715 Mon Sep 17 00:00:00 2001 From: Alberto Date: Mon, 6 Jan 2025 15:37:53 -0500 Subject: [PATCH 06/20] restore husky file --- .husky/{pre-commit-foo => pre-commit} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .husky/{pre-commit-foo => pre-commit} (100%) diff --git a/.husky/pre-commit-foo b/.husky/pre-commit similarity index 100% rename from .husky/pre-commit-foo rename to .husky/pre-commit From 1d0145322a8635bd36f71e5e718046d1070d62f1 Mon Sep 17 00:00:00 2001 From: Alberto Date: Mon, 6 Jan 2025 16:08:01 -0500 Subject: [PATCH 07/20] Test using names --- .../generators/ClientOptionsGenerator.java | 38 +++++++++---------- .../java-sdk/version/.mock/definition/api.yml | 6 ++- .../com/seed/version/core/ApiVersions.java | 4 +- .../com/seed/version/core/ClientOptions.java | 26 +++++++------ 4 files changed, 37 insertions(+), 37 deletions(-) diff --git a/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java b/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java index 8be6a80d320..860e8a74e54 100644 --- a/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java +++ b/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java @@ -149,7 +149,7 @@ public GeneratedClientOptions generateFile() { String.class, platformHeadersPutString) .addStatement("this.$L = $L", HEADER_SUPPLIERS_FIELD.name, HEADER_SUPPLIERS_FIELD.name) - .addStatement("this.$L = $L", OKHTTP_CLIENT_FIELD.name, OKHTTP_CLIENT_FIELD.name); + .addStatement("this.$L = $L", OKHTTP_CLIENT_FIELD.name, OKHTTP_CLIENT_FIELD.name) .addStatement("this.$L = $L", TIMEOUT_FIELD.name, TIMEOUT_FIELD.name); if (clientGeneratorContext.getIr().getApiVersion().isPresent()) { @@ -159,14 +159,14 @@ public GeneratedClientOptions generateFile() { apiVersionScheme.visit(new ApiVersionScheme.Visitor() { @Override public Void visitHeader(HeaderApiVersionScheme headerApiVersionScheme) { - contructorBuilder.addParameter(ParameterSpec.builder( + constructorBuilder.addParameter(ParameterSpec.builder( ParameterizedTypeName.get( ClassName.get(Optional.class), ClassName.get(String.class)), API_VERSIONS_FIELD.name) .build()); if (headerApiVersionScheme.getValue().getDefault().isPresent()) { - contructorBuilder.addStatement( + constructorBuilder.addStatement( "this.$L = $L.orElse($S)", API_VERSIONS_FIELD.name, API_VERSIONS_FIELD.name, @@ -177,11 +177,11 @@ public Void visitHeader(HeaderApiVersionScheme headerApiVersionScheme) { .getName() .getWireValue()); } else { - contructorBuilder.addStatement( + constructorBuilder.addStatement( "this.$L = $L", API_VERSIONS_FIELD.name, API_VERSIONS_FIELD.name); } - contructorBuilder.addStatement( + constructorBuilder.addStatement( "this.$L.put($S,$L)", HEADERS_FIELD.name, headerApiVersionScheme.getHeader().getName().getWireValue(), @@ -195,7 +195,7 @@ public Void _visitUnknown(Object _o) { throw new IllegalArgumentException("Received unknown API versioning schema type in IR."); } }); ->>>>>>> main + } variableFields .values() @@ -291,7 +291,6 @@ public Void _visitUnknown(Object _o) { .httpClientWithTimeout(httpClientWithTimeoutGetter) .builderClassName(builderClassName) .putAllVariableGetters(variableGetters) - .version(versionsGetter) .build(); } @@ -355,9 +354,6 @@ private TypeSpec createBuilder(ClientGeneratorContext context, Map headers, Map> headerSuppliers, OkHttpClient httpClient, - Optional version, - int timeout) { + int timeout, + Optional version) { this.environment = environment; this.headers = new HashMap<>(); this.headers.putAll(headers); @@ -39,9 +40,9 @@ private ClientOptions( }); this.headerSuppliers = headerSuppliers; this.httpClient = httpClient; + this.timeout = timeout; this.version = version.orElse("2.0.0"); this.headers.put("X-API-Version", this.version); - this.timeout = timeout; } public Environment environment() { @@ -91,9 +92,10 @@ public static final class Builder { private final Map> headerSuppliers = new HashMap<>(); - private Optional version; private int timeout = 60; + private Optional version; + public Builder environment(Environment environment) { this.environment = environment; return this; @@ -109,11 +111,6 @@ public Builder addHeader(String key, Supplier value) { return this; } - public Builder version(String version) { - this.version = Optional.of(version); - return this; - } - /** * Override the timeout in seconds. Defaults to 60 seconds. */ @@ -122,12 +119,17 @@ public Builder timeout(int timeout) { return this; } + public Builder version(String version) { + this.version = Optional.of(version); + return this; + } + public ClientOptions build() { OkHttpClient okhttpClient = new OkHttpClient.Builder() .addInterceptor(new RetryInterceptor(3)) .callTimeout(this.timeout, TimeUnit.SECONDS) - .build() - return new ClientOptions(environment, headers, headerSuppliers, okhttpClient, version, this.timeout); + .build(); + return new ClientOptions(environment, headers, headerSuppliers, okhttpClient, this.timeout, version); } } } From 269f7e7657fce69ba1730ef761b4d896a159ed0d Mon Sep 17 00:00:00 2001 From: Alberto Date: Mon, 6 Jan 2025 18:07:06 -0500 Subject: [PATCH 08/20] use apiversions enum --- .../fern/java/utils/ApiVersionConstants.java | 5 ++ .../main/java/com/fern/java/client/Cli.java | 45 ++++++++++++- .../generators/ClientOptionsGenerator.java | 63 +++++++++++-------- .../com/seed/version/core/ApiVersions.java | 4 +- .../com/seed/version/core/ClientOptions.java | 14 ++--- 5 files changed, 95 insertions(+), 36 deletions(-) create mode 100644 generators/java/generator-utils/src/main/java/com/fern/java/utils/ApiVersionConstants.java diff --git a/generators/java/generator-utils/src/main/java/com/fern/java/utils/ApiVersionConstants.java b/generators/java/generator-utils/src/main/java/com/fern/java/utils/ApiVersionConstants.java new file mode 100644 index 00000000000..9c201d7670b --- /dev/null +++ b/generators/java/generator-utils/src/main/java/com/fern/java/utils/ApiVersionConstants.java @@ -0,0 +1,5 @@ +package com.fern.java.utils; + +public final class ApiVersionConstants { + public static final String CURRENT_API_VERSION = "CURRENT"; +} diff --git a/generators/java/sdk/src/main/java/com/fern/java/client/Cli.java b/generators/java/sdk/src/main/java/com/fern/java/client/Cli.java index b15c81bd7f6..b0079cb66df 100644 --- a/generators/java/sdk/src/main/java/com/fern/java/client/Cli.java +++ b/generators/java/sdk/src/main/java/com/fern/java/client/Cli.java @@ -8,8 +8,13 @@ import com.fern.ir.model.auth.AuthScheme; import com.fern.ir.model.auth.OAuthScheme; import com.fern.ir.model.commons.ErrorId; +import com.fern.ir.model.commons.Name; +import com.fern.ir.model.commons.NameAndWireValue; +import com.fern.ir.model.commons.SafeAndUnsafeString; import com.fern.ir.model.ir.HeaderApiVersionScheme; import com.fern.ir.model.ir.IntermediateRepresentation; +import com.fern.ir.model.types.EnumTypeDeclaration; +import com.fern.ir.model.types.EnumValue; import com.fern.java.AbstractGeneratorCli; import com.fern.java.AbstractPoetClassNameFactory; import com.fern.java.DefaultGeneratorExecClient; @@ -42,6 +47,7 @@ import com.fern.java.output.gradle.GradleDependency; import com.fern.java.output.gradle.GradleDependencyType; import com.fern.java.output.gradle.ParsedGradleDependency; +import com.fern.java.utils.ApiVersionConstants; import com.palantir.common.streams.KeyedStream; import java.util.ArrayList; import java.util.Collections; @@ -182,9 +188,44 @@ public GeneratedRootClient generateClient( ir.getApiVersion() .flatMap(apiVersion -> apiVersion.getHeader().map(HeaderApiVersionScheme::getValue)) - .ifPresent(enumTypeDeclaration -> { + .ifPresent(irDeclaration -> { + EnumTypeDeclaration.Builder enumTypeDeclaration = + EnumTypeDeclaration.builder().from(irDeclaration); + + irDeclaration.getDefault().ifPresent(defaultValue -> { + Name current = Name.builder() + .originalName(ApiVersionConstants.CURRENT_API_VERSION) + .camelCase(SafeAndUnsafeString.builder() + .unsafeName(ApiVersionConstants.CURRENT_API_VERSION) + .safeName(ApiVersionConstants.CURRENT_API_VERSION) + .build()) + .pascalCase(SafeAndUnsafeString.builder() + .unsafeName(ApiVersionConstants.CURRENT_API_VERSION) + .safeName(ApiVersionConstants.CURRENT_API_VERSION) + .build()) + .snakeCase(SafeAndUnsafeString.builder() + .unsafeName(ApiVersionConstants.CURRENT_API_VERSION) + .safeName(ApiVersionConstants.CURRENT_API_VERSION) + .build()) + .screamingSnakeCase(SafeAndUnsafeString.builder() + .unsafeName(ApiVersionConstants.CURRENT_API_VERSION) + .safeName(ApiVersionConstants.CURRENT_API_VERSION) + .build()) + .build(); + + enumTypeDeclaration.addValues(EnumValue.builder() + .from(defaultValue) + .name(NameAndWireValue.builder() + .from(defaultValue.getName()) + .name(current) + .build()) + .build()); + }); + EnumGenerator apiVersionsGenerator = new EnumGenerator( - context.getPoetClassNameFactory().getApiVersionsClassName(), context, enumTypeDeclaration); + context.getPoetClassNameFactory().getApiVersionsClassName(), + context, + enumTypeDeclaration.build()); GeneratedJavaFile generatedApiVersions = apiVersionsGenerator.generateFile(); this.addGeneratedFile(generatedApiVersions); }); diff --git a/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java b/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java index 860e8a74e54..747a07fdce9 100644 --- a/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java +++ b/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java @@ -27,6 +27,7 @@ import com.fern.java.client.GeneratedEnvironmentsClass; import com.fern.java.generators.AbstractFileGenerator; import com.fern.java.output.GeneratedJavaFile; +import com.fern.java.utils.ApiVersionConstants; import com.google.common.collect.ImmutableList; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.CodeBlock; @@ -71,9 +72,6 @@ public final class ClientOptionsGenerator extends AbstractFileGenerator { Modifier.PRIVATE, Modifier.FINAL) .build(); - private static final FieldSpec API_VERSIONS_FIELD = FieldSpec.builder( - String.class, "version", Modifier.PRIVATE, Modifier.FINAL) - .build(); private static final FieldSpec OKHTTP_CLIENT_FIELD = FieldSpec.builder( OkHttpClient.class, "httpClient", Modifier.PRIVATE, Modifier.FINAL) .build(); @@ -86,6 +84,7 @@ public final class ClientOptionsGenerator extends AbstractFileGenerator { private final FieldSpec environmentField; private final GeneratedJavaFile requestOptionsFile; private final ClientGeneratorContext clientGeneratorContext; + private final FieldSpec apiVersionsField; public ClientOptionsGenerator( ClientGeneratorContext clientGeneratorContext, @@ -101,13 +100,19 @@ public ClientOptionsGenerator( .build(); this.requestOptionsFile = requestOptionsFile; this.clientGeneratorContext = clientGeneratorContext; + this.apiVersionsField = FieldSpec.builder( + clientGeneratorContext.getPoetClassNameFactory().getApiVersionsClassName(), + "version", + Modifier.PRIVATE, + Modifier.FINAL) + .build(); } @Override public GeneratedClientOptions generateFile() { MethodSpec environmentGetter = createGetter(environmentField); MethodSpec headersFromRequestOptions = headersFromRequestOptions(); - Optional versionsGetter = Optional.empty(); + Optional versionsGetter; Optional headersFromIdempotentRequestOptions = headersFromIdempotentRequestOptions(); MethodSpec httpClientGetter = createGetter(OKHTTP_CLIENT_FIELD); Map variableFields = getVariableFields(); @@ -161,31 +166,33 @@ public GeneratedClientOptions generateFile() { public Void visitHeader(HeaderApiVersionScheme headerApiVersionScheme) { constructorBuilder.addParameter(ParameterSpec.builder( ParameterizedTypeName.get( - ClassName.get(Optional.class), ClassName.get(String.class)), - API_VERSIONS_FIELD.name) + ClassName.get(Optional.class), + clientGeneratorContext + .getPoetClassNameFactory() + .getApiVersionsClassName()), + apiVersionsField.name) .build()); if (headerApiVersionScheme.getValue().getDefault().isPresent()) { constructorBuilder.addStatement( - "this.$L = $L.orElse($S)", - API_VERSIONS_FIELD.name, - API_VERSIONS_FIELD.name, - headerApiVersionScheme - .getValue() - .getDefault() - .get() - .getName() - .getWireValue()); + "this.$L = $L.orElse($L)", + apiVersionsField.name, + apiVersionsField.name, + CodeBlock.of( + "$T.$L", + clientGeneratorContext + .getPoetClassNameFactory() + .getApiVersionsClassName(), + ApiVersionConstants.CURRENT_API_VERSION)); } else { - constructorBuilder.addStatement( - "this.$L = $L", API_VERSIONS_FIELD.name, API_VERSIONS_FIELD.name); + constructorBuilder.addStatement("this.$L = $L", apiVersionsField.name, apiVersionsField.name); } constructorBuilder.addStatement( "this.$L.put($S,$L)", HEADERS_FIELD.name, headerApiVersionScheme.getHeader().getName().getWireValue(), - CodeBlock.of("this.$L", API_VERSIONS_FIELD.name)); + CodeBlock.of("this.$L.toString()", apiVersionsField.name)); return null; } @@ -214,8 +221,8 @@ public Void _visitUnknown(Object _o) { .addMethod(headersFromRequestOptions); if (clientGeneratorContext.getIr().getApiVersion().isPresent()) { - clientOptionsBuilder.addField(API_VERSIONS_FIELD); - versionsGetter = Optional.of(createGetter(API_VERSIONS_FIELD)); + clientOptionsBuilder.addField(apiVersionsField); + versionsGetter = Optional.of(createGetter(apiVersionsField)); clientOptionsBuilder.addMethod(versionsGetter.get()); } @@ -358,8 +365,10 @@ private TypeSpec createBuilder(ClientGeneratorContext context, Map> headerSuppliers, OkHttpClient httpClient, int timeout, - Optional version) { + Optional version) { this.environment = environment; this.headers = new HashMap<>(); this.headers.putAll(headers); @@ -41,8 +41,8 @@ private ClientOptions( this.headerSuppliers = headerSuppliers; this.httpClient = httpClient; this.timeout = timeout; - this.version = version.orElse("2.0.0"); - this.headers.put("X-API-Version", this.version); + this.version = version.orElse(ApiVersions.CURRENT); + this.headers.put("X-API-Version", this.version.toString()); } public Environment environment() { @@ -60,7 +60,7 @@ public Map headers(RequestOptions requestOptions) { return values; } - public String version() { + public ApiVersions version() { return this.version; } @@ -94,7 +94,7 @@ public static final class Builder { private int timeout = 60; - private Optional version; + private Optional version; public Builder environment(Environment environment) { this.environment = environment; @@ -119,7 +119,7 @@ public Builder timeout(int timeout) { return this; } - public Builder version(String version) { + public Builder version(ApiVersions version) { this.version = Optional.of(version); return this; } From 2d9c68a5bcdb15bc28fbe9c66291e389602b34f6 Mon Sep 17 00:00:00 2001 From: Alberto Date: Mon, 6 Jan 2025 18:09:44 -0500 Subject: [PATCH 09/20] singularize --- .../fern/java/client/ClientPoetClassNameFactory.java | 2 +- .../core/{ApiVersions.java => ApiVersion.java} | 4 ++-- .../java/com/seed/version/core/ClientOptions.java | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) rename seed/java-sdk/version/src/main/java/com/seed/version/core/{ApiVersions.java => ApiVersion.java} (87%) diff --git a/generators/java/sdk/src/main/java/com/fern/java/client/ClientPoetClassNameFactory.java b/generators/java/sdk/src/main/java/com/fern/java/client/ClientPoetClassNameFactory.java index 0247bf3a839..ae3ecbc6621 100644 --- a/generators/java/sdk/src/main/java/com/fern/java/client/ClientPoetClassNameFactory.java +++ b/generators/java/sdk/src/main/java/com/fern/java/client/ClientPoetClassNameFactory.java @@ -45,7 +45,7 @@ public ClassName getResponseBodyReaderClassName() { } public ClassName getApiVersionsClassName() { - return ClassName.get(getCorePackage(), "ApiVersions"); + return ClassName.get(getCorePackage(), "ApiVersion"); } public ClassName getRequestOptionsClassName() { diff --git a/seed/java-sdk/version/src/main/java/com/seed/version/core/ApiVersions.java b/seed/java-sdk/version/src/main/java/com/seed/version/core/ApiVersion.java similarity index 87% rename from seed/java-sdk/version/src/main/java/com/seed/version/core/ApiVersions.java rename to seed/java-sdk/version/src/main/java/com/seed/version/core/ApiVersion.java index 7a226d28824..03f90855fd0 100644 --- a/seed/java-sdk/version/src/main/java/com/seed/version/core/ApiVersions.java +++ b/seed/java-sdk/version/src/main/java/com/seed/version/core/ApiVersion.java @@ -5,7 +5,7 @@ import com.fasterxml.jackson.annotation.JsonValue; -public enum ApiVersions { +public enum ApiVersion { V_1("1.0.0"), V_2("2.0.0"), @@ -16,7 +16,7 @@ public enum ApiVersions { private final String value; - ApiVersions(String value) { + ApiVersion(String value) { this.value = value; } diff --git a/seed/java-sdk/version/src/main/java/com/seed/version/core/ClientOptions.java b/seed/java-sdk/version/src/main/java/com/seed/version/core/ClientOptions.java index e767bdf1887..adb6b34043e 100644 --- a/seed/java-sdk/version/src/main/java/com/seed/version/core/ClientOptions.java +++ b/seed/java-sdk/version/src/main/java/com/seed/version/core/ClientOptions.java @@ -21,7 +21,7 @@ public final class ClientOptions { private final int timeout; - private final ApiVersions version; + private final ApiVersion version; private ClientOptions( Environment environment, @@ -29,7 +29,7 @@ private ClientOptions( Map> headerSuppliers, OkHttpClient httpClient, int timeout, - Optional version) { + Optional version) { this.environment = environment; this.headers = new HashMap<>(); this.headers.putAll(headers); @@ -41,7 +41,7 @@ private ClientOptions( this.headerSuppliers = headerSuppliers; this.httpClient = httpClient; this.timeout = timeout; - this.version = version.orElse(ApiVersions.CURRENT); + this.version = version.orElse(ApiVersion.CURRENT); this.headers.put("X-API-Version", this.version.toString()); } @@ -60,7 +60,7 @@ public Map headers(RequestOptions requestOptions) { return values; } - public ApiVersions version() { + public ApiVersion version() { return this.version; } @@ -94,7 +94,7 @@ public static final class Builder { private int timeout = 60; - private Optional version; + private Optional version; public Builder environment(Environment environment) { this.environment = environment; @@ -119,7 +119,7 @@ public Builder timeout(int timeout) { return this; } - public Builder version(ApiVersions version) { + public Builder version(ApiVersion version) { this.version = Optional.of(version); return this; } From 48ad2ab5e2a0a4398fd26eefa35e5ec783866f89 Mon Sep 17 00:00:00 2001 From: Alberto Date: Mon, 6 Jan 2025 18:11:54 -0500 Subject: [PATCH 10/20] don't optimize import --- .../java/sdk/src/main/java/com/fern/java/client/Cli.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/generators/java/sdk/src/main/java/com/fern/java/client/Cli.java b/generators/java/sdk/src/main/java/com/fern/java/client/Cli.java index b0079cb66df..568305f96b4 100644 --- a/generators/java/sdk/src/main/java/com/fern/java/client/Cli.java +++ b/generators/java/sdk/src/main/java/com/fern/java/client/Cli.java @@ -37,7 +37,11 @@ import com.fern.java.client.generators.SubpackageClientGenerator; import com.fern.java.client.generators.SuppliersGenerator; import com.fern.java.client.generators.TestGenerator; -import com.fern.java.generators.*; +import com.fern.java.generators.DateTimeDeserializerGenerator; +import com.fern.java.generators.ObjectMappersGenerator; +import com.fern.java.generators.PaginationCoreGenerator; +import com.fern.java.generators.StreamGenerator; +import com.fern.java.generators.TypesGenerator; import com.fern.java.generators.TypesGenerator.Result; import com.fern.java.output.GeneratedFile; import com.fern.java.output.GeneratedJavaFile; From 079713a0f7c792f516611e49c9d90530eccb20a3 Mon Sep 17 00:00:00 2001 From: Alberto Date: Mon, 6 Jan 2025 18:19:03 -0500 Subject: [PATCH 11/20] reimport missing thing --- generators/java/sdk/src/main/java/com/fern/java/client/Cli.java | 1 + 1 file changed, 1 insertion(+) diff --git a/generators/java/sdk/src/main/java/com/fern/java/client/Cli.java b/generators/java/sdk/src/main/java/com/fern/java/client/Cli.java index 568305f96b4..ecd7ee9a7f0 100644 --- a/generators/java/sdk/src/main/java/com/fern/java/client/Cli.java +++ b/generators/java/sdk/src/main/java/com/fern/java/client/Cli.java @@ -38,6 +38,7 @@ import com.fern.java.client.generators.SuppliersGenerator; import com.fern.java.client.generators.TestGenerator; import com.fern.java.generators.DateTimeDeserializerGenerator; +import com.fern.java.generators.EnumGenerator; import com.fern.java.generators.ObjectMappersGenerator; import com.fern.java.generators.PaginationCoreGenerator; import com.fern.java.generators.StreamGenerator; From bbaccf4b897c27aa30cee971ce938afd681794fa Mon Sep 17 00:00:00 2001 From: Alberto Date: Mon, 6 Jan 2025 19:26:56 -0500 Subject: [PATCH 12/20] fix no default --- .../generators/ClientOptionsGenerator.java | 49 ++++++----- .../generators/RequestOptionsGenerator.java | 82 ++++++++++++++++++- .../com/seed/version/core/ApiVersion.java | 26 ++++++ .../com/seed/version/core/ClientOptions.java | 21 ++++- .../com/seed/version/core/RequestOptions.java | 21 ++++- .../com/seed/version/core/RequestOptions.java | 21 ++++- 6 files changed, 189 insertions(+), 31 deletions(-) create mode 100644 seed/java-sdk/version-no-default/src/main/java/com/seed/version/core/ApiVersion.java diff --git a/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java b/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java index 747a07fdce9..d39b60248c4 100644 --- a/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java +++ b/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java @@ -84,7 +84,7 @@ public final class ClientOptionsGenerator extends AbstractFileGenerator { private final FieldSpec environmentField; private final GeneratedJavaFile requestOptionsFile; private final ClientGeneratorContext clientGeneratorContext; - private final FieldSpec apiVersionsField; + private final FieldSpec apiVersionField; public ClientOptionsGenerator( ClientGeneratorContext clientGeneratorContext, @@ -100,7 +100,7 @@ public ClientOptionsGenerator( .build(); this.requestOptionsFile = requestOptionsFile; this.clientGeneratorContext = clientGeneratorContext; - this.apiVersionsField = FieldSpec.builder( + this.apiVersionField = FieldSpec.builder( clientGeneratorContext.getPoetClassNameFactory().getApiVersionsClassName(), "version", Modifier.PRIVATE, @@ -164,20 +164,19 @@ public GeneratedClientOptions generateFile() { apiVersionScheme.visit(new ApiVersionScheme.Visitor() { @Override public Void visitHeader(HeaderApiVersionScheme headerApiVersionScheme) { - constructorBuilder.addParameter(ParameterSpec.builder( - ParameterizedTypeName.get( - ClassName.get(Optional.class), - clientGeneratorContext - .getPoetClassNameFactory() - .getApiVersionsClassName()), - apiVersionsField.name) - .build()); - if (headerApiVersionScheme.getValue().getDefault().isPresent()) { + constructorBuilder.addParameter(ParameterSpec.builder( + ParameterizedTypeName.get( + ClassName.get(Optional.class), + clientGeneratorContext + .getPoetClassNameFactory() + .getApiVersionsClassName()), + apiVersionField.name) + .build()); constructorBuilder.addStatement( "this.$L = $L.orElse($L)", - apiVersionsField.name, - apiVersionsField.name, + apiVersionField.name, + apiVersionField.name, CodeBlock.of( "$T.$L", clientGeneratorContext @@ -185,14 +184,20 @@ public Void visitHeader(HeaderApiVersionScheme headerApiVersionScheme) { .getApiVersionsClassName(), ApiVersionConstants.CURRENT_API_VERSION)); } else { - constructorBuilder.addStatement("this.$L = $L", apiVersionsField.name, apiVersionsField.name); + constructorBuilder.addParameter(ParameterSpec.builder( + clientGeneratorContext + .getPoetClassNameFactory() + .getApiVersionsClassName(), + apiVersionField.name) + .build()); + constructorBuilder.addStatement("this.$L = $L", apiVersionField.name, apiVersionField.name); } constructorBuilder.addStatement( "this.$L.put($S,$L)", HEADERS_FIELD.name, headerApiVersionScheme.getHeader().getName().getWireValue(), - CodeBlock.of("this.$L.toString()", apiVersionsField.name)); + CodeBlock.of("this.$L.toString()", apiVersionField.name)); return null; } @@ -221,8 +226,8 @@ public Void _visitUnknown(Object _o) { .addMethod(headersFromRequestOptions); if (clientGeneratorContext.getIr().getApiVersion().isPresent()) { - clientOptionsBuilder.addField(apiVersionsField); - versionsGetter = Optional.of(createGetter(apiVersionsField)); + clientOptionsBuilder.addField(apiVersionField); + versionsGetter = Optional.of(createGetter(apiVersionField)); clientOptionsBuilder.addMethod(versionsGetter.get()); } @@ -368,7 +373,7 @@ private TypeSpec createBuilder(ClientGeneratorContext context, Map additionalHeaders; private final ClassName builderClassName; + private final ClientGeneratorContext clientGeneratorContext; - public RequestOptionsGenerator(AbstractGeneratorContext generatorContext, ClassName className) { + public RequestOptionsGenerator(ClientGeneratorContext generatorContext, ClassName className) { this(generatorContext, className, Collections.emptyList()); } public RequestOptionsGenerator( - AbstractGeneratorContext generatorContext, ClassName className, List additionalHeaders) { + ClientGeneratorContext generatorContext, ClassName className, List additionalHeaders) { super(className, generatorContext); this.builderClassName = className.nestedClass("Builder"); this.additionalHeaders = additionalHeaders; + this.clientGeneratorContext = generatorContext; } @Override @@ -80,6 +84,41 @@ public GeneratedJavaFile generateFile() { "$T headers = new $T<>()", ParameterizedTypeName.get(Map.class, String.class, String.class), HashMap.class); + + FieldSpec apiVersionField = FieldSpec.builder( + ParameterizedTypeName.get( + ClassName.get(Optional.class), + clientGeneratorContext.getPoetClassNameFactory().getApiVersionsClassName()), + "version", + Modifier.PRIVATE, + Modifier.FINAL) + .build(); + + if (clientGeneratorContext.getIr().getApiVersion().isPresent()) { + ApiVersionScheme apiVersionScheme = + clientGeneratorContext.getIr().getApiVersion().get(); + + apiVersionScheme.visit(new ApiVersionScheme.Visitor() { + @Override + public Void visitHeader(HeaderApiVersionScheme headerApiVersionScheme) { + getHeadersCodeBlock + .beginControlFlow("if (this.$N.isPresent())", apiVersionField) + .addStatement( + "headers.put($S,$L)", + headerApiVersionScheme.getHeader().getName().getWireValue(), + CodeBlock.of("this.$L.get().toString()", apiVersionField.name)) + .endControlFlow(); + + return null; + } + + @Override + public Void _visitUnknown(Object _o) { + throw new IllegalArgumentException("Received unknown API versioning schema type in IR."); + } + }); + } + HeaderHandler headerHandler = new HeaderHandler(requestOptionsTypeSpec, builderTypeSpec, getHeadersCodeBlock); AuthSchemeHandler authSchemeHandler = new AuthSchemeHandler(requestOptionsTypeSpec, builderTypeSpec, getHeadersCodeBlock, headerHandler); @@ -127,6 +166,31 @@ public GeneratedJavaFile generateFile() { builderTypeSpec, fields); + if (clientGeneratorContext.getIr().getApiVersion().isPresent()) { + ApiVersionScheme apiVersionScheme = + clientGeneratorContext.getIr().getApiVersion().get(); + + apiVersionScheme.visit(new ApiVersionScheme.Visitor() { + @Override + public Void visitHeader(HeaderApiVersionScheme headerApiVersionScheme) { + createRequestOptionField( + "getVersion", + apiVersionField.toBuilder(), + CodeBlock.of("$T.empty()", Optional.class), + requestOptionsTypeSpec, + builderTypeSpec, + fields); + + return null; + } + + @Override + public Void _visitUnknown(Object _o) { + throw new IllegalArgumentException("Received unknown API versioning schema type in IR."); + } + }); + } + FieldSpec timeoutField = timeoutFieldBuilder.build(); FieldSpec timeUnitField = timeoutTimeUnitFieldBuilder.build(); builderTypeSpec.addMethod(MethodSpec.methodBuilder(timeoutField.name) @@ -147,6 +211,18 @@ public GeneratedJavaFile generateFile() { .returns(builderClassName) .build()); + if (clientGeneratorContext.getIr().getApiVersion().isPresent()) { + builderTypeSpec.addMethod(MethodSpec.methodBuilder(apiVersionField.name) + .addModifiers(Modifier.PUBLIC) + .addParameter( + clientGeneratorContext.getPoetClassNameFactory().getApiVersionsClassName(), + apiVersionField.name) + .addStatement("this.$L = Optional.of($L)", apiVersionField.name, apiVersionField.name) + .addStatement("return this") + .returns(builderClassName) + .build()); + } + String constructorArgs = fields.stream().map(field -> field.builderField.name).collect(Collectors.joining(", ")); builderTypeSpec.addMethod(MethodSpec.methodBuilder("build") diff --git a/seed/java-sdk/version-no-default/src/main/java/com/seed/version/core/ApiVersion.java b/seed/java-sdk/version-no-default/src/main/java/com/seed/version/core/ApiVersion.java new file mode 100644 index 00000000000..5b8abd3eaa0 --- /dev/null +++ b/seed/java-sdk/version-no-default/src/main/java/com/seed/version/core/ApiVersion.java @@ -0,0 +1,26 @@ +/** + * This file was auto-generated by Fern from our API Definition. + */ +package com.seed.version.core; + +import com.fasterxml.jackson.annotation.JsonValue; + +public enum ApiVersion { + _1_0_0("1.0.0"), + + _2_0_0("2.0.0"), + + LATEST("latest"); + + private final String value; + + ApiVersion(String value) { + this.value = value; + } + + @JsonValue + @java.lang.Override + public String toString() { + return this.value; + } +} diff --git a/seed/java-sdk/version-no-default/src/main/java/com/seed/version/core/ClientOptions.java b/seed/java-sdk/version-no-default/src/main/java/com/seed/version/core/ClientOptions.java index 1cf23912bcd..aebea843e03 100644 --- a/seed/java-sdk/version-no-default/src/main/java/com/seed/version/core/ClientOptions.java +++ b/seed/java-sdk/version-no-default/src/main/java/com/seed/version/core/ClientOptions.java @@ -5,6 +5,7 @@ import java.util.HashMap; import java.util.Map; +import java.util.Optional; import java.util.concurrent.TimeUnit; import java.util.function.Supplier; import okhttp3.OkHttpClient; @@ -20,12 +21,15 @@ public final class ClientOptions { private final int timeout; + private final ApiVersion version; + private ClientOptions( Environment environment, Map headers, Map> headerSuppliers, OkHttpClient httpClient, - int timeout) { + int timeout, + ApiVersion version) { this.environment = environment; this.headers = new HashMap<>(); this.headers.putAll(headers); @@ -37,6 +41,8 @@ private ClientOptions( this.headerSuppliers = headerSuppliers; this.httpClient = httpClient; this.timeout = timeout; + this.version = version; + this.headers.put("X-API-Version", this.version.toString()); } public Environment environment() { @@ -54,6 +60,10 @@ public Map headers(RequestOptions requestOptions) { return values; } + public ApiVersion version() { + return this.version; + } + public OkHttpClient httpClient() { return this.httpClient; } @@ -84,6 +94,8 @@ public static final class Builder { private int timeout = 60; + private Optional version; + public Builder environment(Environment environment) { this.environment = environment; return this; @@ -107,12 +119,17 @@ public Builder timeout(int timeout) { return this; } + public Builder version(ApiVersion version) { + this.version = Optional.of(version); + return this; + } + public ClientOptions build() { OkHttpClient okhttpClient = new OkHttpClient.Builder() .addInterceptor(new RetryInterceptor(3)) .callTimeout(this.timeout, TimeUnit.SECONDS) .build(); - return new ClientOptions(environment, headers, headerSuppliers, okhttpClient, this.timeout); + return new ClientOptions(environment, headers, headerSuppliers, okhttpClient, this.timeout, version); } } } diff --git a/seed/java-sdk/version-no-default/src/main/java/com/seed/version/core/RequestOptions.java b/seed/java-sdk/version-no-default/src/main/java/com/seed/version/core/RequestOptions.java index de8c713d8f4..365a5a68de4 100644 --- a/seed/java-sdk/version-no-default/src/main/java/com/seed/version/core/RequestOptions.java +++ b/seed/java-sdk/version-no-default/src/main/java/com/seed/version/core/RequestOptions.java @@ -13,9 +13,12 @@ public final class RequestOptions { private final TimeUnit timeoutTimeUnit; - private RequestOptions(Optional timeout, TimeUnit timeoutTimeUnit) { + private final Optional version; + + private RequestOptions(Optional timeout, TimeUnit timeoutTimeUnit, Optional version) { this.timeout = timeout; this.timeoutTimeUnit = timeoutTimeUnit; + this.version = version; } public Optional getTimeout() { @@ -26,8 +29,15 @@ public TimeUnit getTimeoutTimeUnit() { return timeoutTimeUnit; } + public Optional getVersion() { + return version; + } + public Map getHeaders() { Map headers = new HashMap<>(); + if (this.version.isPresent()) { + headers.put("X-API-Version", this.version.get().toString()); + } return headers; } @@ -40,6 +50,8 @@ public static final class Builder { private TimeUnit timeoutTimeUnit = TimeUnit.SECONDS; + private Optional version = Optional.empty(); + public Builder timeout(Integer timeout) { this.timeout = Optional.of(timeout); return this; @@ -51,8 +63,13 @@ public Builder timeout(Integer timeout, TimeUnit timeoutTimeUnit) { return this; } + public Builder version(ApiVersion version) { + this.version = Optional.of(version); + return this; + } + public RequestOptions build() { - return new RequestOptions(timeout, timeoutTimeUnit); + return new RequestOptions(timeout, timeoutTimeUnit, version); } } } diff --git a/seed/java-sdk/version/src/main/java/com/seed/version/core/RequestOptions.java b/seed/java-sdk/version/src/main/java/com/seed/version/core/RequestOptions.java index de8c713d8f4..365a5a68de4 100644 --- a/seed/java-sdk/version/src/main/java/com/seed/version/core/RequestOptions.java +++ b/seed/java-sdk/version/src/main/java/com/seed/version/core/RequestOptions.java @@ -13,9 +13,12 @@ public final class RequestOptions { private final TimeUnit timeoutTimeUnit; - private RequestOptions(Optional timeout, TimeUnit timeoutTimeUnit) { + private final Optional version; + + private RequestOptions(Optional timeout, TimeUnit timeoutTimeUnit, Optional version) { this.timeout = timeout; this.timeoutTimeUnit = timeoutTimeUnit; + this.version = version; } public Optional getTimeout() { @@ -26,8 +29,15 @@ public TimeUnit getTimeoutTimeUnit() { return timeoutTimeUnit; } + public Optional getVersion() { + return version; + } + public Map getHeaders() { Map headers = new HashMap<>(); + if (this.version.isPresent()) { + headers.put("X-API-Version", this.version.get().toString()); + } return headers; } @@ -40,6 +50,8 @@ public static final class Builder { private TimeUnit timeoutTimeUnit = TimeUnit.SECONDS; + private Optional version = Optional.empty(); + public Builder timeout(Integer timeout) { this.timeout = Optional.of(timeout); return this; @@ -51,8 +63,13 @@ public Builder timeout(Integer timeout, TimeUnit timeoutTimeUnit) { return this; } + public Builder version(ApiVersion version) { + this.version = Optional.of(version); + return this; + } + public RequestOptions build() { - return new RequestOptions(timeout, timeoutTimeUnit); + return new RequestOptions(timeout, timeoutTimeUnit, version); } } } From 46ec661bd23b3df2d3c26866e90b8fd3625d728c Mon Sep 17 00:00:00 2001 From: Alberto Date: Tue, 7 Jan 2025 09:36:55 -0500 Subject: [PATCH 13/20] Fix no default generation --- .../generators/ClientOptionsGenerator.java | 54 +++++++++++++++---- .../com/seed/version/core/ClientOptions.java | 5 +- 2 files changed, 47 insertions(+), 12 deletions(-) diff --git a/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java b/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java index d39b60248c4..5411f76a0c2 100644 --- a/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java +++ b/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java @@ -369,14 +369,38 @@ private TypeSpec createBuilder(ClientGeneratorContext context, Map() { + @Override + public Void visitHeader(HeaderApiVersionScheme headerApiVersionScheme) { + if (headerApiVersionScheme.getValue().getDefault().isPresent()) { + builder.addField(FieldSpec.builder( + ParameterizedTypeName.get( + ClassName.get(Optional.class), + context.getPoetClassNameFactory() + .getApiVersionsClassName()), + apiVersionField.name, + Modifier.PRIVATE) + .build()); + builder.addMethod(getOptionalVersionBuilder()); + } else { + builder.addField(FieldSpec.builder( + context.getPoetClassNameFactory().getApiVersionsClassName(), + apiVersionField.name, + Modifier.PRIVATE) + .build()); + builder.addMethod(getRequiredVersionBuilder()); + } + + return null; + } + + @Override + public Void _visitUnknown(Object _o) { + throw new IllegalArgumentException("Received unknown API versioning schema type in IR."); + } + }); } builder.addMethod(getBuildMethod(context, variableFields)); @@ -405,7 +429,7 @@ private MethodSpec getHeaderBuilder() { .build(); } - private MethodSpec getVersionBuilder() { + private MethodSpec getOptionalVersionBuilder() { return MethodSpec.methodBuilder(apiVersionField.name) .addModifiers(Modifier.PUBLIC) .returns(builderClassName) @@ -417,6 +441,18 @@ private MethodSpec getVersionBuilder() { .build(); } + private MethodSpec getRequiredVersionBuilder() { + return MethodSpec.methodBuilder(apiVersionField.name) + .addModifiers(Modifier.PUBLIC) + .returns(builderClassName) + .addParameter( + clientGeneratorContext.getPoetClassNameFactory().getApiVersionsClassName(), + apiVersionField.name) + .addStatement("this.$L = $L", apiVersionField.name, apiVersionField.name) + .addStatement("return this") + .build(); + } + private MethodSpec getHeaderSupplierBuilder() { return MethodSpec.methodBuilder("addHeader") .addModifiers(Modifier.PUBLIC) diff --git a/seed/java-sdk/version-no-default/src/main/java/com/seed/version/core/ClientOptions.java b/seed/java-sdk/version-no-default/src/main/java/com/seed/version/core/ClientOptions.java index aebea843e03..56ddbe340f8 100644 --- a/seed/java-sdk/version-no-default/src/main/java/com/seed/version/core/ClientOptions.java +++ b/seed/java-sdk/version-no-default/src/main/java/com/seed/version/core/ClientOptions.java @@ -5,7 +5,6 @@ import java.util.HashMap; import java.util.Map; -import java.util.Optional; import java.util.concurrent.TimeUnit; import java.util.function.Supplier; import okhttp3.OkHttpClient; @@ -94,7 +93,7 @@ public static final class Builder { private int timeout = 60; - private Optional version; + private ApiVersion version; public Builder environment(Environment environment) { this.environment = environment; @@ -120,7 +119,7 @@ public Builder timeout(int timeout) { } public Builder version(ApiVersion version) { - this.version = Optional.of(version); + this.version = version; return this; } From b1739506d9e2cbeda9a60aeaba16fee2d2be36f5 Mon Sep 17 00:00:00 2001 From: Alberto Date: Tue, 7 Jan 2025 10:09:21 -0500 Subject: [PATCH 14/20] Move constants into sdk project and declare name in constants file --- .../fern/java/utils/ApiVersionConstants.java | 5 --- .../fern/java/client/ApiVersionConstants.java | 33 +++++++++++++++++++ .../main/java/com/fern/java/client/Cli.java | 23 +------------ .../generators/ClientOptionsGenerator.java | 2 +- 4 files changed, 35 insertions(+), 28 deletions(-) delete mode 100644 generators/java/generator-utils/src/main/java/com/fern/java/utils/ApiVersionConstants.java create mode 100644 generators/java/sdk/src/main/java/com/fern/java/client/ApiVersionConstants.java diff --git a/generators/java/generator-utils/src/main/java/com/fern/java/utils/ApiVersionConstants.java b/generators/java/generator-utils/src/main/java/com/fern/java/utils/ApiVersionConstants.java deleted file mode 100644 index 9c201d7670b..00000000000 --- a/generators/java/generator-utils/src/main/java/com/fern/java/utils/ApiVersionConstants.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.fern.java.utils; - -public final class ApiVersionConstants { - public static final String CURRENT_API_VERSION = "CURRENT"; -} diff --git a/generators/java/sdk/src/main/java/com/fern/java/client/ApiVersionConstants.java b/generators/java/sdk/src/main/java/com/fern/java/client/ApiVersionConstants.java new file mode 100644 index 00000000000..944faa6fdce --- /dev/null +++ b/generators/java/sdk/src/main/java/com/fern/java/client/ApiVersionConstants.java @@ -0,0 +1,33 @@ +package com.fern.java.client; + +import com.fern.ir.model.commons.Name; +import com.fern.ir.model.commons.SafeAndUnsafeString; + +public final class ApiVersionConstants { + /** + * Do not instantiate utils class. + */ + private ApiVersionConstants() {} + + public static final String CURRENT_API_VERSION = "CURRENT"; + + public static final Name CURRENT_API_VERSION_NAME = Name.builder() + .originalName("CURRENT") + .camelCase(SafeAndUnsafeString.builder() + .unsafeName("current") + .safeName("current") + .build()) + .pascalCase(SafeAndUnsafeString.builder() + .unsafeName("Current") + .safeName("Current") + .build()) + .snakeCase(SafeAndUnsafeString.builder() + .unsafeName("current") + .safeName("current") + .build()) + .screamingSnakeCase(SafeAndUnsafeString.builder() + .unsafeName("CURRENT") + .safeName("CURRENT") + .build()) + .build(); +} diff --git a/generators/java/sdk/src/main/java/com/fern/java/client/Cli.java b/generators/java/sdk/src/main/java/com/fern/java/client/Cli.java index ecd7ee9a7f0..9dadac6c67c 100644 --- a/generators/java/sdk/src/main/java/com/fern/java/client/Cli.java +++ b/generators/java/sdk/src/main/java/com/fern/java/client/Cli.java @@ -52,7 +52,6 @@ import com.fern.java.output.gradle.GradleDependency; import com.fern.java.output.gradle.GradleDependencyType; import com.fern.java.output.gradle.ParsedGradleDependency; -import com.fern.java.utils.ApiVersionConstants; import com.palantir.common.streams.KeyedStream; import java.util.ArrayList; import java.util.Collections; @@ -198,31 +197,11 @@ public GeneratedRootClient generateClient( EnumTypeDeclaration.builder().from(irDeclaration); irDeclaration.getDefault().ifPresent(defaultValue -> { - Name current = Name.builder() - .originalName(ApiVersionConstants.CURRENT_API_VERSION) - .camelCase(SafeAndUnsafeString.builder() - .unsafeName(ApiVersionConstants.CURRENT_API_VERSION) - .safeName(ApiVersionConstants.CURRENT_API_VERSION) - .build()) - .pascalCase(SafeAndUnsafeString.builder() - .unsafeName(ApiVersionConstants.CURRENT_API_VERSION) - .safeName(ApiVersionConstants.CURRENT_API_VERSION) - .build()) - .snakeCase(SafeAndUnsafeString.builder() - .unsafeName(ApiVersionConstants.CURRENT_API_VERSION) - .safeName(ApiVersionConstants.CURRENT_API_VERSION) - .build()) - .screamingSnakeCase(SafeAndUnsafeString.builder() - .unsafeName(ApiVersionConstants.CURRENT_API_VERSION) - .safeName(ApiVersionConstants.CURRENT_API_VERSION) - .build()) - .build(); - enumTypeDeclaration.addValues(EnumValue.builder() .from(defaultValue) .name(NameAndWireValue.builder() .from(defaultValue.getName()) - .name(current) + .name(ApiVersionConstants.CURRENT_API_VERSION_NAME) .build()) .build()); }); diff --git a/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java b/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java index 5411f76a0c2..3dac720794f 100644 --- a/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java +++ b/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java @@ -22,12 +22,12 @@ import com.fern.ir.model.ir.PlatformHeaders; import com.fern.ir.model.variables.VariableDeclaration; import com.fern.ir.model.variables.VariableId; +import com.fern.java.client.ApiVersionConstants; import com.fern.java.client.ClientGeneratorContext; import com.fern.java.client.GeneratedClientOptions; import com.fern.java.client.GeneratedEnvironmentsClass; import com.fern.java.generators.AbstractFileGenerator; import com.fern.java.output.GeneratedJavaFile; -import com.fern.java.utils.ApiVersionConstants; import com.google.common.collect.ImmutableList; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.CodeBlock; From 92ac176f474ba4da68325e7f255e57b9cccdd4fb Mon Sep 17 00:00:00 2001 From: Alberto Date: Tue, 7 Jan 2025 10:12:06 -0500 Subject: [PATCH 15/20] Format --- .../main/java/com/fern/java/client/ApiVersionConstants.java | 4 +--- .../java/sdk/src/main/java/com/fern/java/client/Cli.java | 2 -- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/generators/java/sdk/src/main/java/com/fern/java/client/ApiVersionConstants.java b/generators/java/sdk/src/main/java/com/fern/java/client/ApiVersionConstants.java index 944faa6fdce..93dbe8e89d8 100644 --- a/generators/java/sdk/src/main/java/com/fern/java/client/ApiVersionConstants.java +++ b/generators/java/sdk/src/main/java/com/fern/java/client/ApiVersionConstants.java @@ -4,9 +4,7 @@ import com.fern.ir.model.commons.SafeAndUnsafeString; public final class ApiVersionConstants { - /** - * Do not instantiate utils class. - */ + /** Do not instantiate utils class. */ private ApiVersionConstants() {} public static final String CURRENT_API_VERSION = "CURRENT"; diff --git a/generators/java/sdk/src/main/java/com/fern/java/client/Cli.java b/generators/java/sdk/src/main/java/com/fern/java/client/Cli.java index 9dadac6c67c..68f839f5d7e 100644 --- a/generators/java/sdk/src/main/java/com/fern/java/client/Cli.java +++ b/generators/java/sdk/src/main/java/com/fern/java/client/Cli.java @@ -8,9 +8,7 @@ import com.fern.ir.model.auth.AuthScheme; import com.fern.ir.model.auth.OAuthScheme; import com.fern.ir.model.commons.ErrorId; -import com.fern.ir.model.commons.Name; import com.fern.ir.model.commons.NameAndWireValue; -import com.fern.ir.model.commons.SafeAndUnsafeString; import com.fern.ir.model.ir.HeaderApiVersionScheme; import com.fern.ir.model.ir.IntermediateRepresentation; import com.fern.ir.model.types.EnumTypeDeclaration; From 3ac35084907ec8fb93d1f6944c1ed0276a4ca2ab Mon Sep 17 00:00:00 2001 From: Alberto Date: Tue, 7 Jan 2025 10:48:41 -0500 Subject: [PATCH 16/20] Methodize visitor actions --- .../main/java/com/fern/java/client/Cli.java | 2 +- .../client/ClientPoetClassNameFactory.java | 2 +- .../generators/ClientOptionsGenerator.java | 148 ++++++++++-------- .../generators/RequestOptionsGenerator.java | 56 ++++--- 4 files changed, 111 insertions(+), 97 deletions(-) diff --git a/generators/java/sdk/src/main/java/com/fern/java/client/Cli.java b/generators/java/sdk/src/main/java/com/fern/java/client/Cli.java index 68f839f5d7e..b982f0fe804 100644 --- a/generators/java/sdk/src/main/java/com/fern/java/client/Cli.java +++ b/generators/java/sdk/src/main/java/com/fern/java/client/Cli.java @@ -205,7 +205,7 @@ public GeneratedRootClient generateClient( }); EnumGenerator apiVersionsGenerator = new EnumGenerator( - context.getPoetClassNameFactory().getApiVersionsClassName(), + context.getPoetClassNameFactory().getApiVersionClassName(), context, enumTypeDeclaration.build()); GeneratedJavaFile generatedApiVersions = apiVersionsGenerator.generateFile(); diff --git a/generators/java/sdk/src/main/java/com/fern/java/client/ClientPoetClassNameFactory.java b/generators/java/sdk/src/main/java/com/fern/java/client/ClientPoetClassNameFactory.java index ae3ecbc6621..de72bca155f 100644 --- a/generators/java/sdk/src/main/java/com/fern/java/client/ClientPoetClassNameFactory.java +++ b/generators/java/sdk/src/main/java/com/fern/java/client/ClientPoetClassNameFactory.java @@ -44,7 +44,7 @@ public ClassName getResponseBodyReaderClassName() { return ClassName.get(getCorePackage(), "ResponseBodyReader"); } - public ClassName getApiVersionsClassName() { + public ClassName getApiVersionClassName() { return ClassName.get(getCorePackage(), "ApiVersion"); } diff --git a/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java b/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java index 3dac720794f..1bca8eb521e 100644 --- a/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java +++ b/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java @@ -101,7 +101,7 @@ public ClientOptionsGenerator( this.requestOptionsFile = requestOptionsFile; this.clientGeneratorContext = clientGeneratorContext; this.apiVersionField = FieldSpec.builder( - clientGeneratorContext.getPoetClassNameFactory().getApiVersionsClassName(), + clientGeneratorContext.getPoetClassNameFactory().getApiVersionClassName(), "version", Modifier.PRIVATE, Modifier.FINAL) @@ -157,57 +157,7 @@ public GeneratedClientOptions generateFile() { .addStatement("this.$L = $L", OKHTTP_CLIENT_FIELD.name, OKHTTP_CLIENT_FIELD.name) .addStatement("this.$L = $L", TIMEOUT_FIELD.name, TIMEOUT_FIELD.name); - if (clientGeneratorContext.getIr().getApiVersion().isPresent()) { - ApiVersionScheme apiVersionScheme = - clientGeneratorContext.getIr().getApiVersion().get(); - - apiVersionScheme.visit(new ApiVersionScheme.Visitor() { - @Override - public Void visitHeader(HeaderApiVersionScheme headerApiVersionScheme) { - if (headerApiVersionScheme.getValue().getDefault().isPresent()) { - constructorBuilder.addParameter(ParameterSpec.builder( - ParameterizedTypeName.get( - ClassName.get(Optional.class), - clientGeneratorContext - .getPoetClassNameFactory() - .getApiVersionsClassName()), - apiVersionField.name) - .build()); - constructorBuilder.addStatement( - "this.$L = $L.orElse($L)", - apiVersionField.name, - apiVersionField.name, - CodeBlock.of( - "$T.$L", - clientGeneratorContext - .getPoetClassNameFactory() - .getApiVersionsClassName(), - ApiVersionConstants.CURRENT_API_VERSION)); - } else { - constructorBuilder.addParameter(ParameterSpec.builder( - clientGeneratorContext - .getPoetClassNameFactory() - .getApiVersionsClassName(), - apiVersionField.name) - .build()); - constructorBuilder.addStatement("this.$L = $L", apiVersionField.name, apiVersionField.name); - } - - constructorBuilder.addStatement( - "this.$L.put($S,$L)", - HEADERS_FIELD.name, - headerApiVersionScheme.getHeader().getName().getWireValue(), - CodeBlock.of("this.$L.toString()", apiVersionField.name)); - - return null; - } - - @Override - public Void _visitUnknown(Object _o) { - throw new IllegalArgumentException("Received unknown API versioning schema type in IR."); - } - }); - } + addApiVersionToConstructor(constructorBuilder); variableFields .values() @@ -289,7 +239,7 @@ public Void _visitUnknown(Object _o) { .returns(builderClassName) .addStatement("return new $T()", builderClassName) .build()) - .addType(createBuilder(clientGeneratorContext, variableFields)) + .addType(createBuilder(variableFields)) .build(); JavaFile environmentsFile = @@ -306,6 +256,60 @@ public Void _visitUnknown(Object _o) { .build(); } + private void addApiVersionToConstructor(MethodSpec.Builder constructorBuilder) { + if (clientGeneratorContext.getIr().getApiVersion().isPresent()) { + ApiVersionScheme apiVersionScheme = + clientGeneratorContext.getIr().getApiVersion().get(); + + apiVersionScheme.visit(new ApiVersionScheme.Visitor() { + @Override + public Void visitHeader(HeaderApiVersionScheme headerApiVersionScheme) { + if (headerApiVersionScheme.getValue().getDefault().isPresent()) { + constructorBuilder.addParameter(ParameterSpec.builder( + ParameterizedTypeName.get( + ClassName.get(Optional.class), + clientGeneratorContext + .getPoetClassNameFactory() + .getApiVersionClassName()), + apiVersionField.name) + .build()); + constructorBuilder.addStatement( + "this.$L = $L.orElse($L)", + apiVersionField.name, + apiVersionField.name, + CodeBlock.of( + "$T.$L", + clientGeneratorContext + .getPoetClassNameFactory() + .getApiVersionClassName(), + ApiVersionConstants.CURRENT_API_VERSION)); + } else { + constructorBuilder.addParameter(ParameterSpec.builder( + clientGeneratorContext + .getPoetClassNameFactory() + .getApiVersionClassName(), + apiVersionField.name) + .build()); + constructorBuilder.addStatement("this.$L = $L", apiVersionField.name, apiVersionField.name); + } + + constructorBuilder.addStatement( + "this.$L.put($S,$L)", + HEADERS_FIELD.name, + headerApiVersionScheme.getHeader().getName().getWireValue(), + CodeBlock.of("this.$L.toString()", apiVersionField.name)); + + return null; + } + + @Override + public Void _visitUnknown(Object _o) { + throw new IllegalArgumentException("Received unknown API versioning schema type in IR."); + } + }); + } + } + private MethodSpec headersFromRequestOptions() { return constructHeadersMethod() .addParameter( @@ -339,7 +343,7 @@ private MethodSpec.Builder constructHeadersMethod() { .addStatement("return values"); } - private TypeSpec createBuilder(ClientGeneratorContext context, Map variableFields) { + private TypeSpec createBuilder(Map variableFields) { TypeSpec.Builder builder = TypeSpec.classBuilder(builderClassName) .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) .addField(FieldSpec.builder(environmentField.type, environmentField.name) @@ -368,8 +372,17 @@ private TypeSpec createBuilder(ClientGeneratorContext context, Map() { @Override @@ -378,15 +391,18 @@ public Void visitHeader(HeaderApiVersionScheme headerApiVersionScheme) { builder.addField(FieldSpec.builder( ParameterizedTypeName.get( ClassName.get(Optional.class), - context.getPoetClassNameFactory() - .getApiVersionsClassName()), + clientGeneratorContext + .getPoetClassNameFactory() + .getApiVersionClassName()), apiVersionField.name, Modifier.PRIVATE) .build()); builder.addMethod(getOptionalVersionBuilder()); } else { builder.addField(FieldSpec.builder( - context.getPoetClassNameFactory().getApiVersionsClassName(), + clientGeneratorContext + .getPoetClassNameFactory() + .getApiVersionClassName(), apiVersionField.name, Modifier.PRIVATE) .build()); @@ -402,10 +418,6 @@ public Void _visitUnknown(Object _o) { } }); } - - builder.addMethod(getBuildMethod(context, variableFields)); - - return builder.build(); } private MethodSpec getEnvironmentBuilder() { @@ -434,8 +446,7 @@ private MethodSpec getOptionalVersionBuilder() { .addModifiers(Modifier.PUBLIC) .returns(builderClassName) .addParameter( - clientGeneratorContext.getPoetClassNameFactory().getApiVersionsClassName(), - apiVersionField.name) + clientGeneratorContext.getPoetClassNameFactory().getApiVersionClassName(), apiVersionField.name) .addStatement("this.$L = $T.of($L)", apiVersionField.name, Optional.class, apiVersionField.name) .addStatement("return this") .build(); @@ -446,8 +457,7 @@ private MethodSpec getRequiredVersionBuilder() { .addModifiers(Modifier.PUBLIC) .returns(builderClassName) .addParameter( - clientGeneratorContext.getPoetClassNameFactory().getApiVersionsClassName(), - apiVersionField.name) + clientGeneratorContext.getPoetClassNameFactory().getApiVersionClassName(), apiVersionField.name) .addStatement("this.$L = $L", apiVersionField.name, apiVersionField.name) .addStatement("return this") .build(); @@ -513,14 +523,14 @@ private Map getVariableGetters(Map variableFields) { + private MethodSpec getBuildMethod(Map variableFields) { ImmutableList.Builder argsBuilder = ImmutableList.builder(); argsBuilder.add( className, environmentField.name, HEADERS_FIELD.name, HEADER_SUPPLIERS_FIELD.name, "okhttpClient"); String returnString = "return new $T($L, $L, $L, $L, this.timeout"; - if (context.getIr().getApiVersion().isPresent()) { + if (clientGeneratorContext.getIr().getApiVersion().isPresent()) { argsBuilder.add(apiVersionField.name); returnString = "return new $T($L, $L, $L, $L, this.timeout, $L"; } diff --git a/generators/java/sdk/src/main/java/com/fern/java/client/generators/RequestOptionsGenerator.java b/generators/java/sdk/src/main/java/com/fern/java/client/generators/RequestOptionsGenerator.java index aa64baf775f..1eb11e2734c 100644 --- a/generators/java/sdk/src/main/java/com/fern/java/client/generators/RequestOptionsGenerator.java +++ b/generators/java/sdk/src/main/java/com/fern/java/client/generators/RequestOptionsGenerator.java @@ -88,36 +88,13 @@ public GeneratedJavaFile generateFile() { FieldSpec apiVersionField = FieldSpec.builder( ParameterizedTypeName.get( ClassName.get(Optional.class), - clientGeneratorContext.getPoetClassNameFactory().getApiVersionsClassName()), + clientGeneratorContext.getPoetClassNameFactory().getApiVersionClassName()), "version", Modifier.PRIVATE, Modifier.FINAL) .build(); - if (clientGeneratorContext.getIr().getApiVersion().isPresent()) { - ApiVersionScheme apiVersionScheme = - clientGeneratorContext.getIr().getApiVersion().get(); - - apiVersionScheme.visit(new ApiVersionScheme.Visitor() { - @Override - public Void visitHeader(HeaderApiVersionScheme headerApiVersionScheme) { - getHeadersCodeBlock - .beginControlFlow("if (this.$N.isPresent())", apiVersionField) - .addStatement( - "headers.put($S,$L)", - headerApiVersionScheme.getHeader().getName().getWireValue(), - CodeBlock.of("this.$L.get().toString()", apiVersionField.name)) - .endControlFlow(); - - return null; - } - - @Override - public Void _visitUnknown(Object _o) { - throw new IllegalArgumentException("Received unknown API versioning schema type in IR."); - } - }); - } + addApiVersionHeader(getHeadersCodeBlock, apiVersionField); HeaderHandler headerHandler = new HeaderHandler(requestOptionsTypeSpec, builderTypeSpec, getHeadersCodeBlock); AuthSchemeHandler authSchemeHandler = @@ -215,7 +192,7 @@ public Void _visitUnknown(Object _o) { builderTypeSpec.addMethod(MethodSpec.methodBuilder(apiVersionField.name) .addModifiers(Modifier.PUBLIC) .addParameter( - clientGeneratorContext.getPoetClassNameFactory().getApiVersionsClassName(), + clientGeneratorContext.getPoetClassNameFactory().getApiVersionClassName(), apiVersionField.name) .addStatement("this.$L = Optional.of($L)", apiVersionField.name, apiVersionField.name) .addStatement("return this") @@ -286,6 +263,33 @@ private void createRequestOptionField( .build()); } + private void addApiVersionHeader(CodeBlock.Builder getHeadersCodeBlock, FieldSpec apiVersionField) { + if (clientGeneratorContext.getIr().getApiVersion().isPresent()) { + ApiVersionScheme apiVersionScheme = + clientGeneratorContext.getIr().getApiVersion().get(); + + apiVersionScheme.visit(new ApiVersionScheme.Visitor() { + @Override + public Void visitHeader(HeaderApiVersionScheme headerApiVersionScheme) { + getHeadersCodeBlock + .beginControlFlow("if (this.$N.isPresent())", apiVersionField) + .addStatement( + "headers.put($S,$L)", + headerApiVersionScheme.getHeader().getName().getWireValue(), + CodeBlock.of("this.$L.get().toString()", apiVersionField.name)) + .endControlFlow(); + + return null; + } + + @Override + public Void _visitUnknown(Object _o) { + throw new IllegalArgumentException("Received unknown API versioning schema type in IR."); + } + }); + } + } + private static class RequestOption { private final FieldSpec builderField; private final FieldSpec requestOptionsField; From 3754b475f5206d822abc43585cefd0bb8efaf2ae Mon Sep 17 00:00:00 2001 From: Alberto Date: Tue, 7 Jan 2025 11:49:49 -0500 Subject: [PATCH 17/20] add javadocs --- .../generators/ClientOptionsGenerator.java | 57 +++++++++++++++---- .../com/seed/version/core/ClientOptions.java | 9 +++ .../com/seed/version/core/ClientOptions.java | 35 ++++++++++++ 3 files changed, 91 insertions(+), 10 deletions(-) diff --git a/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java b/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java index 1bca8eb521e..aa8dad7b16e 100644 --- a/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java +++ b/generators/java/sdk/src/main/java/com/fern/java/client/generators/ClientOptionsGenerator.java @@ -112,7 +112,6 @@ public ClientOptionsGenerator( public GeneratedClientOptions generateFile() { MethodSpec environmentGetter = createGetter(environmentField); MethodSpec headersFromRequestOptions = headersFromRequestOptions(); - Optional versionsGetter; Optional headersFromIdempotentRequestOptions = headersFromIdempotentRequestOptions(); MethodSpec httpClientGetter = createGetter(OKHTTP_CLIENT_FIELD); Map variableFields = getVariableFields(); @@ -175,11 +174,7 @@ public GeneratedClientOptions generateFile() { .addMethod(environmentGetter) .addMethod(headersFromRequestOptions); - if (clientGeneratorContext.getIr().getApiVersion().isPresent()) { - clientOptionsBuilder.addField(apiVersionField); - versionsGetter = Optional.of(createGetter(apiVersionField)); - clientOptionsBuilder.addMethod(versionsGetter.get()); - } + addApiVersionField(clientOptionsBuilder); if (headersFromIdempotentRequestOptions.isPresent()) { clientOptionsBuilder.addMethod(headersFromIdempotentRequestOptions.get()); @@ -256,6 +251,38 @@ public GeneratedClientOptions generateFile() { .build(); } + private void addApiVersionField(TypeSpec.Builder clientOptionsBuilder) { + if (clientGeneratorContext.getIr().getApiVersion().isPresent()) { + ApiVersionScheme apiVersionScheme = + clientGeneratorContext.getIr().getApiVersion().get(); + + apiVersionScheme.visit(new ApiVersionScheme.Visitor() { + @Override + public Void visitHeader(HeaderApiVersionScheme headerApiVersionScheme) { + clientOptionsBuilder.addField(apiVersionField.toBuilder() + .addJavadoc( + "$L.toString() is sent as the $S header.", + apiVersionField.name, + headerApiVersionScheme.getHeader().getName().getWireValue()) + .build()); + clientOptionsBuilder.addMethod(createGetter(apiVersionField).toBuilder() + .addJavadoc( + "$L.toString() is sent as the $S header.", + apiVersionField.name, + headerApiVersionScheme.getHeader().getName().getWireValue()) + .build()); + + return null; + } + + @Override + public Void _visitUnknown(Object _o) { + throw new IllegalArgumentException("Received unknown API versioning schema type in IR."); + } + }); + } + } + private void addApiVersionToConstructor(MethodSpec.Builder constructorBuilder) { if (clientGeneratorContext.getIr().getApiVersion().isPresent()) { ApiVersionScheme apiVersionScheme = @@ -272,6 +299,12 @@ public Void visitHeader(HeaderApiVersionScheme headerApiVersionScheme) { .getPoetClassNameFactory() .getApiVersionClassName()), apiVersionField.name) + .addJavadoc( + "Defaults to $S if empty", + headerApiVersionScheme + .getValue() + .getDefault() + .get()) .build()); constructorBuilder.addStatement( "this.$L = $L.orElse($L)", @@ -397,7 +430,8 @@ public Void visitHeader(HeaderApiVersionScheme headerApiVersionScheme) { apiVersionField.name, Modifier.PRIVATE) .build()); - builder.addMethod(getOptionalVersionBuilder()); + builder.addMethod(getOptionalVersionBuilder( + headerApiVersionScheme.getHeader().getName().getWireValue())); } else { builder.addField(FieldSpec.builder( clientGeneratorContext @@ -406,7 +440,8 @@ public Void visitHeader(HeaderApiVersionScheme headerApiVersionScheme) { apiVersionField.name, Modifier.PRIVATE) .build()); - builder.addMethod(getRequiredVersionBuilder()); + builder.addMethod(getRequiredVersionBuilder( + headerApiVersionScheme.getHeader().getName().getWireValue())); } return null; @@ -441,8 +476,9 @@ private MethodSpec getHeaderBuilder() { .build(); } - private MethodSpec getOptionalVersionBuilder() { + private MethodSpec getOptionalVersionBuilder(String headerName) { return MethodSpec.methodBuilder(apiVersionField.name) + .addJavadoc("$L.toString() is sent as the $S header.", apiVersionField.name, headerName) .addModifiers(Modifier.PUBLIC) .returns(builderClassName) .addParameter( @@ -452,8 +488,9 @@ private MethodSpec getOptionalVersionBuilder() { .build(); } - private MethodSpec getRequiredVersionBuilder() { + private MethodSpec getRequiredVersionBuilder(String headerName) { return MethodSpec.methodBuilder(apiVersionField.name) + .addJavadoc("$L.toString() is sent as the $S header.", apiVersionField.name, headerName) .addModifiers(Modifier.PUBLIC) .returns(builderClassName) .addParameter( diff --git a/seed/java-sdk/version-no-default/src/main/java/com/seed/version/core/ClientOptions.java b/seed/java-sdk/version-no-default/src/main/java/com/seed/version/core/ClientOptions.java index 56ddbe340f8..12d52c46dce 100644 --- a/seed/java-sdk/version-no-default/src/main/java/com/seed/version/core/ClientOptions.java +++ b/seed/java-sdk/version-no-default/src/main/java/com/seed/version/core/ClientOptions.java @@ -20,6 +20,9 @@ public final class ClientOptions { private final int timeout; + /** + * version.toString() is sent as the "X-API-Version" header. + */ private final ApiVersion version; private ClientOptions( @@ -59,6 +62,9 @@ public Map headers(RequestOptions requestOptions) { return values; } + /** + * version.toString() is sent as the "X-API-Version" header. + */ public ApiVersion version() { return this.version; } @@ -118,6 +124,9 @@ public Builder timeout(int timeout) { return this; } + /** + * version.toString() is sent as the "X-API-Version" header. + */ public Builder version(ApiVersion version) { this.version = version; return this; diff --git a/seed/java-sdk/version/src/main/java/com/seed/version/core/ClientOptions.java b/seed/java-sdk/version/src/main/java/com/seed/version/core/ClientOptions.java index adb6b34043e..2f32faae595 100644 --- a/seed/java-sdk/version/src/main/java/com/seed/version/core/ClientOptions.java +++ b/seed/java-sdk/version/src/main/java/com/seed/version/core/ClientOptions.java @@ -21,8 +21,37 @@ public final class ClientOptions { private final int timeout; + /** + * version.toString() is sent as the "X-API-Version" header. + */ private final ApiVersion version; + /** + * @param version Defaults to "{\n" + * + " \"name\" : {\n" + * + " \"wireValue\" : \"2.0.0\",\n" + * + " \"name\" : {\n" + * + " \"originalName\" : \"v2\",\n" + * + " \"camelCase\" : {\n" + * + " \"unsafeName\" : \"v2\",\n" + * + " \"safeName\" : \"v2\"\n" + * + " },\n" + * + " \"pascalCase\" : {\n" + * + " \"unsafeName\" : \"V2\",\n" + * + " \"safeName\" : \"V2\"\n" + * + " },\n" + * + " \"snakeCase\" : {\n" + * + " \"unsafeName\" : \"v_2\",\n" + * + " \"safeName\" : \"v_2\"\n" + * + " },\n" + * + " \"screamingSnakeCase\" : {\n" + * + " \"unsafeName\" : \"V_2\",\n" + * + " \"safeName\" : \"V_2\"\n" + * + " }\n" + * + " }\n" + * + " }\n" + * + "}" if empty + */ private ClientOptions( Environment environment, Map headers, @@ -60,6 +89,9 @@ public Map headers(RequestOptions requestOptions) { return values; } + /** + * version.toString() is sent as the "X-API-Version" header. + */ public ApiVersion version() { return this.version; } @@ -119,6 +151,9 @@ public Builder timeout(int timeout) { return this; } + /** + * version.toString() is sent as the "X-API-Version" header. + */ public Builder version(ApiVersion version) { this.version = Optional.of(version); return this; From d626597fd1ffc7165db87fa01160d352201bf7fc Mon Sep 17 00:00:00 2001 From: Alberto Date: Tue, 7 Jan 2025 12:16:46 -0500 Subject: [PATCH 18/20] add javadoc to request options --- .../generators/RequestOptionsGenerator.java | 107 ++++++++++++------ .../com/seed/version/core/RequestOptions.java | 19 +++- .../com/seed/version/core/RequestOptions.java | 19 +++- 3 files changed, 99 insertions(+), 46 deletions(-) diff --git a/generators/java/sdk/src/main/java/com/fern/java/client/generators/RequestOptionsGenerator.java b/generators/java/sdk/src/main/java/com/fern/java/client/generators/RequestOptionsGenerator.java index 1eb11e2734c..05e193996ab 100644 --- a/generators/java/sdk/src/main/java/com/fern/java/client/generators/RequestOptionsGenerator.java +++ b/generators/java/sdk/src/main/java/com/fern/java/client/generators/RequestOptionsGenerator.java @@ -143,30 +143,7 @@ public GeneratedJavaFile generateFile() { builderTypeSpec, fields); - if (clientGeneratorContext.getIr().getApiVersion().isPresent()) { - ApiVersionScheme apiVersionScheme = - clientGeneratorContext.getIr().getApiVersion().get(); - - apiVersionScheme.visit(new ApiVersionScheme.Visitor() { - @Override - public Void visitHeader(HeaderApiVersionScheme headerApiVersionScheme) { - createRequestOptionField( - "getVersion", - apiVersionField.toBuilder(), - CodeBlock.of("$T.empty()", Optional.class), - requestOptionsTypeSpec, - builderTypeSpec, - fields); - - return null; - } - - @Override - public Void _visitUnknown(Object _o) { - throw new IllegalArgumentException("Received unknown API versioning schema type in IR."); - } - }); - } + addApiVersionField(requestOptionsTypeSpec, builderTypeSpec, apiVersionField.toBuilder(), fields); FieldSpec timeoutField = timeoutFieldBuilder.build(); FieldSpec timeUnitField = timeoutTimeUnitFieldBuilder.build(); @@ -188,18 +165,6 @@ public Void _visitUnknown(Object _o) { .returns(builderClassName) .build()); - if (clientGeneratorContext.getIr().getApiVersion().isPresent()) { - builderTypeSpec.addMethod(MethodSpec.methodBuilder(apiVersionField.name) - .addModifiers(Modifier.PUBLIC) - .addParameter( - clientGeneratorContext.getPoetClassNameFactory().getApiVersionClassName(), - apiVersionField.name) - .addStatement("this.$L = Optional.of($L)", apiVersionField.name, apiVersionField.name) - .addStatement("return this") - .returns(builderClassName) - .build()); - } - String constructorArgs = fields.stream().map(field -> field.builderField.name).collect(Collectors.joining(", ")); builderTypeSpec.addMethod(MethodSpec.methodBuilder("build") @@ -290,6 +255,76 @@ public Void _visitUnknown(Object _o) { } } + private void addApiVersionField( + TypeSpec.Builder requestOptionsTypeSpec, + TypeSpec.Builder builderTypeSpec, + FieldSpec.Builder apiVersionField, + List fields) { + if (clientGeneratorContext.getIr().getApiVersion().isPresent()) { + ApiVersionScheme apiVersionScheme = + clientGeneratorContext.getIr().getApiVersion().get(); + + apiVersionScheme.visit(new ApiVersionScheme.Visitor() { + @Override + public Void visitHeader(HeaderApiVersionScheme headerApiVersionScheme) { + FieldSpec field = apiVersionField.build(); + requestOptionsTypeSpec.addField(apiVersionField + .addModifiers(Modifier.FINAL) + .addJavadoc( + "$L.get().toString() is sent as the $S header, overriding client options " + + "if present.", + field.name, + headerApiVersionScheme.getHeader().getName().getWireValue()) + .build()); + fields.add(new RequestOption( + apiVersionField + .initializer(CodeBlock.of("$T.empty()", Optional.class)) + .build(), + field)); + FieldSpec builderField = FieldSpec.builder(field.type, field.name, Modifier.PRIVATE) + .initializer(CodeBlock.of("$T.empty()", Optional.class)) + .build(); + builderTypeSpec.addField(builderField); + + requestOptionsTypeSpec.addMethod(MethodSpec.methodBuilder("getVersion") + .addJavadoc( + "$L.get().toString() is sent as the $S header, overriding client options " + + "if present.", + field.name, + headerApiVersionScheme.getHeader().getName().getWireValue()) + .addModifiers(Modifier.PUBLIC) + .addStatement("return $N", field.name) + .returns(field.type) + .build()); + + builderTypeSpec.addMethod(MethodSpec.methodBuilder(field.name) + .addJavadoc( + "$L.get().toString() is sent as the $S header, overriding client options " + + "if present.", + field.name, + headerApiVersionScheme.getHeader().getName().getWireValue()) + .addModifiers(Modifier.PUBLIC) + .addParameter( + clientGeneratorContext + .getPoetClassNameFactory() + .getApiVersionClassName(), + field.name) + .addStatement("this.$L = Optional.of($L)", field.name, field.name) + .addStatement("return this") + .returns(builderClassName) + .build()); + + return null; + } + + @Override + public Void _visitUnknown(Object _o) { + throw new IllegalArgumentException("Received unknown API versioning schema type in IR."); + } + }); + } + } + private static class RequestOption { private final FieldSpec builderField; private final FieldSpec requestOptionsField; diff --git a/seed/java-sdk/version-no-default/src/main/java/com/seed/version/core/RequestOptions.java b/seed/java-sdk/version-no-default/src/main/java/com/seed/version/core/RequestOptions.java index 365a5a68de4..a5b01bc7cdb 100644 --- a/seed/java-sdk/version-no-default/src/main/java/com/seed/version/core/RequestOptions.java +++ b/seed/java-sdk/version-no-default/src/main/java/com/seed/version/core/RequestOptions.java @@ -13,6 +13,9 @@ public final class RequestOptions { private final TimeUnit timeoutTimeUnit; + /** + * version.get().toString() is sent as the "X-API-Version" header, overriding client options if present. + */ private final Optional version; private RequestOptions(Optional timeout, TimeUnit timeoutTimeUnit, Optional version) { @@ -29,6 +32,9 @@ public TimeUnit getTimeoutTimeUnit() { return timeoutTimeUnit; } + /** + * version.get().toString() is sent as the "X-API-Version" header, overriding client options if present. + */ public Optional getVersion() { return version; } @@ -52,6 +58,14 @@ public static final class Builder { private Optional version = Optional.empty(); + /** + * version.get().toString() is sent as the "X-API-Version" header, overriding client options if present. + */ + public Builder version(ApiVersion version) { + this.version = Optional.of(version); + return this; + } + public Builder timeout(Integer timeout) { this.timeout = Optional.of(timeout); return this; @@ -63,11 +77,6 @@ public Builder timeout(Integer timeout, TimeUnit timeoutTimeUnit) { return this; } - public Builder version(ApiVersion version) { - this.version = Optional.of(version); - return this; - } - public RequestOptions build() { return new RequestOptions(timeout, timeoutTimeUnit, version); } diff --git a/seed/java-sdk/version/src/main/java/com/seed/version/core/RequestOptions.java b/seed/java-sdk/version/src/main/java/com/seed/version/core/RequestOptions.java index 365a5a68de4..a5b01bc7cdb 100644 --- a/seed/java-sdk/version/src/main/java/com/seed/version/core/RequestOptions.java +++ b/seed/java-sdk/version/src/main/java/com/seed/version/core/RequestOptions.java @@ -13,6 +13,9 @@ public final class RequestOptions { private final TimeUnit timeoutTimeUnit; + /** + * version.get().toString() is sent as the "X-API-Version" header, overriding client options if present. + */ private final Optional version; private RequestOptions(Optional timeout, TimeUnit timeoutTimeUnit, Optional version) { @@ -29,6 +32,9 @@ public TimeUnit getTimeoutTimeUnit() { return timeoutTimeUnit; } + /** + * version.get().toString() is sent as the "X-API-Version" header, overriding client options if present. + */ public Optional getVersion() { return version; } @@ -52,6 +58,14 @@ public static final class Builder { private Optional version = Optional.empty(); + /** + * version.get().toString() is sent as the "X-API-Version" header, overriding client options if present. + */ + public Builder version(ApiVersion version) { + this.version = Optional.of(version); + return this; + } + public Builder timeout(Integer timeout) { this.timeout = Optional.of(timeout); return this; @@ -63,11 +77,6 @@ public Builder timeout(Integer timeout, TimeUnit timeoutTimeUnit) { return this; } - public Builder version(ApiVersion version) { - this.version = Optional.of(version); - return this; - } - public RequestOptions build() { return new RequestOptions(timeout, timeoutTimeUnit, version); } From 4d02dc2605a2cc27761654aa8763a558467a8ac7 Mon Sep 17 00:00:00 2001 From: Alberto Date: Tue, 7 Jan 2025 12:19:18 -0500 Subject: [PATCH 19/20] add version entry --- generators/java/sdk/versions.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/generators/java/sdk/versions.yml b/generators/java/sdk/versions.yml index 8f6a59a056e..13c56973fa6 100644 --- a/generators/java/sdk/versions.yml +++ b/generators/java/sdk/versions.yml @@ -1,3 +1,10 @@ +- changelogEntry: + - summary: | + Support version headers in request and client options. + type: feat + createdAt: '2025-01-07' + irVersion: 53 + version: 2.9.0 - changelogEntry: - summary: | Implement global timeout configuration for generated clients. From dee1cfb6b542ed2246a8bf2094ff2b9660f11867 Mon Sep 17 00:00:00 2001 From: ajgateno Date: Tue, 7 Jan 2025 17:22:48 +0000 Subject: [PATCH 20/20] chore: update changelog --- fern/pages/changelogs/java-sdk/2025-01-07.mdx | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 fern/pages/changelogs/java-sdk/2025-01-07.mdx diff --git a/fern/pages/changelogs/java-sdk/2025-01-07.mdx b/fern/pages/changelogs/java-sdk/2025-01-07.mdx new file mode 100644 index 00000000000..0ca5b8ac574 --- /dev/null +++ b/fern/pages/changelogs/java-sdk/2025-01-07.mdx @@ -0,0 +1,4 @@ +## 2.9.0 +**`(feat):`** Support version headers in request and client options. + +