diff --git a/clients/algoliasearch-client-go/.golangci.yml b/clients/algoliasearch-client-go/.golangci.yml index ef10120bd06..2dd039ed968 100644 --- a/clients/algoliasearch-client-go/.golangci.yml +++ b/clients/algoliasearch-client-go/.golangci.yml @@ -50,6 +50,10 @@ linters: presets: - comments - std-error-handling + rules: + - path: api_search.go + linters: + - wrapcheck formatters: enable: - gofmt diff --git a/clients/algoliasearch-client-go/README.md b/clients/algoliasearch-client-go/README.md index 89cb9f895cd..c6a4f90b8c5 100644 --- a/clients/algoliasearch-client-go/README.md +++ b/clients/algoliasearch-client-go/README.md @@ -41,35 +41,30 @@ You can now import the Algolia API client in your project and play with it. ```go -import "github.com/algolia/algoliasearch-client-go/v4/algolia/search" +import "github.com/algolia/algoliasearch-client-go/v4/algolia/next/search" client, err := search.NewClient("YOUR_APP_ID", "YOUR_API_KEY") // Add a new record to your Algolia index -response, err := client.SaveObject(client.NewApiSaveObjectRequest( - "", map[string]any{"objectID": "id", "test": "val"}, -)) +saveResponse, err := client.SaveObject("", map[string]any{"objectID": "id", "test": "val"}) if err != nil { // handle the eventual error panic(err) } // use the model directly -print(response) +print(saveResponse) // Poll the task status to know when it has been indexed -taskResponse, err := searchClient.WaitForTask("", response.TaskID, nil, nil, nil) +_, err = client.WaitForTask("", saveResponse.TaskID) if err != nil { panic(err) } // Fetch search results, with typo tolerance -response, err := client.Search(client.NewApiSearchRequest( - - search.NewEmptySearchMethodParams().SetRequests( - []search.SearchQuery{*search.SearchForHitsAsSearchQuery( - search.NewEmptySearchForHits().SetIndexName("").SetQuery("").SetHitsPerPage(50))}), -)) +response, err := client.Search([]search.SearchQuery{ + *search.SearchForHitsAsSearchQuery(search.NewSearchForHits("").SetQuery("").SetHitsPerPage(50)), +}, nil) if err != nil { // handle the eventual error panic(err) @@ -77,6 +72,8 @@ if err != nil { // use the model directly print(response) + +return 0 ``` For full documentation, visit the **[Algolia Go API Client](https://www.algolia.com/doc/libraries/go/)**. diff --git a/config/clients.config.json b/config/clients.config.json index 4b3c8ab2cff..9ed566099ac 100644 --- a/config/clients.config.json +++ b/config/clients.config.json @@ -88,8 +88,8 @@ "folder": "clients/algoliasearch-client-go", "gitRepoId": "algoliasearch-client-go", "packageVersion": "4.28.1", - "modelFolder": "algolia", - "apiFolder": "algolia", + "modelFolder": "algolia/next", + "apiFolder": "algolia/next", "dockerImage": "apic_base", "tests": { "extension": "_test.go", diff --git a/generators/src/main/java/com/algolia/codegen/AlgoliaGoGenerator.java b/generators/src/main/java/com/algolia/codegen/AlgoliaGoGenerator.java index 788cba5aba3..0722b61a494 100644 --- a/generators/src/main/java/com/algolia/codegen/AlgoliaGoGenerator.java +++ b/generators/src/main/java/com/algolia/codegen/AlgoliaGoGenerator.java @@ -1,8 +1,10 @@ package com.algolia.codegen; +import com.algolia.codegen.cts.lambda.ScreamingSnakeCaseLambda; import com.algolia.codegen.exceptions.*; -import com.algolia.codegen.lambda.ScreamingSnakeCaseLambda; import com.algolia.codegen.utils.*; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; import com.samskivert.mustache.Mustache; @@ -11,6 +13,7 @@ import io.swagger.v3.oas.models.servers.Server; import java.io.File; import java.util.*; +import java.util.stream.Collectors; import org.openapitools.codegen.*; import org.openapitools.codegen.languages.GoClientCodegen; import org.openapitools.codegen.model.ModelMap; @@ -19,6 +22,9 @@ public class AlgoliaGoGenerator extends GoClientCodegen { + // This is used for the CTS generation + private static final AlgoliaGoGenerator INSTANCE = new AlgoliaGoGenerator(); + @Override public String getName() { return "algolia-go"; @@ -29,10 +35,9 @@ public void processOpts() { String client = (String) additionalProperties.get("client"); additionalProperties.put("packageName", client.equals("query-suggestions") ? "suggestions" : Helpers.camelize(client)); - additionalProperties.put("enumClassPrefix", true); additionalProperties.put("is" + Helpers.capitalize(Helpers.camelize(client)) + "Client", true); - String outputFolder = "algolia" + File.separator + client; + String outputFolder = "algolia/next/" + client; setOutputDir(getOutputDir() + File.separator + outputFolder); super.processOpts(); @@ -44,6 +49,7 @@ public void processOpts() { typeMapping.put("AnyType", "any"); modelNameMapping.put("range", "modelRange"); + typeMapping.put("integer", "int"); apiTestTemplateFiles.clear(); modelTestTemplateFiles.clear(); @@ -54,7 +60,7 @@ public void processOpts() { supportingFiles.add(new SupportingFile("configuration.mustache", "", "configuration.go")); supportingFiles.add(new SupportingFile("client.mustache", "", "client.go")); - Helpers.addCommonSupportingFiles(supportingFiles, "../../"); + Helpers.addCommonSupportingFiles(supportingFiles, "../../../"); try { additionalProperties.put("packageVersion", Helpers.getClientConfigField("go", "packageVersion")); @@ -78,6 +84,13 @@ public void processOpenAPI(OpenAPI openAPI) { super.processOpenAPI(openAPI); Helpers.generateServers(super.fromServers(openAPI.getServers()), additionalProperties); Timeouts.enrichBundle(openAPI, additionalProperties); + additionalProperties.put( + "appDescription", + Arrays.stream(openAPI.getInfo().getDescription().split("\n")) + .map(line -> "// " + line) + .collect(Collectors.joining("\n")) + .trim() + ); } @Override @@ -118,7 +131,8 @@ public Map postProcessAllModels(Map objs) String modelName = entry.getKey(); CodegenModel model = entry.getValue().getModels().get(0).getModel(); - // for some reason the property additionalPropertiesIsAnyType is not propagated to the + // for some reason the property additionalPropertiesIsAnyType is not propagated + // to the // property for (CodegenProperty prop : model.getVars()) { ModelsMap propertyModel = models.get(prop.datatypeWithEnum); @@ -140,9 +154,105 @@ public Map postProcessAllModels(Map objs) @Override public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List models) { OperationsMap operations = super.postProcessOperationsWithModels(objs, models); + + // Flatten body params to remove the wrapping object + for (CodegenOperation ope : operations.getOperations().getOperation()) { + // clean up the description + String[] lines = ope.unescapedNotes.split("\n"); + ope.notes = (lines[0] + + "\n" + + Arrays.stream(lines) + .skip(1) + .map(line -> "// " + line) + .collect(Collectors.joining("\n"))).trim(); + + // enrich the params + for (CodegenParameter param : ope.optionalParams) { + param.nameInPascalCase = Helpers.capitalize(param.baseName); + } + + CodegenParameter bodyParam = ope.bodyParam; + if (bodyParam != null) { + flattenBody(ope); + } + + // If the optional param struct only has 1 param, we can remove the wrapper + if (ope.optionalParams.size() == 1) { + CodegenParameter param = ope.optionalParams.get(0); + + // move it to required, it's easier to handle im mustache + ope.optionalParams.clear(); + + ope.requiredParams.add(param); + } + } + ModelPruner.removeOrphanModelFiles(this, operations, models); Helpers.removeHelpers(operations); GenericPropagator.propagateGenericsToOperations(operations, models); return operations; } + + private void flattenBody(CodegenOperation ope) { + CodegenParameter bodyParam = ope.bodyParam; + bodyParam.nameInPascalCase = Helpers.capitalize(bodyParam.baseName); + if (!bodyParam.isModel) { + return; + } + + if (!canFlattenBody(ope)) { + System.out.println( + "Operation " + ope.operationId + " has body param " + bodyParam.paramName + " in colision with a parameter, skipping flattening" + ); + return; + } + + bodyParam.vendorExtensions.put("x-flat-body", bodyParam.getVars().size() > 0); + + if (bodyParam.getVars().size() > 0) { + ope.allParams.removeIf(param -> param.isBodyParam); + ope.requiredParams.removeIf(param -> param.isBodyParam); + ope.optionalParams.removeIf(param -> param.isBodyParam); + } + + for (CodegenProperty prop : bodyParam.getVars()) { + prop.nameInLowerCase = toParamName(prop.baseName); + + CodegenParameter param = new ObjectMapper() + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .convertValue(prop, CodegenParameter.class); + param.nameInPascalCase = Helpers.capitalize(prop.baseName); + param.paramName = toParamName(prop.baseName); + + if (prop.required) { + ope.requiredParams.add(param); + } else { + ope.optionalParams.add(param); + } + ope.allParams.add(param); + } + } + + public static boolean canFlattenBody(CodegenOperation ope) { + if (ope.bodyParam == null || !ope.bodyParam.isModel) { + return false; + } + + if (ope.allParams.size() == 1) { + return true; + } + + for (CodegenProperty prop : ope.bodyParam.getVars()) { + for (CodegenParameter param : ope.allParams) { + if (param.paramName.equals(prop.baseName)) { + return false; + } + } + } + return true; + } + + public static String toEnum(String value) { + return INSTANCE.toEnumVarName(value, "String"); + } } diff --git a/generators/src/main/java/com/algolia/codegen/AlgoliaJavascriptGenerator.java b/generators/src/main/java/com/algolia/codegen/AlgoliaJavascriptGenerator.java index 700c106f0f5..2e5b9ff8d79 100644 --- a/generators/src/main/java/com/algolia/codegen/AlgoliaJavascriptGenerator.java +++ b/generators/src/main/java/com/algolia/codegen/AlgoliaJavascriptGenerator.java @@ -236,20 +236,13 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List addMustacheLambdas() { lambdas.put("escapeSlash", new EscapeSlashLambda()); lambdas.put("escapeJSON", new EscapeJSONLambda()); lambdas.put("replaceBacktick", new ReplaceBacktickLambda()); + lambdas.put("screamingSnakeCase", new ScreamingSnakeCaseLambda()); return lambdas; } diff --git a/generators/src/main/java/com/algolia/codegen/cts/lambda/DynamicSnippetLambda.java b/generators/src/main/java/com/algolia/codegen/cts/lambda/DynamicSnippetLambda.java index e5647d767a9..2609da2254e 100644 --- a/generators/src/main/java/com/algolia/codegen/cts/lambda/DynamicSnippetLambda.java +++ b/generators/src/main/java/com/algolia/codegen/cts/lambda/DynamicSnippetLambda.java @@ -32,6 +32,7 @@ public class DynamicSnippetLambda implements Mustache.Lambda { private final Map operations; private final Map snippets; + private final String language; public DynamicSnippetLambda( DefaultCodegen generator, @@ -41,6 +42,7 @@ public DynamicSnippetLambda( String client ) { this.operations = operations; + this.language = language; this.paramsType = new ParametersWithDataType(models, language, client, true); JsonNode snippetsFile = Helpers.readJsonFile("tests/CTS/guides/" + client + ".json"); @@ -74,7 +76,7 @@ public void execute(Template.Fragment fragment, Writer writer) throws IOExceptio // set the method attributes Map context = (Map) fragment.context(); - snippet.addMethodCall(context, paramsType, operation); + snippet.addMethodCall(language, context, paramsType, operation); writer.write(adaptor.compileTemplate(executor, context, "tests/method.mustache")); } diff --git a/generators/src/main/java/com/algolia/codegen/lambda/ScreamingSnakeCaseLambda.java b/generators/src/main/java/com/algolia/codegen/cts/lambda/ScreamingSnakeCaseLambda.java similarity index 91% rename from generators/src/main/java/com/algolia/codegen/lambda/ScreamingSnakeCaseLambda.java rename to generators/src/main/java/com/algolia/codegen/cts/lambda/ScreamingSnakeCaseLambda.java index 29b6cd61b8d..d09abaddb4a 100644 --- a/generators/src/main/java/com/algolia/codegen/lambda/ScreamingSnakeCaseLambda.java +++ b/generators/src/main/java/com/algolia/codegen/cts/lambda/ScreamingSnakeCaseLambda.java @@ -1,4 +1,4 @@ -package com.algolia.codegen.lambda; +package com.algolia.codegen.cts.lambda; import com.algolia.codegen.utils.Helpers; import com.samskivert.mustache.Mustache; diff --git a/generators/src/main/java/com/algolia/codegen/cts/manager/GoCTSManager.java b/generators/src/main/java/com/algolia/codegen/cts/manager/GoCTSManager.java index 45090a0da71..4242e5089e1 100644 --- a/generators/src/main/java/com/algolia/codegen/cts/manager/GoCTSManager.java +++ b/generators/src/main/java/com/algolia/codegen/cts/manager/GoCTSManager.java @@ -1,7 +1,9 @@ package com.algolia.codegen.cts.manager; +import com.algolia.codegen.AlgoliaGoGenerator; import com.algolia.codegen.exceptions.GeneratorException; import com.algolia.codegen.utils.*; +import com.samskivert.mustache.Mustache.Lambda; import java.util.*; import org.openapitools.codegen.SupportingFile; @@ -40,4 +42,9 @@ public void addSnippetsSupportingFiles(List supportingFiles, Str supportingFiles.add(new SupportingFile("snippets/.golangci.mustache", output + "/go/.golangci.yml")); supportingFiles.add(new SupportingFile("snippets/go.mod.mustache", output + "/go/go.mod")); } + + @Override + public void addMustacheLambdas(Map lambdas) { + lambdas.put("toEnum", (fragment, writer) -> writer.write(AlgoliaGoGenerator.toEnum(fragment.execute()))); + } } diff --git a/generators/src/main/java/com/algolia/codegen/cts/manager/JavaCTSManager.java b/generators/src/main/java/com/algolia/codegen/cts/manager/JavaCTSManager.java index 42e5aece0bc..886c873d0eb 100644 --- a/generators/src/main/java/com/algolia/codegen/cts/manager/JavaCTSManager.java +++ b/generators/src/main/java/com/algolia/codegen/cts/manager/JavaCTSManager.java @@ -52,6 +52,6 @@ public void addDataToBundle(Map bundle) throws GeneratorExceptio @Override public void addMustacheLambdas(Map lambdas) { - lambdas.put("javaEnum", (fragment, writer) -> writer.write(AlgoliaJavaGenerator.toEnum(fragment.execute()))); + lambdas.put("toEnum", (fragment, writer) -> writer.write(AlgoliaJavaGenerator.toEnum(fragment.execute()))); } } diff --git a/generators/src/main/java/com/algolia/codegen/cts/tests/ParametersWithDataType.java b/generators/src/main/java/com/algolia/codegen/cts/tests/ParametersWithDataType.java index 2f7bdb38c08..fd01ba091db 100644 --- a/generators/src/main/java/com/algolia/codegen/cts/tests/ParametersWithDataType.java +++ b/generators/src/main/java/com/algolia/codegen/cts/tests/ParametersWithDataType.java @@ -1,5 +1,6 @@ package com.algolia.codegen.cts.tests; +import com.algolia.codegen.AlgoliaGoGenerator; import com.algolia.codegen.AlgoliaSwiftGenerator; import com.algolia.codegen.exceptions.*; import com.algolia.codegen.utils.*; @@ -60,7 +61,7 @@ public void enhanceParameters(Map parameters, Map parameters, Map paramWithType = traverseParams(param.getKey(), param.getValue(), specParam, "", 0, false); - parametersWithDataType.add(paramWithType); - parametersWithDataTypeMap.put((String) paramWithType.get("key"), paramWithType); + if ( + language.equals("go") && + specParam != null && + specParam.isBodyParam && + operation != null && + operation.bodyParam != null && + operation.bodyParam.isModel && + operation.bodyParam.getVars().size() > 0 && + AlgoliaGoGenerator.canFlattenBody(operation) + ) { + // flatten the body params by skipping one level + flattenBodyParams((Map) param.getValue(), operation, parametersWithDataType); + } else { + Map paramWithType = traverseParams(param.getKey(), param.getValue(), specParam, "", 0, false); + parametersWithDataType.add(paramWithType); + parametersWithDataTypeMap.put((String) paramWithType.get("key"), paramWithType); + } } } + } else if (language.equals("go") && parameters != null && operation.bodyParam.getVars().size() > 0) { + // also flatten when the body is the only parameter + flattenBodyParams(parameters, operation, parametersWithDataType); } else { Map paramWithType = traverseParams(paramName, parameters, spec, "", 0, false); parametersWithDataType.add(paramWithType); @@ -105,6 +123,22 @@ private String toJSONWithVar(Map parameters) throws JsonProcessi return Json.mapper().writeValueAsString(parameters).replaceAll("\"\\$var: (.*?)\"", "$1"); } + private void flattenBodyParams( + Map parameters, + CodegenOperation operation, + List> parametersWithDataType + ) throws CTSException { + for (String nestedParam : parameters.keySet()) { + for (CodegenProperty prop : operation.bodyParam.getVars()) { + if (prop.baseName.equals(nestedParam)) { + Map paramWithType = traverseParams(prop.baseName, parameters.get(nestedParam), prop, "", 0, false); + parametersWithDataType.add(paramWithType); + break; + } + } + } + } + private Map traverseParams( String paramName, Object param, @@ -418,19 +452,7 @@ private void handleModel( } if (language.equals("swift")) { - // Store ordered params from the spec - var orderedParams = spec - .getVars() - .stream() - .map(v -> v.baseName) - .toList(); - - // Create a map to store the indices of each string in orderedParams - Map indexMap = IntStream.range(0, orderedParams.size()) - .boxed() - .collect(Collectors.toMap(orderedParams::get, i -> i)); - - values.sort(Comparator.comparing(value -> indexMap.getOrDefault((String) value.get("key"), Integer.MAX_VALUE))); + sortParameters(spec, values); } var hasAdditionalProperties = values @@ -556,7 +578,7 @@ private String getObjectNameForLanguage(String objectName) { case "Double": return "float64"; case "Integer": - return "int32"; + return "int"; case "Long": return "int64"; case "Boolean": @@ -762,4 +784,18 @@ private boolean couldMatchEnum(Object value, CodegenProperty model) { return ((List) values).contains(value); } + + private void sortParameters(IJsonSchemaValidationProperties spec, List> parameters) { + // Store ordered params from the spec + var orderedParams = spec + .getVars() + .stream() + .map(v -> v.baseName) + .toList(); + + // Create a map to store the indices of each string in orderedParams + Map indexMap = IntStream.range(0, orderedParams.size()).boxed().collect(Collectors.toMap(orderedParams::get, i -> i)); + + parameters.sort(Comparator.comparing(param -> indexMap.getOrDefault((String) param.get("key"), Integer.MAX_VALUE))); + } } diff --git a/generators/src/main/java/com/algolia/codegen/cts/tests/Snippet.java b/generators/src/main/java/com/algolia/codegen/cts/tests/Snippet.java index c4be9988341..adfdcb89ef9 100644 --- a/generators/src/main/java/com/algolia/codegen/cts/tests/Snippet.java +++ b/generators/src/main/java/com/algolia/codegen/cts/tests/Snippet.java @@ -39,7 +39,8 @@ public String toString() { return sb.toString(); } - public void addMethodCall(Map context, ParametersWithDataType paramsType, CodegenOperation ope) throws CTSException { + public void addMethodCall(String language, Map context, ParametersWithDataType paramsType, CodegenOperation ope) + throws CTSException { // for dynamic snippets, we need to reset the context because the order of generation is random context.put("method", method); context.put("returnType", null); @@ -53,11 +54,12 @@ public void addMethodCall(Map context, ParametersWithDataType pa } try { + boolean isHelper = (boolean) ope.vendorExtensions.getOrDefault("x-helper", false); context.put("isGeneric", (boolean) ope.vendorExtensions.getOrDefault("x-is-generic", false)); context.put("isCustomRequest", Helpers.CUSTOM_METHODS.contains(ope.operationIdOriginal)); context.put("isAsyncMethod", (boolean) ope.vendorExtensions.getOrDefault("x-asynchronous-helper", true)); context.put("hasParams", ope.getHasParams()); - context.put("isHelper", (boolean) ope.vendorExtensions.getOrDefault("x-helper", false)); + context.put("isHelper", isHelper); context.put("hasRequestOptions", requestOptions != null); if (requestOptions != null) { @@ -86,6 +88,8 @@ public void addMethodCall(Map context, ParametersWithDataType pa } } + TestsGenerator.setOptionalParameters(language, ope, context, parameters, isHelper); + paramsType.enhanceParameters(parameters, context, ope); } catch (CTSException e) { e.setTestName((String) context.get("testName")); diff --git a/generators/src/main/java/com/algolia/codegen/cts/tests/SnippetsGenerator.java b/generators/src/main/java/com/algolia/codegen/cts/tests/SnippetsGenerator.java index baa7f7cbf29..f4f4e81b297 100644 --- a/generators/src/main/java/com/algolia/codegen/cts/tests/SnippetsGenerator.java +++ b/generators/src/main/java/com/algolia/codegen/cts/tests/SnippetsGenerator.java @@ -124,7 +124,7 @@ public void run(Map models, Map test.put("testName", ops.size() > 1 ? name : "default"); test.put("description", name); test.put("testIndex", i == 0 ? "" : i); - snippet.addMethodCall(test, paramsType, ope); + snippet.addMethodCall(language, test, paramsType, ope); addRequestOptions(paramsType, snippet.requestOptions, test); tests.add(test); } diff --git a/generators/src/main/java/com/algolia/codegen/cts/tests/TestsClient.java b/generators/src/main/java/com/algolia/codegen/cts/tests/TestsClient.java index 6bb67dfd7eb..95d0bc6be18 100644 --- a/generators/src/main/java/com/algolia/codegen/cts/tests/TestsClient.java +++ b/generators/src/main/java/com/algolia/codegen/cts/tests/TestsClient.java @@ -80,6 +80,12 @@ public void run(Map models, Map testOut.put("autoCreateClient", test.autoCreateClient); testOut.put("useEchoRequester", true); testOut.put("isBenchmark", withBenchmark); + + if (language.equals("go") && "`addApiKey` throws with invalid parameters".equals(test.testName)) { + // skip this test because the body is flattened in go + continue; + } + for (Step step : test.steps) { Map stepOut = new HashMap<>(); if (step.times > 1) stepOut.put("times", step.times); @@ -158,6 +164,7 @@ public void run(Map models, Map // default to true because most api calls are asynchronous testOut.put("isAsyncMethod", (boolean) ope.vendorExtensions.getOrDefault("x-asynchronous-helper", true)); + setOptionalParameters(language, ope, stepOut, step.parameters, isHelper); addRequestOptions(paramsType, step.requestOptions, stepOut); methodCount++; @@ -179,6 +186,7 @@ public void run(Map models, Map item -> (boolean) item.getOrDefault("isNullObject", false) || (boolean) item.getOrDefault("isNull", false) ); if (isNotTestable) { + System.out.println("Skipping test " + test.testName + " for " + language + " because of nil object"); continue; } } diff --git a/generators/src/main/java/com/algolia/codegen/cts/tests/TestsGenerator.java b/generators/src/main/java/com/algolia/codegen/cts/tests/TestsGenerator.java index eab9caf43a3..73150fc7929 100644 --- a/generators/src/main/java/com/algolia/codegen/cts/tests/TestsGenerator.java +++ b/generators/src/main/java/com/algolia/codegen/cts/tests/TestsGenerator.java @@ -1,5 +1,6 @@ package com.algolia.codegen.cts.tests; +import com.algolia.codegen.AlgoliaGoGenerator; import com.algolia.codegen.cts.manager.CTSManager; import com.algolia.codegen.exceptions.CTSException; import com.algolia.codegen.utils.*; @@ -11,9 +12,7 @@ import java.nio.file.Paths; import java.util.*; import org.apache.commons.lang3.ArrayUtils; -import org.openapitools.codegen.CodegenModel; -import org.openapitools.codegen.CodegenOperation; -import org.openapitools.codegen.SupportingFile; +import org.openapitools.codegen.*; public abstract class TestsGenerator { @@ -130,4 +129,72 @@ protected void addRequestOptions(ParametersWithDataType paramsType, RequestOptio output.put("requestOptions", requestOptions); } } + + public static void setOptionalParameters( + String language, + CodegenOperation ope, + Map test, + Map parameters, + boolean isHelper + ) { + if (!"go".equals(language)) return; + + boolean isBodyRequired = ope.bodyParam != null && ope.bodyParam.required; + boolean alreadyInlinedBody = ope.allParams.size() == 1 && ope.bodyParam != null && !ope.bodyParam.isArray; + // I can't figure out the correct condition for this one so it's harcoded for now + boolean isSFFV = + "searchForFacetValues".equals(ope.operationId) && !ope.tags.isEmpty() && "composition".equals(ope.tags.get(0).getName()); + + int bodyPropsOptional = 0; + boolean isBodyTooBig = false; + boolean actuallyHasOptional = false; + + if (AlgoliaGoGenerator.canFlattenBody(ope) && ope.bodyParam != null) { + List vars = ope.bodyParam.getVars(); + bodyPropsOptional = (int) vars + .stream() + .filter(p -> !p.required) + .count(); + isBodyTooBig = vars.isEmpty(); + + Map paramBody = parameters; + if (!alreadyInlinedBody) { + Object paramObj = parameters.get(ope.bodyParam.paramName); + if (paramObj instanceof String) { + actuallyHasOptional = !isBodyRequired; + } else if (paramObj instanceof Map) { + paramBody = (Map) paramObj; + } + } + + for (CodegenProperty prop : vars) { + if (!prop.required && paramBody != null && paramBody.containsKey(prop.baseName)) { + actuallyHasOptional = true; + } + } + } + + for (CodegenParameter param : ope.allParams) { + if (!param.required && parameters.containsKey(param.baseName)) { + actuallyHasOptional = true; + break; + } + } + + int totalOptional = ope.optionalParams.size() + bodyPropsOptional; + + // hasOptionalWrapper if there is more that one optional param, after the body has been + // flattened. + boolean hasOptionalWrapper = totalOptional > 1 && actuallyHasOptional && !isSFFV; + boolean hasInlineOptional = ((totalOptional == 1 || isSFFV) && actuallyHasOptional) || isBodyTooBig; + boolean hasNilOptional = totalOptional > 0 && !actuallyHasOptional && !isHelper; + if (isBodyTooBig && !isBodyRequired) { + boolean isBodySet = alreadyInlinedBody ? !parameters.isEmpty() : parameters.containsKey(ope.bodyParam.paramName); + hasNilOptional = !isBodySet; + } + + test.put("hasOptionalWrapper", hasOptionalWrapper); + test.put("hasInlineOptional", hasInlineOptional); + test.put("hasNilOptional", hasNilOptional); + } } diff --git a/generators/src/main/java/com/algolia/codegen/cts/tests/TestsRequest.java b/generators/src/main/java/com/algolia/codegen/cts/tests/TestsRequest.java index cbb20c25b6d..338dca17ea6 100644 --- a/generators/src/main/java/com/algolia/codegen/cts/tests/TestsRequest.java +++ b/generators/src/main/java/com/algolia/codegen/cts/tests/TestsRequest.java @@ -171,6 +171,7 @@ public void run(Map models, Map test.put("hasParams", ope.getHasParams()); test.put("isHelper", isHelper); + setOptionalParameters(language, ope, test, req.parameters, isHelper); addRequestOptions(paramsType, req.requestOptions, test); // Determines whether the endpoint is expected to return a response payload deserialized diff --git a/playground/go/analytics.go b/playground/go/analytics.go index 4f18dc73272..9dd4461cda6 100644 --- a/playground/go/analytics.go +++ b/playground/go/analytics.go @@ -1,21 +1,20 @@ package main import ( + "context" "fmt" - "github.com/algolia/algoliasearch-client-go/v4/algolia/analytics" + "github.com/algolia/algoliasearch-client-go/v4/algolia/next/analytics" ) -func testAnalytics(appID, apiKey string) int { +func testAnalytics(ctx context.Context, appID, apiKey string) int { indexName := getEnvWithDefault("ANALYTICS_INDEX", "test_index") analyticsClient, err := analytics.NewClient(appID, apiKey, analytics.US) if err != nil { panic(err) } - getTopFilterForAttributeResponse, err := analyticsClient.GetTopFilterForAttribute( - analyticsClient.NewApiGetTopFilterForAttributeRequest("myAttribute1,myAttribute2", indexName), - ) + getTopFilterForAttributeResponse, err := analyticsClient.GetTopFilterForAttribute(ctx, "myAttribute1,myAttribute2", indexName, nil) if err != nil { fmt.Printf("request error with GetTopFilterForAttribute: %v\n", err) return 1 diff --git a/playground/go/ingestion.go b/playground/go/ingestion.go index b72371c0457..7cb17e73a18 100644 --- a/playground/go/ingestion.go +++ b/playground/go/ingestion.go @@ -1,26 +1,27 @@ package main import ( + "context" "fmt" - "github.com/algolia/algoliasearch-client-go/v4/algolia/ingestion" + "github.com/algolia/algoliasearch-client-go/v4/algolia/next/ingestion" ) -func testIngestion(appID, apiKey string) int { +func testIngestion(ctx context.Context, appID, apiKey string) int { ingestionClient, err := ingestion.NewClient(appID, apiKey, ingestion.US) if err != nil { panic(err) } // another example to generate payload for a request. - _, payload, err := ingestionClient.ListTasksWithHTTPInfo(ingestionClient.NewApiListTasksRequest()) + res, err := ingestionClient.ListTasks(ctx, nil) if err != nil { fmt.Printf("request error: %v\n", err) return 1 } - fmt.Println(string(payload)) + fmt.Println(res) return 0 } diff --git a/playground/go/insights.go b/playground/go/insights.go index 6dcebd25bb8..75eafbdb43e 100644 --- a/playground/go/insights.go +++ b/playground/go/insights.go @@ -1,28 +1,27 @@ package main import ( + "context" "fmt" - "github.com/algolia/algoliasearch-client-go/v4/algolia/insights" + "github.com/algolia/algoliasearch-client-go/v4/algolia/next/insights" ) -func testInsights(appID, apiKey string) int { +func testInsights(ctx context.Context, appID, apiKey string) int { insightsClient, err := insights.NewClient(appID, apiKey, insights.US) if err != nil { panic(err) } - events := insights.NewInsightsEvents([]insights.EventsItems{ + events := []insights.EventsItems{ *insights.ClickedObjectIDsAsEventsItems(insights.NewClickedObjectIDs("myEvent", insights.CLICK_EVENT_CLICK, "test_index", []string{"myObjectID"}, "myToken", insights.WithClickedObjectIDsTimestamp(1234567890))), - }) - eventsResponse, err := insightsClient.PushEvents( - insightsClient.NewApiPushEventsRequest(events), - ) + } + eventsResponse, err := insightsClient.PushEvents(ctx, events) if err != nil { fmt.Printf("request error with PushEvents: %v\n", err) return 1 diff --git a/playground/go/main.go b/playground/go/main.go index b4d8e4ec83b..2a6b6698c61 100644 --- a/playground/go/main.go +++ b/playground/go/main.go @@ -1,6 +1,7 @@ package main import ( + "context" "flag" "fmt" "os" @@ -10,7 +11,11 @@ import ( func main() { fmt.Println("Go playground") - godotenv.Load("../.env") + err := godotenv.Load("../.env") + if err != nil { + panic(fmt.Errorf("error loading .env file: %w", err)) + } + appID := os.Getenv("ALGOLIA_APPLICATION_ID") apiKey := os.Getenv("ALGOLIA_ADMIN_KEY") @@ -27,21 +32,23 @@ func main() { // debug.Enable() + ctx := context.Background() + switch client { case "ingestion": - returnCode = testIngestion(appID, apiKey) + returnCode = testIngestion(ctx, appID, apiKey) case "search": - returnCode = testSearch(appID, apiKey) + returnCode = testSearch(ctx, appID, apiKey) case "analytics": - returnCode = testAnalytics(appID, apiKey) + returnCode = testAnalytics(ctx, appID, apiKey) case "insights": - returnCode = testInsights(appID, apiKey) + returnCode = testInsights(ctx, appID, apiKey) case "personalization": - returnCode = testPersonalization(appID, apiKey) + returnCode = testPersonalization(ctx, appID, apiKey) case "query-suggestions": - returnCode = testQuerySuggestions(appID, apiKey) + returnCode = testQuerySuggestions(ctx, appID, apiKey) case "recommend": - returnCode = testRecommend(appID, apiKey) + returnCode = testRecommend(ctx, appID, apiKey) default: fmt.Println("Please specify a valid client name") os.Exit(1) diff --git a/playground/go/personalization.go b/playground/go/personalization.go index 5fa84b4b73d..68b51351b64 100644 --- a/playground/go/personalization.go +++ b/playground/go/personalization.go @@ -5,22 +5,19 @@ import ( "fmt" "time" - "github.com/algolia/algoliasearch-client-go/v4/algolia/personalization" + "github.com/algolia/algoliasearch-client-go/v4/algolia/next/personalization" ) -func testPersonalization(appID, apiKey string) int { +func testPersonalization(ctx context.Context, appID, apiKey string) int { personalizationClient, err := personalization.NewClient(appID, apiKey, personalization.US) if err != nil { panic(err) } - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Millisecond) + ctx, cancel := context.WithTimeout(ctx, 10*time.Millisecond) defer cancel() // it will fail expectedly because of the very short timeout to showcase the context usage. - deleteUserProfileResponse, err := personalizationClient.DeleteUserProfile( - personalizationClient.NewApiDeleteUserProfileRequest("userToken"), - personalization.WithContext(ctx), - ) + deleteUserProfileResponse, err := personalizationClient.DeleteUserProfile(ctx, "userToken") if err != nil { fmt.Printf("request error with DeleteUserProfile: %v\n", err) return 1 diff --git a/playground/go/query-suggestions.go b/playground/go/query-suggestions.go index 262ea7b0362..9756bf6873c 100644 --- a/playground/go/query-suggestions.go +++ b/playground/go/query-suggestions.go @@ -1,19 +1,19 @@ package main import ( + "context" "fmt" - "github.com/algolia/algoliasearch-client-go/v4/algolia/query-suggestions" + suggestions "github.com/algolia/algoliasearch-client-go/v4/algolia/next/query-suggestions" ) -func testQuerySuggestions(appID, apiKey string) int { +func testQuerySuggestions(ctx context.Context, appID, apiKey string) int { suggestionsClient, err := suggestions.NewClient(appID, apiKey, suggestions.US) if err != nil { panic(err) } - // if there is no params for the requests, we don't need to give empty request instance such as `suggestionsClient.NewApiGetAllConfigsRequest()`. - querySuggestionsIndex, err := suggestionsClient.GetAllConfigs() + querySuggestionsIndex, err := suggestionsClient.GetAllConfigs(ctx) if err != nil { fmt.Printf("request error with GetAllConfigs: %v\n", err) return 1 diff --git a/playground/go/recommend.go b/playground/go/recommend.go index 75d7a8c6bf6..daaacccab50 100644 --- a/playground/go/recommend.go +++ b/playground/go/recommend.go @@ -1,39 +1,34 @@ package main import ( + "context" "fmt" - "github.com/algolia/algoliasearch-client-go/v4/algolia/recommend" + "github.com/algolia/algoliasearch-client-go/v4/algolia/next/recommend" ) -func testRecommend(appID, apiKey string) int { +func testRecommend(ctx context.Context, appID, apiKey string) int { recommendClient, err := recommend.NewClient(appID, apiKey) if err != nil { panic(err) } /* - recommend.NewGetRecommendationsParams([]recommend.RecommendationsRequest{ + params := []recommend.RecommendationsRequest{ recommend.RecommendationRequestAsRecommendationsRequest(recommend.NewRecommendationRequest(recommend.RECOMMENDATIONMODELS_BOUGHT_TOGETHER, "test_query", "test_index", 0)), - }) + } */ // alternative way to create the payloads, a similar approach can be used with any of the other clients - params := &recommend.GetRecommendationsParams{ - Requests: []recommend.RecommendationsRequest{ - { - BoughtTogetherQuery: &recommend.BoughtTogetherQuery{ - Model: recommend.FBT_MODEL_BOUGHT_TOGETHER, - ObjectID: "test_query", - IndexName: "test_index", - Threshold: 0, - }, - }, + params := []recommend.RecommendationsRequest{{ + BoughtTogetherQuery: &recommend.BoughtTogetherQuery{ + Model: recommend.FBT_MODEL_BOUGHT_TOGETHER, + ObjectID: "test_query", + IndexName: "test_index", + Threshold: 0, }, - } + }} - searchResponse, err := recommendClient.GetRecommendations( - recommendClient.NewApiGetRecommendationsRequest(params), - ) + searchResponse, err := recommendClient.GetRecommendations(ctx, params) if err != nil { fmt.Printf("request error with SearchSingleIndex: %v\n", err) return 1 diff --git a/playground/go/search.go b/playground/go/search.go index e1989e3464e..8988a2011d7 100644 --- a/playground/go/search.go +++ b/playground/go/search.go @@ -1,20 +1,20 @@ package main import ( + "context" "fmt" - "github.com/algolia/algoliasearch-client-go/v4/algolia/search" - // "github.com/algolia/algoliasearch-client-go/v4/algolia/transport" + "github.com/algolia/algoliasearch-client-go/v4/algolia/next/search" ) -func testSearch(appID, apiKey string) int { +func testSearch(ctx context.Context, appID, apiKey string) int { // indexName := getEnvWithDefault("SEARCH_INDEX", "test_index") searchClient, err := search.NewClient(appID, apiKey) if err != nil { panic(err) } - err = searchClient.BrowseObjects("test-flag", *search.NewEmptyBrowseParamsObject(), search.WithAggregator(func(res any, err error) { + err = searchClient.BrowseObjects(ctx, "test-flag", *search.NewEmptyBrowseParamsObject(), search.WithAggregator(func(res any, err error) { if err != nil { panic(err) } @@ -24,31 +24,18 @@ func testSearch(appID, apiKey string) int { panic(err) } - // config := search.SearchConfiguration{ - // Configuration: transport.Configuration{ - // AppID: appID, - // ApiKey: apiKey, - // }, - // } - // - // config.WithTransformation("eu") - // - // fmt.Println(config.Transformation.Region) - // - // searchClient, err := search.NewClientWithConfig(config) - // if err != nil { - // panic(err) - // } - // - // watchResponse, err := searchClient.SaveObjectsWithTransformation("foo", []map[string]any{{"objectID": "foobarbaz"}}, search.WithWaitForTasks(true)) - // if err != nil { - // panic(err) - // } - // - // fmt.Printf("%#v\n", watchResponse) + // old way + //searchClient.Search(searchClient.NewApiSearchRequest(search.NewSearchMethodParams([]search.SearchQuery{ + // *search.SearchForHitsAsSearchQuery(search.NewSearchForHits("indexName", search.WithSearchForHitsQuery("foo"))), + //}))) + + // new way + //searchClient.Search(ctx, []search.SearchQuery{ + // search.NewSearchForHits("indexName").WithQuery("foo"), + //}, nil) /* - response, err := searchClient.AddOrUpdateObject( + response, err := searchClient.AddOrUpdateObject(ctx, searchClient.NewApiAddOrUpdateObjectRequest( indexName, "1", @@ -63,12 +50,12 @@ func testSearch(appID, apiKey string) int { panic(err) } - _, err = searchClient.WaitForTask(indexName, *response.TaskID) + _, err = searchClient.WaitForTask(ctx, indexName, *response.TaskID) if err != nil { panic(err) } - searchResponse, err := searchClient.Search( + searchResponse, err := searchClient.Search(ctx, searchClient.NewApiSearchRequest( search.NewSearchMethodParams( []search.SearchQuery{ diff --git a/specs/search/paths/search/browse.yml b/specs/search/paths/search/browse.yml index ddafd05d371..8c185f36926 100644 --- a/specs/search/paths/search/browse.yml +++ b/specs/search/paths/search/browse.yml @@ -13,23 +13,22 @@ post: browsing _just_ returns matching records. This can be useful if you want to export your indices. - - The Analytics API doesn't collect data when using `browse`. - - Records are ranked by attributes and custom ranking. - - There's no ranking for: typo-tolerance, number of matched words, proximity, geo distance. + - The Analytics API doesn't collect data when using `browse`. + - Records are ranked by attributes and custom ranking. + - There's no ranking for: typo-tolerance, number of matched words, proximity, geo distance. Browse requests automatically apply these settings: - - - `advancedSyntax`: `false` - - `attributesToHighlight`: `[]` - - `attributesToSnippet`: `[]` - - `distinct`: `false` - - `enablePersonalization`: `false` - - `enableRules`: `false` - - `facets`: `[]` - - `getRankingInfo`: `false` - - `ignorePlurals`: `false` - - `optionalFilters`: `[]` - - `typoTolerance`: `true` or `false` (`min` and `strict` evaluate to `true`) + - `advancedSyntax`: `false` + - `attributesToHighlight`: `[]` + - `attributesToSnippet`: `[]` + - `distinct`: `false` + - `enablePersonalization`: `false` + - `enableRules`: `false` + - `facets`: `[]` + - `getRankingInfo`: `false` + - `ignorePlurals`: `false` + - `optionalFilters`: `[]` + - `typoTolerance`: `true` or `false` (`min` and `strict` evaluate to `true`) If you send these parameters with your browse requests, they'll be ignored. parameters: diff --git a/specs/search/paths/search/search.yml b/specs/search/paths/search/search.yml index 688232c4948..a817870da4c 100644 --- a/specs/search/paths/search/search.yml +++ b/specs/search/paths/search/search.yml @@ -13,8 +13,8 @@ post: This can be useful in these cases: - - Different indices for different purposes, such as, one index for products, another one for marketing content. - - Multiple searches to the same index—for example, with different filters. + - Different indices for different purposes, such as, one index for products, another one for marketing content. + - Multiple searches to the same index—for example, with different filters. Use the helper `searchForHits` or `searchForFacets` to get the results in a more convenient format, if you already know the return type you want. requestBody: diff --git a/templates/go/api.mustache b/templates/go/api.mustache index 71c03d20ad8..53a21259b53 100644 --- a/templates/go/api.mustache +++ b/templates/go/api.mustache @@ -1,11 +1,11 @@ -// {{{generationBanner}}} +{{{appDescription}}} package {{packageName}} +// {{{generationBanner}}} + {{#operations}} import ( "context" - "encoding/json" - "fmt" "net/http" "net/url" "strings" @@ -28,7 +28,6 @@ import ( type config struct { // -- Request options for API calls - context context.Context queryParams url.Values headerParams map[string]string timeouts transport.RequestConfiguration @@ -75,12 +74,6 @@ func (r requestOption) apply(c *config) { r(c) } -func WithContext(ctx context.Context) requestOption { - return requestOption(func(c *config) { - c.context = ctx - }) -} - func WithHeaderParam(key string, value any) requestOption { return requestOption(func(c *config) { c.headerParams[key] = utils.ParameterToString(value) @@ -308,120 +301,135 @@ func replaceAllObjectsToChunkBatchOptions(opts []ReplaceAllObjectsOption) []Chun {{/isSearchClient}} {{#operation}} - {{#hasParams}} -func (r *{{#structPrefix}}{{&classname}}{{/structPrefix}}{{^structPrefix}}Api{{/structPrefix}}{{operationId}}Request) UnmarshalJSON(b []byte) error { - req := map[string]json.RawMessage{} - err := json.Unmarshal(b, &req) - if err != nil { - return fmt.Errorf("cannot unmarshal request: %w", err) - } - {{#allParams}} - if v, ok := req["{{#isQueryParam}}{{baseName}}{{/isQueryParam}}{{^isQueryParam}}{{paramName}}{{/isQueryParam}}"]; ok { - err = json.Unmarshal(v, &r.{{paramName}}) - if err != nil { - err = json.Unmarshal(b, &r.{{paramName}}) - if err != nil { - return fmt.Errorf("cannot unmarshal {{paramName}}: %w", err) - } - } - } {{#isBodyParam}}{{#required}}else { - err = json.Unmarshal(b, &r.{{paramName}}) - if err != nil { - return fmt.Errorf("cannot unmarshal body parameter {{paramName}}: %w", err) - } - }{{/required}}{{/isBodyParam}} - {{/allParams}} - - return nil -} - -// {{#structPrefix}}{{&classname}}{{/structPrefix}}{{^structPrefix}}Api{{/structPrefix}}{{operationId}}Request represents the request with all the parameters for the API call. -type {{#structPrefix}}{{&classname}}{{/structPrefix}}{{^structPrefix}}Api{{/structPrefix}}{{operationId}}Request struct { -{{#allParams}} - {{paramName}} {{^required}}{{^isPathParam}}{{^isFreeFormObject}}{{^isArray}}{{^isMap}}{{^isEnumRef}}*{{/isEnumRef}}{{/isMap}}{{/isArray}}{{/isFreeFormObject}}{{/isPathParam}}{{/required}}{{#required}}{{#isModel}}*{{/isModel}}{{/required}}{{{dataType}}} -{{/allParams}} +{{#hasOptionalParams}} +// {{operationId}}Options represents the optional params for the API call. +type {{operationId}}Options struct { + {{#optionalParams}} + {{nameInPascalCase}} {{^isFreeFormObject}}{{^isMap}}*{{/isMap}}{{/isFreeFormObject}}{{{dataType}}} + {{/optionalParams}} } {{#isDeprecated}} -// Deprecated +// Deprecated: {{operationId}}Options is deprecated {{/isDeprecated}} -//New{{#structPrefix}}{{&classname}}{{/structPrefix}}{{^structPrefix}}Api{{/structPrefix}}{{operationId}}Request creates an instance of the {{#structPrefix}}{{&classname}}{{/structPrefix}}{{^structPrefix}}Api{{/structPrefix}}{{operationId}}Request to be used for the API call. -func (c *APIClient) NewApi{{{nickname}}}Request({{#requiredParams}} {{paramName}} {{^isPathParam}}{{^isFreeFormObject}}{{^isArray}}{{^isMap}}{{^isPrimitiveType}}{{^isEnumRef}}*{{/isEnumRef}}{{/isPrimitiveType}}{{/isMap}}{{/isArray}}{{/isFreeFormObject}}{{/isPathParam}}{{{dataType}}} {{^-last}},{{/-last}}{{/requiredParams}}) {{#structPrefix}}{{&classname}}{{/structPrefix}}{{^structPrefix}}Api{{/structPrefix}}{{operationId}}Request { - return {{#structPrefix}}{{&classname}}{{/structPrefix}}{{^structPrefix}}Api{{/structPrefix}}{{operationId}}Request{ - {{#requiredParams}} - {{paramName}}: {{paramName}}, - {{/requiredParams}} - } +// New{{operationId}}Options creates an instance of the {{operationId}}Options used to add optional parameters to {{operationId}}WithOptions. +func New{{{operationId}}}Options() *{{operationId}}Options { + return &{{operationId}}Options{} } -{{#allParams}} -{{^required}} -// With{{#lambda.titlecase}}{{baseName}}{{/lambda.titlecase}} adds the {{paramName}} to the {{#structPrefix}}{{&classname}}{{/structPrefix}}{{^structPrefix}}Api{{/structPrefix}}{{operationId}}Request and returns the request for chaining. +{{#optionalParams}} +// With{{#lambda.titlecase}}{{baseName}}{{/lambda.titlecase}} {{#description}}{{{.}}}{{/description}}{{^description}}adds the {{paramName}} to the Api{{operationId}}Request and returns the request for chaining.{{/description}} {{#isDeprecated}} -// Deprecated +// Deprecated: With{{#lambda.titlecase}}{{baseName}}{{/lambda.titlecase}} is deprecated {{/isDeprecated}} -func (r {{#structPrefix}}{{&classname}}{{/structPrefix}}{{^structPrefix}}Api{{/structPrefix}}{{operationId}}Request) With{{#lambda.titlecase}}{{baseName}}{{/lambda.titlecase}}({{paramName}} {{^isFreeFormObject}}{{^isArray}}{{^isMap}}{{^isPrimitiveType}}{{^isEnumRef}}*{{/isEnumRef}}{{/isPrimitiveType}}{{/isMap}}{{/isArray}}{{/isFreeFormObject}}{{{dataType}}}) {{#structPrefix}}{{&classname}}{{/structPrefix}}{{^structPrefix}}Api{{/structPrefix}}{{operationId}}Request { - r.{{paramName}} = {{#isPrimitiveType}}{{^isMap}}&{{/isMap}}{{/isPrimitiveType}}{{paramName}} - return r +func (o *{{operationId}}Options) With{{#lambda.titlecase}}{{baseName}}{{/lambda.titlecase}}({{paramName}} {{#isModel}}*{{/isModel}}{{{dataType}}}) *{{operationId}}Options { + o.{{nameInPascalCase}} = {{^isModel}}{{^isMap}}&{{/isMap}}{{/isModel}}{{paramName}} + return o } +{{/optionalParams}} -{{/required}} -{{/allParams}} -{{/hasParams}} -/* -{{operationId}} calls the API and returns the raw response from it. - {{#notes}} +{{/hasOptionalParams}} - {{{unescapedNotes}}} - {{/notes}} +// {{operationId}} {{{notes}}} {{#vendorExtensions}} - {{#x-acl.0}} - - Required API Key ACLs:{{/x-acl.0}} - {{#x-acl}} - - {{.}} - {{/x-acl}} + {{#x-acl.0}} +// +// Required API Key ACLs:{{/x-acl.0}} + {{#x-acl}} +// - {{.}} + {{/x-acl}} {{/vendorExtensions}} - - Request can be constructed by NewApi{{operationId}}Request with parameters below. - {{#allParams}} - @param {{paramName}} {{dataType}}{{#description}} - {{{.}}}{{/description}} - {{/allParams}} - @param opts ...RequestOption - Optional parameters for the API call - @return *http.Response - The raw response from the API - @return []byte - The raw response body from the API - @return error - An error if the API call fails + {{#hasParams}} +// Parameters: + {{/hasParams}} + {{#requiredParams}} +// - {{paramName}} {{#description}}- {{{.}}}{{/description}} + {{/requiredParams}} + {{#optionalParams}} +// - {{paramName}} {{#description}}- {{{.}}}{{/description}} (in optionalParams) + {{/optionalParams}} +// - opts - Optional parameters for the API call (e.g. WithHeaderParam, WithReadTimeout...) {{#isDeprecated}} +// +// Deprecated: {{operationId}} is deprecated + {{/isDeprecated}} +func (c *APIClient) {{nickname}}(ctx context.Context, {{#requiredParams}}{{paramName}} {{#required}}{{#isModel}}*{{/isModel}}{{/required}}{{^required}}{{^isMap}}*{{/isMap}}{{/required}}{{{dataType}}}, {{/requiredParams}}{{#hasOptionalParams}}optionalParams *{{operationId}}Options, {{/hasOptionalParams}}opts ...RequestOption) ({{#returnType}}{{^isArray}}{{^returnTypeIsPrimitive}}*{{/returnTypeIsPrimitive}}{{/isArray}}{{{.}}}, {{/returnType}}error) { + {{#returnType}} + var returnValue {{^isArray}}{{^returnTypeIsPrimitive}}*{{/returnTypeIsPrimitive}}{{/isArray}}{{{.}}} + {{/returnType}} + + res, resBody, err := c.{{nickname}}WithHTTPInfo(ctx, {{#requiredParams}}{{paramName}}, {{/requiredParams}}{{#hasOptionalParams}}optionalParams, {{/hasOptionalParams}}opts...) + if err != nil { + return {{#returnType}}returnValue, {{/returnType}}err + } + if res == nil { + return {{#returnType}}returnValue, {{/returnType}}reportError("res is nil") + } + defer res.Body.Close() + + if res.StatusCode >= 300 { + return {{#returnType}}returnValue, {{/returnType}}c.decodeError(res, resBody) + } + + {{#returnType}} + err = c.decode(&returnValue, resBody) + if err != nil { + return {{#returnType}}returnValue, {{/returnType}}reportError("cannot decode result: %w", err) + } + {{/returnType}} + return {{#returnType}}returnValue, {{/returnType}}nil +} - Deprecated +// {{operationId}}WithHTTPInfo calls the API and returns the raw response from it. +// {{{notes}}} + {{#vendorExtensions}} + {{#x-acl.0}} +// +// Required API Key ACLs:{{/x-acl.0}} + {{#x-acl}} +// - {{.}} + {{/x-acl}} + {{/vendorExtensions}} + {{#hasParams}} +// +// Parameters: + {{/hasParams}} + {{#requiredParams}} +// - {{paramName}} {{#description}}- {{{.}}}{{/description}} + {{/requiredParams}} + {{#optionalParams}} +// - {{paramName}} {{#description}}- {{{.}}}{{/description}} (in optionalParams) + {{/optionalParams}} +// - opts - Optional parameters for the API call (e.g. WithHeaderParam, WithReadTimeout...) + {{#isDeprecated}} +// +// Deprecated: {{operationId}} is deprecated {{/isDeprecated}} - */ -func (c *APIClient) {{nickname}}WithHTTPInfo({{#hasParams}}r {{#structPrefix}}{{&classname}}{{/structPrefix}}{{^structPrefix}}Api{{/structPrefix}}{{operationId}}Request,{{/hasParams}} opts ...RequestOption) (*http.Response, []byte, error) { +func (c *APIClient) {{nickname}}WithHTTPInfo(ctx context.Context, {{#requiredParams}}{{paramName}} {{#required}}{{#isModel}}*{{/isModel}}{{/required}}{{^required}}{{^isMap}}*{{/isMap}}{{/required}}{{{dataType}}}, {{/requiredParams}}{{#hasOptionalParams}}optionalParams *{{operationId}}Options, {{/hasOptionalParams}}opts ...RequestOption) (*http.Response, []byte, error) { {{#vendorExtensions}} requestPath := "{{{path}}}"{{#pathParams}} - requestPath = strings.ReplaceAll(requestPath, {{=<% %>=}}"{<%baseName%>}"<%={{ }}=%>, {{#x-is-custom-request}}utils.ParameterToString(r.{{paramName}}){{/x-is-custom-request}}{{^x-is-custom-request}}url.PathEscape(utils.ParameterToString(r.{{paramName}})){{/x-is-custom-request}}){{/pathParams}} + requestPath = strings.ReplaceAll(requestPath, {{=<% %>=}}"{<%baseName%>}"<%={{ }}=%>, {{#x-is-custom-request}}utils.ParameterToString({{paramName}}){{/x-is-custom-request}}{{^x-is-custom-request}}url.PathEscape(utils.ParameterToString({{paramName}})){{/x-is-custom-request}}){{/pathParams}} {{/vendorExtensions}} {{#allParams}} {{#required}} {{#isString}} - if r.{{paramName}} == "" { + if {{paramName}} == "" { return nil, nil, reportError("Parameter `{{paramName}}` is required when calling `{{operationId}}`.") }{{/isString}}{{#isContainer}} - if len(r.{{paramName}}) == 0 { + if len({{paramName}}) == 0 { return nil, nil, reportError("Parameter `{{paramName}}` is required when calling `{{operationId}}`.") }{{/isContainer}}{{#isMap}} - if len(r.{{paramName}}) == 0 { + if len({{paramName}}) == 0 { return nil, nil, reportError("Parameter `{{paramName}}` is required when calling `{{operationId}}`.") }{{/isMap}}{{^isPrimitiveType}}{{^isContainer}}{{^isMap}}{{^isEnumRef}} - if r.{{paramName}} == nil { + if {{paramName}} == nil { return nil, nil, reportError("Parameter `{{paramName}}` is required when calling `{{operationId}}`.") }{{/isEnumRef}}{{/isMap}}{{/isContainer}}{{/isPrimitiveType}} {{/required}} {{/allParams}} conf := config{ - context: context.Background(), queryParams: url.Values{}, headerParams: map[string]string{}, {{#vendorExtensions.x-timeouts}} @@ -435,8 +443,8 @@ func (c *APIClient) {{nickname}}WithHTTPInfo({{#hasParams}}r {{#structPrefix}}{{ {{#vendorExtensions.x-is-custom-request}} {{#queryParams}} - {{^required}}if !utils.IsNilOrEmpty(r.{{paramName}}) { {{/required}} - for k, v := range r.{{paramName}} { + {{^required}}if {{#hasOptionalParams}}optionalParams != nil && {{/hasOptionalParams}}!utils.IsNilOrEmpty({{> param_name}}) { {{/required}} + for k, v := range {{> param_name}} { conf.queryParams.Set(k, utils.QueryParameterToString(v)) } {{^required}} } {{/required}} @@ -445,22 +453,22 @@ func (c *APIClient) {{nickname}}WithHTTPInfo({{#hasParams}}r {{#structPrefix}}{{ {{^vendorExtensions.x-is-custom-request}} {{#queryParams}} {{#required}} - conf.queryParams.Set("{{baseName}}", utils.QueryParameterToString({{^isFreeFormObject}}{{^isArray}}{{^isPrimitiveType}}{{^isEnumRef}}*{{/isEnumRef}}{{/isPrimitiveType}}{{/isArray}}{{/isFreeFormObject}}r.{{paramName}})) + conf.queryParams.Set("{{baseName}}", utils.QueryParameterToString({{^isFreeFormObject}}{{^isArray}}{{^isPrimitiveType}}{{^isEnumRef}}*{{/isEnumRef}}{{/isPrimitiveType}}{{/isArray}}{{/isFreeFormObject}}{{paramName}})) {{/required}} {{^required}} - if !utils.IsNilOrEmpty(r.{{paramName}}) { - conf.queryParams.Set("{{baseName}}", utils.QueryParameterToString({{^isFreeFormObject}}{{^isArray}}{{^isEnumRef}}*{{/isEnumRef}}{{/isArray}}{{/isFreeFormObject}}r.{{paramName}})) + if {{#hasOptionalParams}}optionalParams != nil && {{/hasOptionalParams}}!utils.IsNilOrEmpty({{> param_name}}) { + conf.queryParams.Set("{{baseName}}", utils.QueryParameterToString({{^isFreeFormObject}}*{{/isFreeFormObject}}{{> param_name}})) } {{/required}} {{/queryParams}} {{/vendorExtensions.x-is-custom-request}} {{#headerParams}} {{#required}} - conf.headerParams["{{baseName}}"] = utils.ParameterToString({{^isFreeFormObject}}{{^isArray}}{{^isPrimitiveType}}{{^isEnumRef}}*{{/isEnumRef}}{{/isPrimitiveType}}{{/isArray}}{{/isFreeFormObject}}r.{{paramName}}) + conf.headerParams["{{baseName}}"] = utils.ParameterToString({{^isFreeFormObject}}{{^isArray}}{{^isPrimitiveType}}{{^isEnumRef}}*{{/isEnumRef}}{{/isPrimitiveType}}{{/isArray}}{{/isFreeFormObject}}{{paramName}}) {{/required}} {{^required}} - if !utils.IsNilOrEmpty(r.{{paramName}}) { - conf.headerParams["{{baseName}}"] = utils.ParameterToString({{^isFreeFormObject}}{{^isArray}}{{^isEnumRef}}*{{/isEnumRef}}{{/isArray}}{{/isFreeFormObject}}r.{{paramName}}) + if {{#hasOptionalParams}}optionalParams != nil && {{/hasOptionalParams}}!utils.IsNilOrEmpty({{> param_name}}) { + conf.headerParams["{{baseName}}"] = utils.ParameterToString({{^isFreeFormObject}}*{{/isFreeFormObject}}{{> param_name}}) } {{/required}} {{/headerParams}} @@ -470,17 +478,55 @@ func (c *APIClient) {{nickname}}WithHTTPInfo({{#hasParams}}r {{#structPrefix}}{{ opt.apply(&conf) } - var postBody any - {{#bodyParams}} - // body params{{^required}} - if utils.IsNilOrEmpty(r.{{paramName}}) { - postBody = "{}" - } else { {{/required}} - postBody = r.{{paramName}}{{^required}} - } {{/required}} + // body params + {{#vendorExtensions.x-flat-body}} + postBody := struct{ + {{#vars}} + {{name}} {{^required}}{{^isFreeFormObject}}*{{/isFreeFormObject}}{{/required}}{{#required}}{{#isModel}}*{{/isModel}}{{/required}}{{{dataType}}} `json:"{{baseName}}{{^required}},omitempty{{/required}}"` + {{/vars}} + }{ + {{#vars}} + {{#required}} + {{name}}: {{nameInLowerCase}}, + {{/required}} + {{^hasOptionalParams}} + {{^required}} + {{name}}: {{nameInLowerCase}}, + {{/required}} + {{/hasOptionalParams}} + {{/vars}} + } + {{#hasOptionalParams}} + if optionalParams != nil { + {{#vars}} + {{^required}} + postBody.{{name}} = optionalParams.{{nameInPascalCase}} + {{/required}} + {{/vars}} + } + {{/hasOptionalParams}} + {{/vendorExtensions.x-flat-body}} + {{^vendorExtensions.x-flat-body}} + {{#required}} + postBody := {{paramName}} + {{/required}} + {{^required}} + var postBody any = "{}" + {{#hasOptionalParams}} + if optionalParams != nil { + postBody = optionalParams.{{nameInPascalCase}} + } + {{/hasOptionalParams}} + {{^hasOptionalParams}} + if !utils.IsNilOrEmpty({{paramName}}) { + postBody = {{paramName}} + } + {{/hasOptionalParams}} + {{/required}} + {{/vendorExtensions.x-flat-body}} {{/bodyParams}} - req, err := c.prepareRequest(conf.context, requestPath, http.Method{{httpMethod}}, postBody, conf.headerParams, conf.queryParams) + req, err := c.prepareRequest(ctx, requestPath, http.Method{{httpMethod}}, {{^bodyParams}}nil{{/bodyParams}}{{#bodyParams}}postBody{{/bodyParams}}, conf.headerParams, conf.queryParams) if err != nil { return nil, nil, err } @@ -488,37 +534,6 @@ func (c *APIClient) {{nickname}}WithHTTPInfo({{#hasParams}}r {{#structPrefix}}{{ return c.callAPI(req, {{#vendorExtensions}}{{#x-use-read-transporter}}true{{/x-use-read-transporter}}{{^x-use-read-transporter}}false{{/x-use-read-transporter}},{{/vendorExtensions}}conf.timeouts) } -/* -{{operationId}} casts the HTTP response body to a defined struct. -{{> operation_description}} -func (c *APIClient) {{nickname}}({{#hasParams}}r {{#structPrefix}}{{&classname}}{{/structPrefix}}{{^structPrefix}}Api{{/structPrefix}}{{operationId}}Request,{{/hasParams}} opts ...RequestOption) ({{#returnType}}{{^isArray}}{{^returnTypeIsPrimitive}}*{{/returnTypeIsPrimitive}}{{/isArray}}{{{.}}}, {{/returnType}}error) { - {{#returnType}} - var returnValue {{^isArray}}{{^returnTypeIsPrimitive}}*{{/returnTypeIsPrimitive}}{{/isArray}}{{{.}}} - {{/returnType}} - - res, resBody, err := c.{{nickname}}WithHTTPInfo({{#hasParams}}r, {{/hasParams}}opts...) - if err != nil { - return {{#returnType}}returnValue, {{/returnType}}err - } - if res == nil { - return {{#returnType}}returnValue, {{/returnType}}reportError("res is nil") - } - defer res.Body.Close() - - if res.StatusCode >= 300 { - return {{#returnType}}returnValue, {{/returnType}}c.decodeError(res, resBody) - } - - {{#returnType}} - err = c.decode(&returnValue, resBody) - if err != nil { - return {{#returnType}}returnValue, {{/returnType}}reportError("cannot decode result: %w", err) - } - - {{/returnType}} - return {{#returnType}}returnValue, {{/returnType}}nil -} - {{/operation}} {{/operations}} diff --git a/templates/go/client.mustache b/templates/go/client.mustache index a2154e74986..40dca4bd8cd 100644 --- a/templates/go/client.mustache +++ b/templates/go/client.mustache @@ -1,6 +1,7 @@ -// {{{generationBanner}}} package {{packageName}} +// {{{generationBanner}}} + import ( "bytes" "compress/gzip" @@ -311,7 +312,7 @@ func reportError(format string, a ...any) error { return fmt.Errorf(format, a...) } -// Set request body from an any. +// Set request body from an any func setBody(body any, c compression.Compression) (*bytes.Buffer, error) { if body == nil { return nil, nil diff --git a/templates/go/configuration.mustache b/templates/go/configuration.mustache index c301d631451..6d35c4ad09e 100644 --- a/templates/go/configuration.mustache +++ b/templates/go/configuration.mustache @@ -1,6 +1,7 @@ -// {{{generationBanner}}} package {{packageName}} +// {{{generationBanner}}} + import ( "github.com/algolia/algoliasearch-client-go/v4/algolia/transport" ) diff --git a/templates/go/guides/search/saveImageClassifications.mustache b/templates/go/guides/search/saveImageClassifications.mustache index 0c2aed4908b..d0eb83ce959 100644 --- a/templates/go/guides/search/saveImageClassifications.mustache +++ b/templates/go/guides/search/saveImageClassifications.mustache @@ -27,7 +27,7 @@ func saveImageClassifications() { images := []Image{} - err = client.BrowseObjects("", search.BrowseParamsObject{}, search.WithAggregator(func(res any, err error) { + err = client.BrowseObjects(context.Background(), "", search.BrowseParamsObject{}, search.WithAggregator(func(res any, err error) { if err != nil { panic(err) } diff --git a/templates/go/guides/search/saveImageClassificationsAndSettings.mustache b/templates/go/guides/search/saveImageClassificationsAndSettings.mustache index e49ec51dde5..9d52139e08d 100644 --- a/templates/go/guides/search/saveImageClassificationsAndSettings.mustache +++ b/templates/go/guides/search/saveImageClassificationsAndSettings.mustache @@ -27,7 +27,7 @@ func saveImageClassificationsAndSettings() { images := []Image{} - err = client.BrowseObjects("", search.BrowseParamsObject{}, search.WithAggregator(func(res any, err error) { + err = client.BrowseObjects(context.Background(), "", search.BrowseParamsObject{}, search.WithAggregator(func(res any, err error) { if err != nil { panic(err) } diff --git a/templates/go/guides/search/savePopularRecords.mustache b/templates/go/guides/search/savePopularRecords.mustache index 2c37c1a7167..22aa81de8ab 100644 --- a/templates/go/guides/search/savePopularRecords.mustache +++ b/templates/go/guides/search/savePopularRecords.mustache @@ -13,7 +13,7 @@ func savePopularRecords() { records := []map[string]any{ { /* Your records */ } } - err = client.BrowseObjects("", search.BrowseParamsObject{}, search.WithAggregator(func(res any, err error) { + err = client.BrowseObjects(context.Background(), "", search.BrowseParamsObject{}, search.WithAggregator(func(res any, err error) { if err != nil { panic(err) } diff --git a/templates/go/ingestion_helpers.mustache b/templates/go/ingestion_helpers.mustache index bfa11410336..410145a2c8e 100644 --- a/templates/go/ingestion_helpers.mustache +++ b/templates/go/ingestion_helpers.mustache @@ -1,15 +1,13 @@ -/* -ChunkedPush Chunks the given `objects` list in subset of 1000 elements max in order to make it fit in `push` requests by leveraging the Transformation pipeline setup in the Push connector (https://www.algolia.com/doc/guides/sending-and-managing-data/send-and-update-your-data/connectors/push/). - - @param indexName string - the index name to save objects into. - @param objects []map[string]any - List of objects to save. - @param action Action - The action to perform on the objects. - @param referenceIndexName *string - This is required when targeting an index that does not have a push connector setup (e.g. a tmp index), but you wish to attach another index's transformation to it (e.g. the source index name). - @param opts ...ChunkedBatchOption - Optional parameters for the request. - @return []WatchResponse - List of push responses. - @return error - Error if any. -*/ -func (c *APIClient) ChunkedPush(indexName string, objects []map[string]any, action Action, referenceIndexName *string, opts ...ChunkedBatchOption) ([]WatchResponse, error) { +// ChunkedPush Chunks the given `objects` list in subset of 1000 elements max in order to make it fit in `push` requests by leveraging the Transformation pipeline setup in the Push connector (https://www.algolia.com/doc/guides/sending-and-managing-data/send-and-update-your-data/connectors/push/). +// +// Parameters: +// - transformationID - Unique identifier of a transformation. +// - indexName string - the index name to save objects into. +// - objects []map[string]any - List of objects to save. +// - action Action - The action to perform on the objects. +// - referenceIndexName *string - This is required when targeting an index that does not have a push connector setup (e.g. a tmp index), but you wish to attach another index's transformation to it (e.g. the source index name). +// - opts - Optional parameters for the API call (e.g. WithHeaderParam, WithReadTimeout...) +func (c *APIClient) ChunkedPush(ctx context.Context, indexName string, objects []map[string]any, action Action, referenceIndexName *string, opts ...ChunkedBatchOption) ([]WatchResponse, error) { conf := config{ headerParams: map[string]string{}, waitForTasks: false, @@ -45,18 +43,12 @@ func (c *APIClient) ChunkedPush(indexName string, objects []map[string]any, acti return nil, reportError("unable to unmarshal the given `objects` to an `[]PushTaskRecords` payload: %w", err) } - request := c.NewApiPushRequest( - indexName, - NewEmptyPushTaskPayload(). - SetAction(action). - SetRecords(pushRecords), - ) - - if referenceIndexName != nil { - request = request.WithReferenceIndexName(*referenceIndexName) - } + opts := NewPushOptions() + if referenceIndexName != nil { + opts = opts.WithReferenceIndexName(*referenceIndexName) + } - resp, err := c.Push(request) + resp, err := c.Push(ctx, indexName, action, pushRecords, opts) if err != nil { return nil, err //nolint: wrapcheck } @@ -65,7 +57,6 @@ func (c *APIClient) ChunkedPush(indexName string, objects []map[string]any, acti records = make([]map[string]any, 0, len(objects)%conf.batchSize) } - if conf.waitForTasks && len(responses) > 0 && (len(responses)%waitBatchSize == 0 || i == len(objects)-1) { var waitableResponses []WatchResponse @@ -82,7 +73,7 @@ func (c *APIClient) ChunkedPush(indexName string, objects []map[string]any, acti return nil, reportError("received unexpected response from the push endpoint, eventID must not be undefined") } - return c.GetEvent(c.NewApiGetEventRequest(resp.RunID, *resp.EventID)) + return c.GetEvent(ctx, resp.RunID, *resp.EventID) }, func(response *Event, err error) (bool, error) { var apiErr *APIError @@ -104,4 +95,4 @@ func (c *APIClient) ChunkedPush(indexName string, objects []map[string]any, acti } return responses, nil -} \ No newline at end of file +} diff --git a/templates/go/model.mustache b/templates/go/model.mustache index 35ee884d6ec..41fdd31f556 100644 --- a/templates/go/model.mustache +++ b/templates/go/model.mustache @@ -1,6 +1,7 @@ -// {{{generationBanner}}} package {{packageName}} +// {{{generationBanner}}} + {{#models}} import ( "encoding/json" diff --git a/templates/go/model_enum.mustache b/templates/go/model_enum.mustache index 7f85e8da1e0..ee679dd1837 100644 --- a/templates/go/model_enum.mustache +++ b/templates/go/model_enum.mustache @@ -7,7 +7,7 @@ const ( {{#enumVars}} {{^-first}} {{/-first}} - {{#enumClassPrefix}}{{#lambda.screamingSnakeCase}}{{{classname}}}{{/lambda.screamingSnakeCase}}_{{/enumClassPrefix}}{{name}} {{{classname}}} = {{{value}}} + {{#lambda.screamingSnakeCase}}{{{classname}}}{{/lambda.screamingSnakeCase}}_{{name}} {{{classname}}} = {{{value}}} {{/enumVars}} {{/allowableValues}} ) diff --git a/templates/go/operation_description.mustache b/templates/go/operation_description.mustache deleted file mode 100644 index 44166eec5e5..00000000000 --- a/templates/go/operation_description.mustache +++ /dev/null @@ -1,23 +0,0 @@ -{{#notes}} - -{{{unescapedNotes}}} -{{/notes}} -{{#vendorExtensions}} -{{#x-acl.0}} - -Required API Key ACLs:{{/x-acl.0}} -{{#x-acl}} - - {{.}} -{{/x-acl}} -{{/vendorExtensions}} - -Request can be constructed by NewApi{{operationId}}Request with parameters below. - {{#allParams}} - @param {{paramName}} {{dataType}}{{#description}} - {{{.}}}{{/description}} - {{/allParams}} - {{#returnType}}@return {{{.}}}{{/returnType}} -{{#isDeprecated}} - -Deprecated -{{/isDeprecated}} -*/ diff --git a/templates/go/param_name.mustache b/templates/go/param_name.mustache new file mode 100644 index 00000000000..67c301f7399 --- /dev/null +++ b/templates/go/param_name.mustache @@ -0,0 +1 @@ +{{#hasOptionalParams}}optionalParams.{{nameInPascalCase}}{{/hasOptionalParams}}{{^hasOptionalParams}}{{paramName}}{{/hasOptionalParams}} \ No newline at end of file diff --git a/templates/go/search_helpers.mustache b/templates/go/search_helpers.mustache index a297bec029f..6d8db96caec 100644 --- a/templates/go/search_helpers.mustache +++ b/templates/go/search_helpers.mustache @@ -1,14 +1,7 @@ -/* -SearchForHits calls the `search` method but with certainty that we will only request Algolia records (hits) and not facets. -Disclaimer: We don't assert that the parameters you pass to this method only contains `hits` requests to prevent impacting search performances, this helper is purely for typing purposes. - - @param r ApiSearchRequest - Body of the `search` operation. - @param opts ...RequestOption - Optional parameters for the request. - @return []SearchResponse - List of hits. - @return error - Error if any. - */ -func (c *APIClient) SearchForHits(r ApiSearchRequest, opts ...RequestOption) ([]SearchResponse, error) { - res, err := c.Search(r, opts...) +// SearchForHits calls the `search` method but with certainty that we will only request Algolia records (hits) and not facets. +// Disclaimer: We don't assert that the parameters you pass to this method only contains `hits` requests to prevent impacting search performances, this helper is purely for typing purposes. +func (c *APIClient) SearchForHits(ctx context.Context, requests []SearchQuery, strategy *SearchStrategy, opts ...RequestOption) ([]SearchResponse, error) { + res, err := c.Search(ctx, requests, strategy, opts...) if err != nil { return nil, err } @@ -24,17 +17,10 @@ func (c *APIClient) SearchForHits(r ApiSearchRequest, opts ...RequestOption) ([] return slices.Clip(hits), nil } -/* -SearchForFacets calls the `search` method but with certainty that we will only request Algolia facets and not records (hits). -Disclaimer: We don't assert that the parameters you pass to this method only contains `facets` requests to prevent impacting search performances, this helper is purely for typing purposes. - - @param r ApiSearchRequest - Body of the `search` operation. - @param opts ...RequestOption - Optional parameters for the request. - @return []SearchForFacetValuesResponse - List of facet hits. - @return error - Error if any. - */ -func (c *APIClient) SearchForFacets(r ApiSearchRequest, opts ...RequestOption) ([]SearchForFacetValuesResponse, error) { - res, err := c.Search(r, opts...) +// SearchForFacets calls the `search` method but with certainty that we will only request Algolia facets and not records (hits). +// Disclaimer: We don't assert that the parameters you pass to this method only contains `facets` requests to prevent impacting search performances, this helper is purely for typing purposes. +func (c *APIClient) SearchForFacets(ctx context.Context,requests []SearchQuery, strategy *SearchStrategy, opts ...RequestOption) ([]SearchForFacetValuesResponse, error) { + res, err := c.Search(ctx, requests, strategy, opts...) if err != nil { return nil, err } @@ -50,18 +36,11 @@ func (c *APIClient) SearchForFacets(r ApiSearchRequest, opts ...RequestOption) ( return slices.Clip(facetHits), nil } -/* -WaitForTask waits for a task to be published. -It returns the task response if the operation was successful. -It returns an error if the operation failed. - - @param indexName string - Index name. - @param taskID int64 - Task ID. - @param opts ...IterableOption - Optional parameters for the request. - @return *GetTaskResponse - Task response. - @return error - Error if any. -*/ +// WaitForTask waits for a task to be published. +// It returns the task response if the operation was successful. +// It returns an error if the operation failed. func (c *APIClient) WaitForTask( + ctx context.Context, indexName string, taskID int64, opts ...IterableOption, @@ -73,7 +52,7 @@ func (c *APIClient) WaitForTask( return CreateIterable( //nolint:wrapcheck func(*GetTaskResponse, error) (*GetTaskResponse, error) { - return c.GetTask(c.NewApiGetTaskRequest(indexName, taskID), toRequestOptions(opts)...) + return c.GetTask(ctx, indexName, taskID, toRequestOptions(opts)...) }, func(response *GetTaskResponse, err error) (bool, error) { if err != nil || response == nil { @@ -86,17 +65,11 @@ func (c *APIClient) WaitForTask( ) } -/* -WaitForAppTask waits for an application-level task to be published. -It returns the task response if the operation was successful. -It returns an error if the operation failed. - - @param taskID int64 - Task ID. - @param opts ...IterableOption - Optional parameters for the request. - @return *GetTaskResponse - Task response. - @return error - Error if any. -*/ +// WaitForAppTask waits for an application-level task to be published. +// It returns the task response if the operation was successful. +// It returns an error if the operation failed. func (c *APIClient) WaitForAppTask( + ctx context.Context, taskID int64, opts ...IterableOption, ) (*GetTaskResponse, error) { @@ -107,7 +80,7 @@ func (c *APIClient) WaitForAppTask( return CreateIterable( //nolint:wrapcheck func(*GetTaskResponse, error) (*GetTaskResponse, error) { - return c.GetAppTask(c.NewApiGetAppTaskRequest(taskID), toRequestOptions(opts)...) + return c.GetAppTask(ctx, taskID, toRequestOptions(opts)...) }, func(response *GetTaskResponse, err error) (bool, error) { if err != nil || response == nil { @@ -138,26 +111,19 @@ func slicesEqualUnordered[T cmp.Ordered](a []T, b []T) bool { return slices.Equal(aCopy, bCopy) } -/* -WaitForApiKey waits for an API key to be created, deleted or updated. -It returns the API key response if the operation was successful. -It returns an error if the operation failed. - -The operation can be one of the following: - - "add": wait for the API key to be created - - "delete": wait for the API key to be deleted - - "update": wait for the API key to be updated - -If the operation is "update", the apiKey parameter must be set. -If the operation is "delete" or "add", the apiKey parameter is not used. - - @param key string - API key. - @param operation ApiKeyOperation - Operation type - add, delete or update. - @param opts ...WaitForApiKeyOption - Optional parameters for the request, you must provide WithApiKey if the operation is "update". - @return *GetApiKeyResponse - API key response. - @return error - Error if any. -*/ +// WaitForApiKey waits for an API key to be created, deleted or updated. +// It returns the API key response if the operation was successful. +// It returns an error if the operation failed. +// +// The operation can be one of the following: +// - "add": wait for the API key to be created +// - "delete": wait for the API key to be deleted +// - "update": wait for the API key to be updated +// +// If the operation is "update", the apiKey parameter must be set. +// If the operation is "delete" or "add", the apiKey parameter is not used. func (c *APIClient) WaitForApiKey( + ctx context.Context, key string, operation ApiKeyOperation, opts ...WaitForApiKeyOption, @@ -241,30 +207,23 @@ func (c *APIClient) WaitForApiKey( return CreateIterable( //nolint:wrapcheck func(*GetApiKeyResponse, error) (*GetApiKeyResponse, error) { - return c.GetApiKey(c.NewApiGetApiKeyRequest(key), toRequestOptions(opts)...) + return c.GetApiKey(ctx, key, toRequestOptions(opts)...) }, validateFunc, waitForApiKeyToIterableOptions(opts)..., ) } -/* -BrowseObjects allows to aggregate all the hits returned by the API calls. -Use the `WithAggregator` option to collect all the responses. - - @param indexName string - Index name. - @param browseParams BrowseParamsObject - Browse parameters. - @param opts ...IterableOption - Optional parameters for the request. - @return *BrowseResponse - Browse response. - @return error - Error if any. -*/ +// BrowseObjects allows to aggregate all the hits returned by the API calls. +// Use the `WithAggregator` option to collect all the responses. func (c *APIClient) BrowseObjects( + ctx context.Context, indexName string, browseParams BrowseParamsObject, opts ...IterableOption, ) error { if browseParams.HitsPerPage == nil { - browseParams.HitsPerPage = utils.ToPtr(int32(1000)) + browseParams.HitsPerPage = utils.ToPtr(1000) } _, err := CreateIterable( //nolint:wrapcheck @@ -274,7 +233,7 @@ func (c *APIClient) BrowseObjects( } return c.Browse( - c.NewApiBrowseRequest(indexName).WithBrowseParams(BrowseParamsObjectAsBrowseParams(&browseParams)), + ctx, indexName, BrowseParamsObjectAsBrowseParams(&browseParams), toRequestOptions(opts)..., ) }, @@ -287,45 +246,38 @@ func (c *APIClient) BrowseObjects( return err } -/* -BrowseRules allows to aggregate all the rules returned by the API calls. -Use the `WithAggregator` option to collect all the responses. - - @param indexName string - Index name. - @param searchRulesParams SearchRulesParams - Search rules parameters. - @param opts ...IterableOption - Optional parameters for the request. - @return *SearchRulesResponse - Search rules response. - @return error - Error if any. -*/ +// BrowseRules allows to aggregate all the rules returned by the API calls. +// Use the `WithAggregator` option to collect all the responses. func (c *APIClient) BrowseRules( + ctx context.Context, indexName string, - searchRulesParams SearchRulesParams, + optionalParams *SearchRulesOptions, opts ...IterableOption, ) error { - hitsPerPage := int32(1000) - if searchRulesParams.HitsPerPage != nil { - hitsPerPage = *searchRulesParams.HitsPerPage + hitsPerPage := 1000 + if optionalParams == nil { + optionalParams = NewSearchRulesOptions() + } + if optionalParams.HitsPerPage != nil { + hitsPerPage = *optionalParams.HitsPerPage } _, err := CreateIterable( //nolint:wrapcheck func(previousResponse *SearchRulesResponse, previousErr error) (*SearchRulesResponse, error) { - searchRulesParams.HitsPerPage = &hitsPerPage + optionalParams.HitsPerPage = &hitsPerPage if previousResponse != nil { - searchRulesParams.Page = utils.ToPtr(previousResponse.Page + 1) + optionalParams.Page = utils.ToPtr(previousResponse.Page + 1) } - if searchRulesParams.Page == nil { - searchRulesParams.Page = utils.ToPtr(int32(0)) + if optionalParams.Page == nil { + optionalParams.Page = utils.ToPtr(0) } - return c.SearchRules( - c.NewApiSearchRulesRequest(indexName).WithSearchRulesParams(&searchRulesParams), - toRequestOptions(opts)..., - ) + return c.SearchRules(ctx, indexName, optionalParams, toRequestOptions(opts)...) }, func(response *SearchRulesResponse, err error) (bool, error) { - return err != nil || (response != nil && len(response.Hits) < int(hitsPerPage)), err + return err != nil || (response != nil && len(response.Hits) < hitsPerPage), err }, opts..., ) @@ -333,45 +285,38 @@ func (c *APIClient) BrowseRules( return err } -/* -BrowseSynonyms allows to aggregate all the synonyms returned by the API calls. -Use the `WithAggregator` option to collect all the responses. - - @param indexName string - Index name. - @param searchSynonymsParams SearchSynonymsParams - Search synonyms parameters. - @param opts ...IterableOption - Optional parameters for the request. - @return *SearchSynonymsResponse - Search synonyms response. - @return error - Error if any. -*/ +// BrowseSynonyms allows to aggregate all the synonyms returned by the API calls. +// Use the `WithAggregator` option to collect all the responses. func (c *APIClient) BrowseSynonyms( + ctx context.Context, indexName string, - searchSynonymsParams SearchSynonymsParams, + optionalParams *SearchSynonymsOptions, opts ...IterableOption, ) error { - hitsPerPage := int32(1000) - if searchSynonymsParams.HitsPerPage != nil { - hitsPerPage = *searchSynonymsParams.HitsPerPage + hitsPerPage := 1000 + if optionalParams == nil { + optionalParams = NewSearchSynonymsOptions() + } + if optionalParams.HitsPerPage != nil { + hitsPerPage = *optionalParams.HitsPerPage } - if searchSynonymsParams.Page == nil { - searchSynonymsParams.Page = utils.ToPtr(int32(0)) + if optionalParams.Page == nil { + optionalParams.Page = utils.ToPtr(0) } _, err := CreateIterable( //nolint:wrapcheck func(previousResponse *SearchSynonymsResponse, previousErr error) (*SearchSynonymsResponse, error) { - searchSynonymsParams.HitsPerPage = &hitsPerPage + optionalParams.HitsPerPage = &hitsPerPage defer func() { - searchSynonymsParams.Page = utils.ToPtr(*searchSynonymsParams.Page + 1) + optionalParams.Page = utils.ToPtr(*optionalParams.Page + 1) }() - return c.SearchSynonyms( - c.NewApiSearchSynonymsRequest(indexName).WithSearchSynonymsParams(&searchSynonymsParams), - toRequestOptions(opts)..., - ) + return c.SearchSynonyms(ctx, indexName, optionalParams, toRequestOptions(opts)...) }, func(response *SearchSynonymsResponse, err error) (bool, error) { - return err != nil || (response != nil && len(response.Hits) < int(hitsPerPage)), err + return err != nil || (response != nil && len(response.Hits) < hitsPerPage), err }, opts..., ) @@ -427,15 +372,7 @@ func encodeRestrictions(restrictions *SecuredApiKeyRestrictions) (string, error) return strings.Join(queryString, "&"), nil } -/* -GenerateSecuredApiKey generates a public API key intended to restrict access -to certain records. This new key is built upon the existing key named `parentApiKey` and the following options. - - @param parentApiKey string - The parent API key. - @param restrictions *SecuredApiKeyRestrictions - The restrictions to apply to the new key. - @return string - The new secured API key. - @return error - Error if any. -*/ +// GenerateSecuredApiKey generates a public API key intended to restrict access to certain records. This new key is built upon the existing key named `parentApiKey` and the following options. func (c *APIClient) GenerateSecuredApiKey(parentApiKey string, restrictions *SecuredApiKeyRestrictions) (string, error) { h := hmac.New(sha256.New, []byte(parentApiKey)) @@ -454,13 +391,7 @@ func (c *APIClient) GenerateSecuredApiKey(parentApiKey string, restrictions *Sec return key, nil } -/* -GetSecuredApiKeyRemainingValidity retrieves the remaining validity of the previously generated `securedApiKey`, the `ValidUntil` parameter must have been provided. - - @param securedApiKey string - The secured API key. - @return time.Duration - The remaining validity of the secured API key. - @return error - Error if any. -*/ +// GetSecuredApiKeyRemainingValidity retrieves the remaining validity of the previously generated `securedApiKey`, the `ValidUntil` parameter must have been provided. func (c *APIClient) GetSecuredApiKeyRemainingValidity(securedApiKey string) (time.Duration, error) { if len(securedApiKey) == 0 { return 0, fmt.Errorf("given secured API key is empty: %s", securedApiKey) @@ -485,50 +416,24 @@ func (c *APIClient) GetSecuredApiKeyRemainingValidity(securedApiKey string) (tim return time.Until(time.Unix(int64(ts), 0)), nil } - - -/* -Helper: Saves the given array of objects in the given index. The `chunkedBatch` helper is used under the hood, which creates a `batch` requests with at most 1000 objects in it. - - @param indexName string - the index name to save objects into. - @param objects []map[string]any - List of objects to save. - @param opts ...ChunkedBatchOption - Optional parameters for the request. - @return []BatchResponse - List of batch responses. - @return error - Error if any. -*/ -func (c *APIClient) SaveObjects(indexName string, objects []map[string]any, opts ...ChunkedBatchOption) ([]BatchResponse, error) { - return c.ChunkedBatch(indexName, objects, ACTION_ADD_OBJECT, opts...) +// Helper: Saves the given array of objects in the given index. The `chunkedBatch` helper is used under the hood, which creates a `batch` requests with at most 1000 objects in it. +func (c *APIClient) SaveObjects(ctx context.Context, indexName string, objects []map[string]any, opts ...ChunkedBatchOption) ([]BatchResponse, error) { + return c.ChunkedBatch(ctx, indexName, objects, ACTION_ADD_OBJECT, opts...) } -/* -Helper: Deletes every records for the given objectIDs. The `chunkedBatch` helper is used under the hood, which creates a `batch` requests with at most 1000 objectIDs in it. - - @param indexName string - the index name to delete objects from. - @param objectIDs []string - List of objectIDs to delete. - @param opts ...ChunkedBatchOption - Optional parameters for the request. - @return []BatchResponse - List of batch responses. - @return error - Error if any. -*/ -func (c *APIClient) DeleteObjects(indexName string, objectIDs []string, opts ...ChunkedBatchOption) ([]BatchResponse, error) { +// Helper: Deletes every records for the given objectIDs. The `chunkedBatch` helper is used under the hood, which creates a `batch` requests with at most 1000 objectIDs in it. +func (c *APIClient) DeleteObjects(ctx context.Context, indexName string, objectIDs []string, opts ...ChunkedBatchOption) ([]BatchResponse, error) { objects := make([]map[string]any, 0, len(objectIDs)) for _, id := range objectIDs { objects = append(objects, map[string]any{"objectID":id}) } - return c.ChunkedBatch(indexName, objects, ACTION_DELETE_OBJECT, opts...) + return c.ChunkedBatch(ctx, indexName, objects, ACTION_DELETE_OBJECT, opts...) } -/* -Helper: Replaces object content of all the given objects according to their respective `objectID` field. The `chunkedBatch` helper is used under the hood, which creates a `batch` requests with at most 1000 objects in it. - - @param indexName string - the index name to save objects into. - @param objects []map[string]any - List of objects to save. - @param opts ...ChunkedBatchOption - Optional parameters for the request. - @return []BatchResponse - List of batch responses. - @return error - Error if any. -*/ -func (c *APIClient) PartialUpdateObjects(indexName string, objects []map[string]any, opts ...PartialUpdateObjectsOption) ([]BatchResponse, error) { +// Helper: Replaces object content of all the given objects according to their respective `objectID` field. The `chunkedBatch` helper is used under the hood, which creates a `batch` requests with at most 1000 objects in it. +func (c *APIClient) PartialUpdateObjects(ctx context.Context, indexName string, objects []map[string]any, opts ...PartialUpdateObjectsOption) ([]BatchResponse, error) { conf := config{ headerParams: map[string]string{}, createIfNotExists: true, @@ -546,20 +451,11 @@ func (c *APIClient) PartialUpdateObjects(indexName string, objects []map[string] action = ACTION_PARTIAL_UPDATE_OBJECT_NO_CREATE } - return c.ChunkedBatch(indexName, objects, action, partialUpdateObjectsToChunkedBatchOptions(opts)...) + return c.ChunkedBatch(ctx, indexName, objects, action, partialUpdateObjectsToChunkedBatchOptions(opts)...) } -/* -ChunkedBatch chunks the given `objects` list in subset of 1000 elements max in order to make it fit in `batch` requests. - - @param indexName string - the index name to save objects into. - @param objects []map[string]any - List of objects to save. - @param action Action - The action to perform on the objects. - @param opts ...ChunkedBatchOption - Optional parameters for the request. - @return []BatchResponse - List of batch responses. - @return error - Error if any. -*/ -func (c *APIClient) ChunkedBatch(indexName string, objects []map[string]any, action Action, opts ...ChunkedBatchOption) ([]BatchResponse, error) { +// ChunkedBatch chunks the given `objects` list in subset of 1000 elements max in order to make it fit in `batch` requests. +func (c *APIClient) ChunkedBatch(ctx context.Context, indexName string, objects []map[string]any, action Action, opts ...ChunkedBatchOption) ([]BatchResponse, error) { conf := config{ headerParams: map[string]string{}, waitForTasks: false, @@ -577,7 +473,7 @@ func (c *APIClient) ChunkedBatch(indexName string, objects []map[string]any, act requests = append(requests, *NewBatchRequest(action, obj)) if len(requests) == conf.batchSize || i == len(objects)-1 { - resp, err := c.Batch(c.NewApiBatchRequest(indexName, NewBatchWriteParams(requests)), toRequestOptions(opts)...) + resp, err := c.Batch(ctx, indexName, requests, toRequestOptions(opts)...) if err != nil { return nil, err } @@ -589,7 +485,7 @@ func (c *APIClient) ChunkedBatch(indexName string, objects []map[string]any, act if conf.waitForTasks { for _, resp := range responses { - _, err := c.WaitForTask(indexName, resp.TaskID, toIterableOptions(opts)...) + _, err := c.WaitForTask(ctx, indexName, resp.TaskID, toIterableOptions(opts)...) if err != nil { return nil, err } @@ -599,17 +495,9 @@ func (c *APIClient) ChunkedBatch(indexName string, objects []map[string]any, act return responses, nil } -/* -ReplaceAllObjectsWithTransformation is similar to the `replaceAllObjects` method but requires a Push connector (https://www.algolia.com/doc/guides/sending-and-managing-data/send-and-update-your-data/connectors/push/) to be created first, in order to transform records before indexing them to Algolia. The `region` must have been passed to the client instantiation method. -See https://api-clients-automation.netlify.app/docs/custom-helpers/#replaceallobjects for implementation details. - - @param indexName string - the index name to replace objects into. - @param objects []map[string]any - List of objects to replace. - @param opts ...ReplaceAllObjectsOption - Optional parameters for the request. - @return *ReplaceAllObjectsResponse - The response of the replace all objects operation. - @return error - Error if any. -*/ -func (c *APIClient) ReplaceAllObjectsWithTransformation(indexName string, objects []map[string]any, opts ...ReplaceAllObjectsOption) (*ReplaceAllObjectsWithTransformationResponse, error) { +// ReplaceAllObjectsWithTransformation is similar to the `replaceAllObjects` method but requires a Push connector (https://www.algolia.com/doc/guides/sending-and-managing-data/send-and-update-your-data/connectors/push/) to be created first, in order to transform records before indexing them to Algolia. The `region` must have been passed to the client instantiation method. +// See https://api-clients-automation.netlify.app/docs/custom-helpers/#replaceallobjects for implementation details. +func (c *APIClient) ReplaceAllObjectsWithTransformation(ctx context.Context, indexName string, objects []map[string]any, opts ...ReplaceAllObjectsOption) (*ReplaceAllObjectsWithTransformationResponse, error) { if c.ingestionTransporter == nil { return nil, reportError("`region` must be provided at client instantiation before calling this method.") } @@ -627,49 +515,49 @@ func (c *APIClient) ReplaceAllObjectsWithTransformation(indexName string, object opts = append(opts, WithWaitForTasks(true)) - copyResp, err := c.OperationIndex(c.NewApiOperationIndexRequest(indexName, NewOperationIndexParams(OPERATION_TYPE_COPY, tmpIndexName, WithOperationIndexParamsScope(conf.scopes))), toRequestOptions(opts)...) + copyResp, err := c.OperationIndex(ctx, indexName, OPERATION_TYPE_COPY, tmpIndexName, &conf.scopes, toRequestOptions(opts)...) if err != nil { return nil, err } - watchResp, err := c.ingestionTransporter.ChunkedPush(tmpIndexName, objects, ingestion.Action(ACTION_ADD_OBJECT), &indexName, toIngestionChunkedBatchOptions(replaceAllObjectsToChunkBatchOptions(opts))...) + watchResp, err := c.ingestionTransporter.ChunkedPush(ctx, tmpIndexName, objects, ingestion.Action(ACTION_ADD_OBJECT), &indexName, toIngestionChunkedBatchOptions(replaceAllObjectsToChunkBatchOptions(opts))...) if err != nil { - _, _ = c.DeleteIndex(c.NewApiDeleteIndexRequest(tmpIndexName)) + _, _ = c.DeleteIndex(ctx, tmpIndexName) return nil, err //nolint:wrapcheck } - _, err = c.WaitForTask(tmpIndexName, copyResp.TaskID, replaceAllObjectsToIterableOptions(opts)...) + _, err = c.WaitForTask(ctx, tmpIndexName, copyResp.TaskID, replaceAllObjectsToIterableOptions(opts)...) if err != nil { - _, _ = c.DeleteIndex(c.NewApiDeleteIndexRequest(tmpIndexName)) + _, _ = c.DeleteIndex(ctx, tmpIndexName) return nil, err } - copyResp, err = c.OperationIndex(c.NewApiOperationIndexRequest(indexName, NewOperationIndexParams(OPERATION_TYPE_COPY, tmpIndexName, WithOperationIndexParamsScope(conf.scopes))), toRequestOptions(opts)...) + copyResp, err = c.OperationIndex(ctx, indexName, OPERATION_TYPE_COPY, tmpIndexName, &conf.scopes, toRequestOptions(opts)...) if err != nil { - _, _ = c.DeleteIndex(c.NewApiDeleteIndexRequest(tmpIndexName)) + _, _ = c.DeleteIndex(ctx, tmpIndexName) return nil, err } - _, err = c.WaitForTask(tmpIndexName, copyResp.TaskID, replaceAllObjectsToIterableOptions(opts)...) + _, err = c.WaitForTask(ctx, tmpIndexName, copyResp.TaskID, replaceAllObjectsToIterableOptions(opts)...) if err != nil { - _, _ = c.DeleteIndex(c.NewApiDeleteIndexRequest(tmpIndexName)) + _, _ = c.DeleteIndex(ctx, tmpIndexName) return nil, err } - moveResp, err := c.OperationIndex(c.NewApiOperationIndexRequest(tmpIndexName, NewOperationIndexParams(OPERATION_TYPE_MOVE, indexName)), toRequestOptions(opts)...) + moveResp, err := c.OperationIndex(ctx, tmpIndexName, OPERATION_TYPE_MOVE, indexName, nil, toRequestOptions(opts)...) if err != nil { - _, _ = c.DeleteIndex(c.NewApiDeleteIndexRequest(tmpIndexName)) + _, _ = c.DeleteIndex(ctx, tmpIndexName) return nil, err } - _, err = c.WaitForTask(tmpIndexName, moveResp.TaskID, replaceAllObjectsToIterableOptions(opts)...) + _, err = c.WaitForTask(ctx, tmpIndexName, moveResp.TaskID, replaceAllObjectsToIterableOptions(opts)...) if err != nil { - _, _ = c.DeleteIndex(c.NewApiDeleteIndexRequest(tmpIndexName)) + _, _ = c.DeleteIndex(ctx, tmpIndexName) return nil, err } @@ -693,17 +581,9 @@ func (c *APIClient) ReplaceAllObjectsWithTransformation(indexName string, object }, nil } -/* -ReplaceAllObjects replaces all objects (records) in the given `indexName` with the given `objects`. A temporary index is created during this process in order to backup your data. -See https://api-clients-automation.netlify.app/docs/custom-helpers/#replaceallobjects for implementation details. - - @param indexName string - the index name to replace objects into. - @param objects []map[string]any - List of objects to replace. - @param opts ...ReplaceAllObjectsOption - Optional parameters for the request. - @return *ReplaceAllObjectsResponse - The response of the replace all objects operation. - @return error - Error if any. -*/ -func (c *APIClient) ReplaceAllObjects(indexName string, objects []map[string]any, opts ...ReplaceAllObjectsOption) (*ReplaceAllObjectsResponse, error) { +// ReplaceAllObjects replaces all objects (records) in the given `indexName` with the given `objects`. A temporary index is created during this process in order to backup your data. +// See https://api-clients-automation.netlify.app/docs/add-new-api-client#5-helpers for implementation details. +func (c *APIClient) ReplaceAllObjects(ctx context.Context, indexName string, objects []map[string]any, opts ...ReplaceAllObjectsOption) (*ReplaceAllObjectsResponse, error) { tmpIndexName := fmt.Sprintf("%s_tmp_%d", indexName, time.Now().UnixNano()) conf := config{ @@ -717,49 +597,49 @@ func (c *APIClient) ReplaceAllObjects(indexName string, objects []map[string]any opts = append(opts, WithWaitForTasks(true)) - copyResp, err := c.OperationIndex(c.NewApiOperationIndexRequest(indexName, NewOperationIndexParams(OPERATION_TYPE_COPY, tmpIndexName, WithOperationIndexParamsScope(conf.scopes))), toRequestOptions(opts)...) + copyResp, err := c.OperationIndex(ctx, indexName, OPERATION_TYPE_COPY, tmpIndexName, &conf.scopes, toRequestOptions(opts)...) if err != nil { return nil, err } - batchResp, err := c.ChunkedBatch(tmpIndexName, objects, ACTION_ADD_OBJECT, replaceAllObjectsToChunkBatchOptions(opts)...) + batchResp, err := c.ChunkedBatch(ctx, tmpIndexName, objects, ACTION_ADD_OBJECT, replaceAllObjectsToChunkBatchOptions(opts)...) if err != nil { - _, _ = c.DeleteIndex(c.NewApiDeleteIndexRequest(tmpIndexName)) + _, _ = c.DeleteIndex(ctx, tmpIndexName) return nil, err } - _, err = c.WaitForTask(tmpIndexName, copyResp.TaskID, replaceAllObjectsToIterableOptions(opts)...) + _, err = c.WaitForTask(ctx, tmpIndexName, copyResp.TaskID, replaceAllObjectsToIterableOptions(opts)...) if err != nil { - _, _ = c.DeleteIndex(c.NewApiDeleteIndexRequest(tmpIndexName)) + _, _ = c.DeleteIndex(ctx, tmpIndexName) return nil, err } - copyResp, err = c.OperationIndex(c.NewApiOperationIndexRequest(indexName, NewOperationIndexParams(OPERATION_TYPE_COPY, tmpIndexName, WithOperationIndexParamsScope(conf.scopes))), toRequestOptions(opts)...) + copyResp, err = c.OperationIndex(ctx, indexName, OPERATION_TYPE_COPY, tmpIndexName, &conf.scopes, toRequestOptions(opts)...) if err != nil { - _, _ = c.DeleteIndex(c.NewApiDeleteIndexRequest(tmpIndexName)) + _, _ = c.DeleteIndex(ctx, tmpIndexName) return nil, err } - _, err = c.WaitForTask(tmpIndexName, copyResp.TaskID, replaceAllObjectsToIterableOptions(opts)...) + _, err = c.WaitForTask(ctx, tmpIndexName, copyResp.TaskID, replaceAllObjectsToIterableOptions(opts)...) if err != nil { - _, _ = c.DeleteIndex(c.NewApiDeleteIndexRequest(tmpIndexName)) + _, _ = c.DeleteIndex(ctx, tmpIndexName) return nil, err } - moveResp, err := c.OperationIndex(c.NewApiOperationIndexRequest(tmpIndexName, NewOperationIndexParams(OPERATION_TYPE_MOVE, indexName)), toRequestOptions(opts)...) + moveResp, err := c.OperationIndex(ctx, tmpIndexName, OPERATION_TYPE_MOVE, indexName, nil, toRequestOptions(opts)...) if err != nil { - _, _ = c.DeleteIndex(c.NewApiDeleteIndexRequest(tmpIndexName)) + _, _ = c.DeleteIndex(ctx, tmpIndexName) return nil, err } - _, err = c.WaitForTask(tmpIndexName, moveResp.TaskID, replaceAllObjectsToIterableOptions(opts)...) + _, err = c.WaitForTask(ctx, tmpIndexName, moveResp.TaskID, replaceAllObjectsToIterableOptions(opts)...) if err != nil { - _, _ = c.DeleteIndex(c.NewApiDeleteIndexRequest(tmpIndexName)) + _, _ = c.DeleteIndex(ctx, tmpIndexName) return nil, err } @@ -774,8 +654,8 @@ func (c *APIClient) ReplaceAllObjects(indexName string, objects []map[string]any // Exists returns whether an initialized index exists or not, along with a nil // error. When encountering a network error, a non-nil error is returned along // with false. -func (c *APIClient) IndexExists(indexName string) (bool, error) { - _, err := c.GetSettings(c.NewApiGetSettingsRequest(indexName)) +func (c *APIClient) IndexExists(ctx context.Context, indexName string) (bool, error) { + _, err := c.GetSettings(ctx, indexName, nil) if err == nil { return true, nil } @@ -788,33 +668,28 @@ func (c *APIClient) IndexExists(indexName string) (bool, error) { return false, err } -/* -Helper: Similar to the `SaveObjects` method but requires a Push connector (https://www.algolia.com/doc/guides/sending-and-managing-data/send-and-update-your-data/connectors/push/) to be created first, in order to transform records before indexing them to Algolia. The `region` must've been passed to the client's config at instantiation. - - @param indexName string - the index name to save objects into. - @param objects []map[string]any - List of objects to save. - @param opts ...ChunkedBatchOption - Optional parameters for the request. - @return []BatchResponse - List of batch responses. - @return error - Error if any. -*/ -func (c *APIClient) SaveObjectsWithTransformation(indexName string, objects []map[string]any, opts ...ChunkedBatchOption) ([]ingestion.WatchResponse, error) { +// Helper: Similar to the `SaveObjects` method but requires a Push connector (https://www.algolia.com/doc/guides/sending-and-managing-data/send-and-update-your-data/connectors/push/) to be created first, in order to transform records before indexing them to Algolia. The `region` must've been passed to the client's config at instantiation. +// +// Parameters: +// - indexName string - the index name to save objects into. +// - objects []map[string]any - List of objects to save. +// - opts - Optional parameters for the API call (e.g. WithHeaderParam, WithReadTimeout...) +func (c *APIClient) SaveObjectsWithTransformation(ctx context.Context, indexName string, objects []map[string]any, opts ...ChunkedBatchOption) ([]ingestion.WatchResponse, error) { if c.ingestionTransporter == nil { return nil, reportError("`region` must be provided at client instantiation before calling this method.") } - return c.ingestionTransporter.ChunkedPush(indexName, objects, ingestion.Action(ACTION_ADD_OBJECT), nil, toIngestionChunkedBatchOptions(opts)...) //nolint:wrapcheck + return c.ingestionTransporter.ChunkedPush(ctx, indexName, objects, ingestion.Action(ACTION_ADD_OBJECT), nil, toIngestionChunkedBatchOptions(opts)...) //nolint:wrapcheck } -/* -Helper: Similar to the `PartialUpdateObjects` method but requires a Push connector (https://www.algolia.com/doc/guides/sending-and-managing-data/send-and-update-your-data/connectors/push/) to be created first, in order to transform records before indexing them to Algolia. The `region` must've been passed to the client instantiation method. - - @param indexName string - the index name to save objects into. - @param objects []map[string]any - List of objects to save. - @param opts ...ChunkedBatchOption - Optional parameters for the request. - @return []BatchResponse - List of batch responses. - @return error - Error if any. -*/ -func (c *APIClient) PartialUpdateObjectsWithTransformation(indexName string, objects []map[string]any, opts ...PartialUpdateObjectsOption) ([]ingestion.WatchResponse, error) { +// Helper: Similar to the `PartialUpdateObjects` method but requires a Push connector (https://www.algolia.com/doc/guides/sending-and-managing-data/send-and-update-your-data/connectors/push/) to be created first, in order to transform records before indexing them to Algolia. The `region` must've been passed to the client instantiation method. +// +// Parameters: +// - ctx context.Context - The context to use for the request. +// - indexName string - the index name to save objects into. +// - objects []map[string]any - List of objects to save. +// - opts - Optional parameters for the API call (e.g. WithHeaderParam, WithReadTimeout...) +func (c *APIClient) PartialUpdateObjectsWithTransformation(ctx context.Context, indexName string, objects []map[string]any, opts ...PartialUpdateObjectsOption) ([]ingestion.WatchResponse, error) { if c.ingestionTransporter == nil { return nil, reportError("`region` must be provided at client instantiation before calling this method.") } @@ -836,5 +711,5 @@ func (c *APIClient) PartialUpdateObjectsWithTransformation(indexName string, obj action = ACTION_PARTIAL_UPDATE_OBJECT_NO_CREATE } - return c.ingestionTransporter.ChunkedPush(indexName, objects, ingestion.Action(action), nil, toIngestionChunkedBatchOptions(partialUpdateObjectsToChunkedBatchOptions(opts))...) //nolint:wrapcheck + return c.ingestionTransporter.ChunkedPush(ctx, indexName, objects, ingestion.Action(action), nil, toIngestionChunkedBatchOptions(partialUpdateObjectsToChunkedBatchOptions(opts))...) //nolint:wrapcheck } \ No newline at end of file diff --git a/templates/go/snippets/import.mustache b/templates/go/snippets/import.mustache index 67d0b34473a..4fab4f3172d 100644 --- a/templates/go/snippets/import.mustache +++ b/templates/go/snippets/import.mustache @@ -1,4 +1,4 @@ import ( - "github.com/algolia/algoliasearch-client-go/v4/algolia/{{clientImport}}" + "github.com/algolia/algoliasearch-client-go/v4/algolia/next/{{clientImport}}" "github.com/algolia/algoliasearch-client-go/v4/algolia/utils" -) \ No newline at end of file +) diff --git a/templates/go/snippets/method.mustache b/templates/go/snippets/method.mustache index 3788cb4dfef..cc4e4b9dd22 100644 --- a/templates/go/snippets/method.mustache +++ b/templates/go/snippets/method.mustache @@ -1,6 +1,7 @@ -// {{generationBanner}} package snippets +// {{generationBanner}} + // >IMPORT {{> snippets/import}} // IMPORT< diff --git a/templates/go/tests/client/benchmark.mustache b/templates/go/tests/client/benchmark.mustache index 7c1462fe531..97026140371 100644 --- a/templates/go/tests/client/benchmark.mustache +++ b/templates/go/tests/client/benchmark.mustache @@ -1,15 +1,17 @@ -// {{generationBanner}} package benchmark +// {{generationBanner}} + import ( "testing" - + "regexp" + "context" "github.com/stretchr/testify/require" "gotests/tests" - "github.com/algolia/algoliasearch-client-go/v4/algolia/{{clientImport}}" + "github.com/algolia/algoliasearch-client-go/v4/algolia/next/{{clientImport}}" "github.com/algolia/algoliasearch-client-go/v4/algolia/transport" "github.com/algolia/algoliasearch-client-go/v4/algolia/call" "github.com/algolia/algoliasearch-client-go/v4/algolia/utils" diff --git a/templates/go/tests/client/client.mustache b/templates/go/tests/client/client.mustache index a597f36543e..86905b4f7c3 100644 --- a/templates/go/tests/client/client.mustache +++ b/templates/go/tests/client/client.mustache @@ -1,18 +1,20 @@ -// {{generationBanner}} package client +// {{generationBanner}} + import ( "encoding/json" "net/url" "testing" - "time" + "regexp" + "context" "github.com/kinbiko/jsonassert" "github.com/stretchr/testify/require" "gotests/tests" - "github.com/algolia/algoliasearch-client-go/v4/algolia/{{clientImport}}" + "github.com/algolia/algoliasearch-client-go/v4/algolia/next/{{clientImport}}" "github.com/algolia/algoliasearch-client-go/v4/algolia/transport" "github.com/algolia/algoliasearch-client-go/v4/algolia/compression" "github.com/algolia/algoliasearch-client-go/v4/algolia/utils" diff --git a/templates/go/tests/e2e/e2e.mustache b/templates/go/tests/e2e/e2e.mustache index 23552e8e754..7183e8e0c83 100644 --- a/templates/go/tests/e2e/e2e.mustache +++ b/templates/go/tests/e2e/e2e.mustache @@ -1,10 +1,12 @@ -// {{generationBanner}} package e2e +// {{generationBanner}} + import ( "encoding/json" "os" "testing" + "context" "github.com/stretchr/testify/require" "github.com/kinbiko/jsonassert" @@ -12,7 +14,7 @@ import ( "gotests/tests" - "github.com/algolia/algoliasearch-client-go/v4/algolia/{{clientImport}}" + "github.com/algolia/algoliasearch-client-go/v4/algolia/next/{{clientImport}}" ) func createE2E{{#lambda.titlecase}}{{clientPrefix}}{{/lambda.titlecase}}Client(t *testing.T) *{{clientPrefix}}.APIClient { diff --git a/templates/go/tests/generateInnerParams.mustache b/templates/go/tests/generateInnerParams.mustache index 7a4ff09f866..47bd315c52f 100644 --- a/templates/go/tests/generateInnerParams.mustache +++ b/templates/go/tests/generateInnerParams.mustache @@ -1,3 +1,3 @@ -{{#isVerbatim}}{{{value}}}{{/isVerbatim}}{{#isHelper}}{{#goFunctionalParam}}{{clientPrefix}}.With{{#lambda.pascalcase}}{{key}}{{/lambda.pascalcase}}({{/goFunctionalParam}}{{/isHelper}}{{#isNull}}{{#inClientTest}}tests.ZeroValue[{{#isNullObject}}*{{clientPrefix}}.{{/isNullObject}}{{objectName}}](){{/inClientTest}}{{^inClientTest}}nil{{/inClientTest}}{{/isNull}}{{#isString}}"{{#lambda.escapeQuotes}}{{{value}}}{{/lambda.escapeQuotes}}"{{/isString}}{{#isInteger}}{{{value}}}{{/isInteger}}{{#isLong}}{{{value}}}{{/isLong}}{{#isDouble}}{{{value}}}{{/isDouble}}{{#isBoolean}}{{{value}}}{{/isBoolean}}{{#isEnum}}{{clientPrefix}}.{{objectName}}("{{{value}}}"){{/isEnum}}{{#isArray}} +{{#isVerbatim}}{{{value}}}{{/isVerbatim}}{{#isHelper}}{{#goFunctionalParam}}{{clientPrefix}}.With{{#lambda.pascalcase}}{{key}}{{/lambda.pascalcase}}({{/goFunctionalParam}}{{/isHelper}}{{#isNull}}{{#inClientTest}}tests.ZeroValue[{{#isNullObject}}*{{clientPrefix}}.{{/isNullObject}}{{objectName}}](){{/inClientTest}}{{^inClientTest}}nil{{/inClientTest}}{{/isNull}}{{#isString}}"{{#lambda.escapeQuotes}}{{{value}}}{{/lambda.escapeQuotes}}"{{/isString}}{{#isInteger}}{{{value}}}{{/isInteger}}{{#isLong}}{{{value}}}{{/isLong}}{{#isDouble}}{{{value}}}{{/isDouble}}{{#isBoolean}}{{{value}}}{{/isBoolean}}{{#isEnum}}{{clientPrefix}}.{{#lambda.screamingSnakeCase}}{{{objectName}}}{{/lambda.screamingSnakeCase}}_{{#lambda.toEnum}}{{value}}{{/lambda.toEnum}}{{/isEnum}}{{#isArray}} {{> tests/arrayType}}{{^value.isEmpty}}{ {{#value}}{{#isObject}}*{{/isObject}}{{#oneOfModel}}{{^isObject}}*{{/isObject}}{{/oneOfModel}}{{> tests/generateParams}},{{/value}} }{{/value.isEmpty}}{{/isArray}}{{#isObject}} {{clientPrefix}}.NewEmpty{{objectName}}(){{#value}}{{#isAdditionalProperty}}.SetAdditionalProperty("{{{key}}}", {{> tests/generateParams}}){{/isAdditionalProperty}}{{^isAdditionalProperty}}.Set{{#lambda.pascalcase}}{{{key}}}{{/lambda.pascalcase}}({{> tests/generateParams}}){{/isAdditionalProperty}}{{/value}}{{/isObject}}{{#isFreeFormObject}}{{#isAnyType}}map[string]any{ {{#value}}{{#entrySet}}"{{{key}}}": "{{{value}}}",{{/entrySet}}{{/value}} }{{/isAnyType}}{{^isAnyType}}{{> tests/mapType}}{ {{#value}}"{{{key}}}": {{#oneOfModel}}{{^isObject}}*{{/isObject}}{{/oneOfModel}}{{#isObject}}*{{/isObject}}{{> tests/generateParams}},{{/value}} }{{/isAnyType}}{{/isFreeFormObject}}{{#isHelper}}{{#goFunctionalParam}}){{/goFunctionalParam}}{{/isHelper}} \ No newline at end of file diff --git a/templates/go/tests/inlineOptional.mustache b/templates/go/tests/inlineOptional.mustache new file mode 100644 index 00000000000..97ac147fe15 --- /dev/null +++ b/templates/go/tests/inlineOptional.mustache @@ -0,0 +1 @@ +{{#hasInlineOptional}}{{#parametersWithDataType}}{{^required}}{{^isFreeFormObject}}{{^isObject}}{{^isVerbatim}}utils.ToPtr({{/isVerbatim}}{{/isObject}}{{/isFreeFormObject}}{{> tests/generateParams}}{{^isFreeFormObject}}{{^isObject}}{{^isVerbatim}}){{/isVerbatim}}{{/isObject}}{{/isFreeFormObject}},{{/required}}{{/parametersWithDataType}}{{/hasInlineOptional}} \ No newline at end of file diff --git a/templates/go/tests/method.mustache b/templates/go/tests/method.mustache index d2819805aef..e089af1e0ca 100644 --- a/templates/go/tests/method.mustache +++ b/templates/go/tests/method.mustache @@ -1,2 +1 @@ -client.{{#lambda.titlecase}}{{method}}{{/lambda.titlecase}}({{#hasParams}}{{^isHelper}}client.NewApi{{#lambda.titlecase}}{{method}}{{/lambda.titlecase}}Request({{/isHelper}} - {{#parametersWithDataType}}{{#required}}{{> tests/generateParams}},{{/required}}{{/parametersWithDataType}} {{^isHelper}}){{#parametersWithDataType}}{{^required}}.With{{#lambda.pascalcase}}{{{key}}}{{/lambda.pascalcase}}({{> tests/generateParams}}){{#-last}},{{/-last}}{{/required}}{{/parametersWithDataType}}{{/isHelper}}{{#isHelper}}{{#parametersWithDataType}}{{^required}}{{> tests/generateParams}},{{/required}}{{/parametersWithDataType}}{{/isHelper}}{{/hasParams}}{{#requestOptions}}{{#queryParameters.parametersWithDataType}}{{clientPrefix}}.WithQueryParam("{{{key}}}", {{> tests/generateInnerParams}}),{{/queryParameters.parametersWithDataType}}{{#headers.parametersWithDataType}}{{clientPrefix}}.WithHeaderParam("{{{key}}}", {{> tests/generateInnerParams}}),{{/headers.parametersWithDataType}} {{#timeouts.read}} ,{{clientPrefix}}.WithReadTimeout({{.}} * time.Millisecond), {{/timeouts.read}} {{#timeouts.write}} ,{{clientPrefix}}.WithWriteTimeout({{.}} * time.Millisecond), {{/timeouts.write}} {{#timeouts.connect}} ,{{clientPrefix}}.WithConnectTimeout({{.}} * time.Millisecond), {{/timeouts.connect}} {{/requestOptions}}) \ No newline at end of file +client.{{#lambda.titlecase}}{{method}}{{/lambda.titlecase}}({{#isAsyncMethod}}context.Background(), {{/isAsyncMethod}}{{> tests/requiredParams}}{{> tests/optionalWrapper}}{{> tests/nilWrapper}}{{> tests/inlineOptional}}{{> tests/requestOptions}}) \ No newline at end of file diff --git a/templates/go/tests/nilWrapper.mustache b/templates/go/tests/nilWrapper.mustache new file mode 100644 index 00000000000..d570014b6e5 --- /dev/null +++ b/templates/go/tests/nilWrapper.mustache @@ -0,0 +1 @@ +{{#hasNilOptional}}nil,{{/hasNilOptional}} \ No newline at end of file diff --git a/templates/go/tests/optionalWrapper.mustache b/templates/go/tests/optionalWrapper.mustache new file mode 100644 index 00000000000..ee1ba5c6315 --- /dev/null +++ b/templates/go/tests/optionalWrapper.mustache @@ -0,0 +1 @@ +{{#hasOptionalWrapper}}{{^isHelper}}{{clientPrefix}}.New{{#lambda.titlecase}}{{method}}{{/lambda.titlecase}}Options(){{#parametersWithDataType}}{{^required}}.With{{#lambda.pascalcase}}{{{key}}}{{/lambda.pascalcase}}({{> tests/generateParams}}){{/required}}{{/parametersWithDataType}}{{/isHelper}}{{#isHelper}}{{#parametersWithDataType}}{{^required}}{{> tests/generateParams}}{{^-last}},{{/-last}} {{/required}}{{/parametersWithDataType}}{{/isHelper}}{{#requestOptions}},{{/requestOptions}}{{/hasOptionalWrapper}} \ No newline at end of file diff --git a/templates/go/tests/requestOptions.mustache b/templates/go/tests/requestOptions.mustache new file mode 100644 index 00000000000..ebba80c50fa --- /dev/null +++ b/templates/go/tests/requestOptions.mustache @@ -0,0 +1 @@ +{{#requestOptions}}{{#queryParameters.parametersWithDataType}}{{clientPrefix}}.WithQueryParam("{{{key}}}", {{> tests/generateInnerParams}}),{{/queryParameters.parametersWithDataType}}{{#headers.parametersWithDataType}}{{clientPrefix}}.WithHeaderParam("{{{key}}}", {{> tests/generateInnerParams}}),{{/headers.parametersWithDataType}} {{#timeouts.read}} ,{{clientPrefix}}.WithReadTimeout({{.}} * time.Millisecond), {{/timeouts.read}} {{#timeouts.write}} {{clientPrefix}}.WithWriteTimeout({{.}} * time.Millisecond), {{/timeouts.write}} {{#timeouts.connect}} ,{{clientPrefix}}.WithConnectTimeout({{.}} * time.Millisecond), {{/timeouts.connect}} {{/requestOptions}} \ No newline at end of file diff --git a/templates/go/tests/requests/requests.mustache b/templates/go/tests/requests/requests.mustache index d1bb0c837b3..6bb006cbfb6 100644 --- a/templates/go/tests/requests/requests.mustache +++ b/templates/go/tests/requests/requests.mustache @@ -5,13 +5,14 @@ import ( "encoding/json" "testing" "time" + "context" "github.com/kinbiko/jsonassert" "github.com/stretchr/testify/require" "gotests/tests" - "github.com/algolia/algoliasearch-client-go/v4/algolia/{{clientImport}}" + "github.com/algolia/algoliasearch-client-go/v4/algolia/next/{{clientImport}}" "github.com/algolia/algoliasearch-client-go/v4/algolia/transport" "github.com/algolia/algoliasearch-client-go/v4/algolia/utils" ) diff --git a/templates/go/tests/requiredParams.mustache b/templates/go/tests/requiredParams.mustache new file mode 100644 index 00000000000..b93d5910466 --- /dev/null +++ b/templates/go/tests/requiredParams.mustache @@ -0,0 +1 @@ +{{#parametersWithDataType}}{{#required}}{{> tests/generateParams}},{{/required}}{{/parametersWithDataType}} \ No newline at end of file diff --git a/templates/java/tests/generateInnerParams.mustache b/templates/java/tests/generateInnerParams.mustache index 81796c232b2..a6deb95d191 100644 --- a/templates/java/tests/generateInnerParams.mustache +++ b/templates/java/tests/generateInnerParams.mustache @@ -20,7 +20,7 @@ {{{value}}} {{/isBoolean}} {{#isEnum}} - {{{objectName}}}.{{#lambda.javaEnum}}{{{value}}}{{/lambda.javaEnum}} + {{{objectName}}}.{{#lambda.toEnum}}{{{value}}}{{/lambda.toEnum}} {{/isEnum}} {{#isArray}} Arrays.asList({{#value}}{{> tests/generateParams}}{{^-last}},{{/-last}}{{/value}}) diff --git a/tests/CTS/requests/abtesting-v3/addABTests.json b/tests/CTS/requests/abtesting-v3/addABTests.json index 388d8341f84..2a649004b8a 100644 --- a/tests/CTS/requests/abtesting-v3/addABTests.json +++ b/tests/CTS/requests/abtesting-v3/addABTests.json @@ -2,9 +2,7 @@ { "testName": "addABTests with minimal parameters", "parameters": { - "endAt": "2022-12-31T00:00:00.000Z", "name": "myABTest", - "metrics": [{"name": "myMetric"}], "variants": [ { "index": "AB_TEST_1", @@ -14,15 +12,19 @@ "index": "AB_TEST_2", "trafficPercentage": 50 } - ] + ], + "metrics": [ + { + "name": "myMetric" + } + ], + "endAt": "2022-12-31T00:00:00.000Z" }, "request": { "path": "/3/abtests", "method": "POST", "body": { - "endAt": "2022-12-31T00:00:00.000Z", "name": "myABTest", - "metrics": [{"name": "myMetric"}], "variants": [ { "index": "AB_TEST_1", @@ -32,7 +34,13 @@ "index": "AB_TEST_2", "trafficPercentage": 50 } - ] + ], + "metrics": [ + { + "name": "myMetric" + } + ], + "endAt": "2022-12-31T00:00:00.000Z" } } } diff --git a/tests/CTS/requests/abtesting-v3/scheduleABTest.json b/tests/CTS/requests/abtesting-v3/scheduleABTest.json index 2a6df45bcb5..ef01f58b070 100644 --- a/tests/CTS/requests/abtesting-v3/scheduleABTest.json +++ b/tests/CTS/requests/abtesting-v3/scheduleABTest.json @@ -2,10 +2,7 @@ { "testName": "scheduleABTest with minimal parameters", "parameters": { - "endAt": "2022-12-31T00:00:00.000Z", - "scheduledAt": "2022-11-31T00:00:00.000Z", "name": "myABTest", - "metrics": [{"name": "myMetric"}], "variants": [ { "index": "AB_TEST_1", @@ -15,16 +12,20 @@ "index": "AB_TEST_2", "trafficPercentage": 50 } - ] + ], + "metrics": [ + { + "name": "myMetric" + } + ], + "scheduledAt": "2022-11-31T00:00:00.000Z", + "endAt": "2022-12-31T00:00:00.000Z" }, "request": { "path": "/3/abtests/schedule", "method": "POST", "body": { - "endAt": "2022-12-31T00:00:00.000Z", - "scheduledAt": "2022-11-31T00:00:00.000Z", "name": "myABTest", - "metrics": [{"name": "myMetric"}], "variants": [ { "index": "AB_TEST_1", @@ -34,7 +35,14 @@ "index": "AB_TEST_2", "trafficPercentage": 50 } - ] + ], + "metrics": [ + { + "name": "myMetric" + } + ], + "scheduledAt": "2022-11-31T00:00:00.000Z", + "endAt": "2022-12-31T00:00:00.000Z" } } } diff --git a/tests/CTS/requests/abtesting/addABTests.json b/tests/CTS/requests/abtesting/addABTests.json index 2c25924d4bf..3a68a9ed126 100644 --- a/tests/CTS/requests/abtesting/addABTests.json +++ b/tests/CTS/requests/abtesting/addABTests.json @@ -2,7 +2,6 @@ { "testName": "addABTests with minimal parameters", "parameters": { - "endAt": "2022-12-31T00:00:00.000Z", "name": "myABTest", "variants": [ { @@ -13,13 +12,13 @@ "index": "AB_TEST_2", "trafficPercentage": 50 } - ] + ], + "endAt": "2022-12-31T00:00:00.000Z" }, "request": { "path": "/2/abtests", "method": "POST", "body": { - "endAt": "2022-12-31T00:00:00.000Z", "name": "myABTest", "variants": [ { @@ -30,7 +29,8 @@ "index": "AB_TEST_2", "trafficPercentage": 50 } - ] + ], + "endAt": "2022-12-31T00:00:00.000Z" } } } diff --git a/tests/CTS/requests/abtesting/scheduleABTest.json b/tests/CTS/requests/abtesting/scheduleABTest.json index 87a1c0bc216..f51988b34bc 100644 --- a/tests/CTS/requests/abtesting/scheduleABTest.json +++ b/tests/CTS/requests/abtesting/scheduleABTest.json @@ -2,8 +2,6 @@ { "testName": "scheduleABTest with minimal parameters", "parameters": { - "endAt": "2022-12-31T00:00:00.000Z", - "scheduledAt": "2022-11-31T00:00:00.000Z", "name": "myABTest", "variants": [ { @@ -14,14 +12,14 @@ "index": "AB_TEST_2", "trafficPercentage": 50 } - ] + ], + "scheduledAt": "2022-11-31T00:00:00.000Z", + "endAt": "2022-12-31T00:00:00.000Z" }, "request": { "path": "/2/abtests/schedule", "method": "POST", "body": { - "endAt": "2022-12-31T00:00:00.000Z", - "scheduledAt": "2022-11-31T00:00:00.000Z", "name": "myABTest", "variants": [ { @@ -32,7 +30,9 @@ "index": "AB_TEST_2", "trafficPercentage": 50 } - ] + ], + "scheduledAt": "2022-11-31T00:00:00.000Z", + "endAt": "2022-12-31T00:00:00.000Z" } } } diff --git a/tests/output/go/.golangci.yml b/tests/output/go/.golangci.yml index a81e164d960..e12675c4f2f 100644 --- a/tests/output/go/.golangci.yml +++ b/tests/output/go/.golangci.yml @@ -13,6 +13,7 @@ linters: - goconst - godoclint - gomoddirectives + - ineffassign - ireturn - lll - maintidx