diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index 069961c0b6c..27250ad5a20 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -78,9 +78,9 @@ runs: if: ${{ inputs.language == 'go' }} shell: bash run: | - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.60.3 - echo "$(go env GOPATH)/bin" >> $GITHUB_PATH + curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/HEAD/install.sh | sh -s -- -b $(go env GOPATH)/bin v2.5.0 go install golang.org/x/tools/cmd/goimports@v0.22.0 + echo "$(go env GOPATH)/bin" >> $GITHUB_PATH - name: Cache golangci-lint analysis if: ${{ inputs.language == 'go' }} diff --git a/clients/algoliasearch-client-go/.golangci.yml b/clients/algoliasearch-client-go/.golangci.yml index 6a638b3644e..ef10120bd06 100644 --- a/clients/algoliasearch-client-go/.golangci.yml +++ b/clients/algoliasearch-client-go/.golangci.yml @@ -1,71 +1,60 @@ -linters-settings: - govet: - enable-all: true - disable: - - fieldalignment - - revive: - rules: - - name: var-naming - disabled: true - +version: "2" +run: + concurrency: 2 linters: - enable-all: true - + default: all disable: - - godox - - bodyclose - - contextcheck - - interfacebloat - - gci - - gosmopolitan - - wsl - - varnamelen - - nlreturn + - canonicalheader + - containedctx + - copyloopvar + - cyclop + - depguard + - dupl + - dupword - err113 - - gochecknoglobals - - exhaustruct - exhaustive - - depguard - - lll + - exhaustruct - forbidigo - - gochecknoinits - - cyclop - - errorlint - - gomnd - - tagliatelle - - nilnil - - stylecheck - - musttag - - errchkjson - - nonamedreturns - - inamedparam - - ineffassign - - dupword - - nestif - - goconst - funlen - - dupl - - unparam + - gochecknoglobals - gocognit - - forcetypeassert - - wastedassign + - goconst - gocyclo - - maintidx - - copyloopvar + - godoclint + - inamedparam - intrange - - canonicalheader + - lll + - maintidx - mnd + - nestif + - nilnil + - nonamedreturns - perfsprint - - containedctx - - # Deprecated - - execinquery - - exportloopref - -issues: - exclude-generated: disable - -run: - concurrency: 2 - timeout: 10m + - recvcheck + - tagliatelle + - varnamelen + - wsl + settings: + govet: + enable-all: true + disable: + - fieldalignment + revive: + rules: + - name: var-naming + disabled: true + staticcheck: + checks: ["all", "-ST1005", "-ST1016"] + exclusions: + generated: disable + presets: + - comments + - std-error-handling +formatters: + enable: + - gofmt + - gofumpt + - golines + settings: + golines: + max-len: 150 diff --git a/clients/algoliasearch-client-go/algolia/debug/debug.go b/clients/algoliasearch-client-go/algolia/debug/debug.go index 56a237de604..1e777633001 100644 --- a/clients/algoliasearch-client-go/algolia/debug/debug.go +++ b/clients/algoliasearch-client-go/algolia/debug/debug.go @@ -30,8 +30,11 @@ func Display(input any) { if !debug { return } + start := time.Now() + var msg string + switch v := input.(type) { case *http.Request: msg = debugRequest(v) @@ -40,6 +43,7 @@ func Display(input any) { default: msg = fmt.Sprintf("do not know how to display %#v", v) } + Println(msg) fmt.Printf("took %s\n", time.Since(start)) } @@ -52,6 +56,7 @@ func Printf(format string, a ...any) { if !debug { return } + msg := fmt.Sprintf(format, a...) fmt.Printf("> ALGOLIA DEBUG: %s", msg) } diff --git a/clients/algoliasearch-client-go/algolia/debug/utils.go b/clients/algoliasearch-client-go/algolia/debug/utils.go index 8086105c3cd..391463ab90d 100644 --- a/clients/algoliasearch-client-go/algolia/debug/utils.go +++ b/clients/algoliasearch-client-go/algolia/debug/utils.go @@ -16,11 +16,14 @@ func copyReadCloser(r io.ReadCloser) (io.ReadCloser, string) { if r == nil { return nil, "" } + data, err := io.ReadAll(r) _ = r.Close() + if err != nil { return nil, "" } + return io.NopCloser(bytes.NewReader(data)), string(data) } @@ -29,10 +32,12 @@ func decodeGzipContent(in string) (string, error) { if err != nil { return in, fmt.Errorf("cannot open content with gzip.Reader: %w", err) } + out, err := io.ReadAll(gr) if err != nil { return in, fmt.Errorf("cannot read content from gzip.Reader: %w", err) } + return string(out), nil } @@ -58,10 +63,12 @@ func extractBody(body io.ReadCloser, c compression.Compression) (io.ReadCloser, func prettyPrintJSON(input string) string { var b bytes.Buffer + err := json.Indent(&b, []byte(input), "\t", " ") if err != nil { return input } + return strings.TrimSuffix(b.String(), "\n") } @@ -88,8 +95,10 @@ func debugRequest(req *http.Request) string { if strings.Contains(strings.ToLower(k), "algolia") { str = strings.Repeat("*", len(str)) } + msg += fmt.Sprintf("\theader=%s:%q\n", k, str) } + msg += fmt.Sprintf("\tbody=\n\t%s\n", prettyPrintJSON(body)) return msg @@ -101,6 +110,7 @@ func debugResponse(res *http.Response) string { } var body string + res.Body, body = extractBody(res.Body, compression.NONE) msg := "> ALGOLIA DEBUG response:\n" diff --git a/clients/algoliasearch-client-go/algolia/errs/no_more_host_to_try_err.go b/clients/algoliasearch-client-go/algolia/errs/no_more_host_to_try_err.go index 9ac4268c5f1..4ea1d22b22d 100644 --- a/clients/algoliasearch-client-go/algolia/errs/no_more_host_to_try_err.go +++ b/clients/algoliasearch-client-go/algolia/errs/no_more_host_to_try_err.go @@ -27,6 +27,7 @@ func (e *NoMoreHostToTryError) Error() string { if len(e.intermediateNetworkErrors) > 0 { return fmt.Errorf("%s %w", baseErr, errors.Join(e.intermediateNetworkErrors...)).Error() } + return fmt.Sprintf("%s You can use 'ExposeIntermediateNetworkErrors: true' in the config to investigate.", baseErr) } diff --git a/clients/algoliasearch-client-go/algolia/transport/configuration.go b/clients/algoliasearch-client-go/algolia/transport/configuration.go index f2c06aa0203..538c32f1905 100644 --- a/clients/algoliasearch-client-go/algolia/transport/configuration.go +++ b/clients/algoliasearch-client-go/algolia/transport/configuration.go @@ -8,7 +8,7 @@ import ( type Configuration struct { AppID string - ApiKey string + ApiKey string //nolint:staticcheck Hosts []StatefulHost DefaultHeader map[string]string diff --git a/clients/algoliasearch-client-go/algolia/transport/retry_strategy.go b/clients/algoliasearch-client-go/algolia/transport/retry_strategy.go index 860a756de10..66a241544a6 100644 --- a/clients/algoliasearch-client-go/algolia/transport/retry_strategy.go +++ b/clients/algoliasearch-client-go/algolia/transport/retry_strategy.go @@ -2,6 +2,7 @@ package transport import ( "context" + "errors" "net" "strings" "sync" @@ -13,14 +14,16 @@ import ( type Outcome int const ( - DefaultReadTimeout = 5 * time.Second - DefaultWriteTimeout = 30 * time.Second - Success Outcome = iota Failure Retry ) +const ( + DefaultReadTimeout = 5 * time.Second + DefaultWriteTimeout = 30 * time.Second +) + type Host struct { scheme string host string @@ -29,6 +32,7 @@ type Host struct { type RetryStrategy struct { sync.RWMutex + hosts []StatefulHost writeTimeout time.Duration readTimeout time.Duration @@ -99,16 +103,19 @@ func (s *RetryStrategy) Decide(h Host, code int, err error) Outcome { if err == nil && is2xx(code) { s.markUp(h) + return Success } if isTimeoutError(err) { s.markTimeout(h) + return Retry } - if !(isZero(code) || is4xx(code) || is2xx(code)) || isNetworkError(err) { + if (!isZero(code) && !is4xx(code) && !is2xx(code)) || isNetworkError(err) { s.markDown(h) + return Retry } @@ -119,6 +126,7 @@ func (s *RetryStrategy) markUp(host Host) { for _, h := range s.hosts { if h.host == host.host { h.markUp() + return } } @@ -128,6 +136,7 @@ func (s *RetryStrategy) markTimeout(host Host) { for _, h := range s.hosts { if h.host == host.host { h.markTimeout() + return } } @@ -137,6 +146,7 @@ func (s *RetryStrategy) markDown(host Host) { for _, h := range s.hosts { if h.host == host.host { h.markDown() + return } } @@ -146,7 +156,10 @@ func isNetworkError(err error) bool { if err == nil { return false } - _, ok := err.(net.Error) + + var netError net.Error + + ok := errors.As(err, &netError) // We need to ensure that the error is a net.Error but not a // context.DeadlineExceeded error (which is actually a net.Error), because // we do not want to consider context.DeadlineExceeded as an error. @@ -157,6 +170,7 @@ func isTimeoutError(err error) bool { if err == nil { return false } + return strings.Contains(err.Error(), context.DeadlineExceeded.Error()) } diff --git a/clients/algoliasearch-client-go/algolia/transport/transport.go b/clients/algoliasearch-client-go/algolia/transport/transport.go index fc8e77069d6..65961cb13fe 100644 --- a/clients/algoliasearch-client-go/algolia/transport/transport.go +++ b/clients/algoliasearch-client-go/algolia/transport/transport.go @@ -52,8 +52,9 @@ func prepareRetryableRequest(req *http.Request) (*http.Request, error) { bodyBytes, err := io.ReadAll(req.Body) if err != nil { - return nil, fmt.Errorf("cannot read body: %v", err) + return nil, fmt.Errorf("cannot read body: %w", err) } + _ = req.Body.Close() // close the original body // Set up GetBody to recreate the body for retries @@ -130,6 +131,7 @@ func (t *Transport) Request(ctx context.Context, req *http.Request, k call.Kind, // already cancelled. if ctx.Err() != nil { cancel() + return res, nil, err } @@ -137,14 +139,18 @@ func (t *Transport) Request(ctx context.Context, req *http.Request, k call.Kind, case Success, Failure: body, errBody := io.ReadAll(res.Body) errClose := res.Body.Close() + cancel() + res.Body = io.NopCloser(bytes.NewBuffer(body)) if errBody != nil { - return res, nil, fmt.Errorf("cannot read body: %v", errBody) + return res, nil, fmt.Errorf("cannot read body: %w", errBody) } + if errClose != nil { - return res, nil, fmt.Errorf("cannot close response's body: %v", errClose) + return res, nil, fmt.Errorf("cannot close response's body: %w", errClose) } + return res, body, err default: if err != nil { @@ -153,9 +159,12 @@ func (t *Transport) Request(ctx context.Context, req *http.Request, k call.Kind, msg := fmt.Sprintf("cannot perform request:\n\tStatusCode=%d\n\tmethod=%s\n\turl=%s\n\t", res.StatusCode, req.Method, req.URL) intermediateNetworkErrors = append(intermediateNetworkErrors, errors.New(msg)) } + if res != nil && res.Body != nil { - if err = res.Body.Close(); err != nil { + err = res.Body.Close() + if err != nil { cancel() + return res, nil, fmt.Errorf("cannot close response's body before retry: %w", err) } } @@ -181,6 +190,7 @@ func (t *Transport) request(req *http.Request, host Host, timeout time.Duration, if err != nil { msg := fmt.Sprintf("cannot perform request:\n\terror=%v\n\tmethod=%s\n\turl=%s", err, req.Method, req.URL) + var nerr net.Error if errors.As(err, &nerr) { // Because net.Error and error have different meanings for the @@ -193,6 +203,7 @@ func (t *Transport) request(req *http.Request, host Host, timeout time.Duration, } else { err = errors.New(msg) } + return nil, err } @@ -203,5 +214,6 @@ func shouldCompress(c compression.Compression, method string, body any) bool { isValidMethod := method == http.MethodPut || method == http.MethodPost isCompressionEnabled := c != compression.NONE isBodyNonEmpty := body != nil + return isCompressionEnabled && isValidMethod && isBodyNonEmpty } diff --git a/clients/algoliasearch-client-go/algolia/transport/utils.go b/clients/algoliasearch-client-go/algolia/transport/utils.go index 14fd91f59ce..e988010c749 100644 --- a/clients/algoliasearch-client-go/algolia/transport/utils.go +++ b/clients/algoliasearch-client-go/algolia/transport/utils.go @@ -8,9 +8,11 @@ func Shuffle(hosts []StatefulHost) []StatefulHost { if hosts == nil { return nil } + shuffled := make([]StatefulHost, len(hosts)) for i, v := range rand.Perm(len(hosts)) { shuffled[i] = hosts[v] } + return shuffled } diff --git a/clients/algoliasearch-client-go/algolia/utils/utils.go b/clients/algoliasearch-client-go/algolia/utils/utils.go index 317a2eb9758..84a57fe7584 100644 --- a/clients/algoliasearch-client-go/algolia/utils/utils.go +++ b/clients/algoliasearch-client-go/algolia/utils/utils.go @@ -58,6 +58,7 @@ func IsNilOrEmpty(i any) bool { if i == nil { return true } + switch reflect.TypeOf(i).Kind() { case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.UnsafePointer, reflect.Interface, reflect.Slice: return reflect.ValueOf(i).IsNil() @@ -78,11 +79,13 @@ func ParameterToString(obj any) string { objKind := reflect.TypeOf(obj).Kind() if objKind == reflect.Slice { var result []string + sliceValue := reflect.ValueOf(obj) for i := 0; i < sliceValue.Len(); i++ { element := sliceValue.Index(i).Interface() result = append(result, ParameterToString(element)) } + return strings.Join(result, ",") } @@ -101,5 +104,6 @@ func ParameterToString(obj any) string { func HasKey[T any](m map[string]T, key string) bool { _, ok := m[key] + return ok } diff --git a/scripts/docker/Dockerfile.base b/scripts/docker/Dockerfile.base index 1eb8c6194c1..71f87ec6e02 100644 --- a/scripts/docker/Dockerfile.base +++ b/scripts/docker/Dockerfile.base @@ -51,10 +51,9 @@ ENV PATH="$VIRTUAL_ENV/bin:$PATH" # Go COPY --from=go-builder /usr/local/go/ /usr/local/go/ RUN echo "export PATH=$PATH:/usr/local/go/bin:/root/go/bin" >> ~/.profile && source ~/.profile \ - && curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.60.3 \ + && curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/HEAD/install.sh | sh -s -- -b $(go env GOPATH)/bin v2.5.0 \ && go install golang.org/x/tools/cmd/goimports@v0.22.0 - # Dart COPY --from=dart-builder /usr/lib/dart/ /usr/lib/dart/ RUN echo "export PATH=/usr/lib/dart/bin:/root/.pub-cache/bin:$PATH" >> ~/.profile && source ~/.profile \ diff --git a/specs/common/schemas/ingestion/Observability.yml b/specs/common/schemas/ingestion/Observability.yml index 1b4e5e1f4a0..3c3bbab3240 100644 --- a/specs/common/schemas/ingestion/Observability.yml +++ b/specs/common/schemas/ingestion/Observability.yml @@ -1,6 +1,6 @@ Event: type: object - description: An event describe a step of the task execution flow.. + description: An event describe a step of the task execution flow. additionalProperties: false properties: eventID: diff --git a/specs/search/paths/rules/common/schemas.yml b/specs/search/paths/rules/common/schemas.yml index 5f2acd94672..6fdf13ef162 100644 --- a/specs/search/paths/rules/common/schemas.yml +++ b/specs/search/paths/rules/common/schemas.yml @@ -289,7 +289,7 @@ automaticFacetFilter: description: | Whether the filter is disjunctive or conjunctive. - If true the filter has multiple matches, multiple occurences are combined with the logical `OR` operation. - If false, multiple occurences are combined with the logical `AND` operation. + If true the filter has multiple matches, multiple occurrences are combined with the logical `OR` operation. + If false, multiple occurrences are combined with the logical `AND` operation. required: - facet diff --git a/templates/go/api.mustache b/templates/go/api.mustache index c5592fd4640..71c03d20ad8 100644 --- a/templates/go/api.mustache +++ b/templates/go/api.mustache @@ -11,7 +11,6 @@ import ( "strings" {{#isSearchClient}} "github.com/algolia/algoliasearch-client-go/v4/algolia/errs" - "github.com/algolia/algoliasearch-client-go/v4/algolia/ingestion" "cmp" "crypto/hmac" "crypto/sha256" @@ -24,6 +23,7 @@ import ( "time" "github.com/algolia/algoliasearch-client-go/v4/algolia/utils" + "github.com/algolia/algoliasearch-client-go/v4/algolia/transport" ) type config struct { @@ -208,7 +208,7 @@ func (r requestOption) waitForApiKey() {} func (i iterableOption) waitForApiKey() {} -// WithApiKey necessary to know if an `update` operation has been processed, compare fields of the response with it. (optional - mandatory if operation is UPDATE) +// WithApiKey necessary to know if an `update` operation has been processed, compare fields of the response with it. (optional - mandatory if operation is UPDATE). func WithApiKey(apiKey *ApiKey) waitForApiKeyOption { return waitForApiKeyOption(func(c *config) { c.apiKey = apiKey @@ -503,6 +503,7 @@ func (c *APIClient) {{nickname}}({{#hasParams}}r {{#structPrefix}}{{&classname}} 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) diff --git a/templates/go/client.mustache b/templates/go/client.mustache index c02ecbe2f3d..a2154e74986 100644 --- a/templates/go/client.mustache +++ b/templates/go/client.mustache @@ -11,16 +11,14 @@ import ( "io" "net/http" "net/url" - "reflect" "regexp" "runtime" - "strings" "slices" + "strings" "time" "github.com/algolia/algoliasearch-client-go/v4/algolia/call" "github.com/algolia/algoliasearch-client-go/v4/algolia/compression" - "github.com/algolia/algoliasearch-client-go/v4/algolia/ingestion" "github.com/algolia/algoliasearch-client-go/v4/algolia/transport" ) @@ -150,28 +148,13 @@ func getUserAgent() string { return fmt.Sprintf("Algolia for Go ({{{packageVersion}}}); Go (%s); {{#lambda.titlecase}}{{#lambda.camelcase}}{{client}}{{/lambda.camelcase}}{{/lambda.titlecase}} ({{{packageVersion}}})", runtime.Version()) } -// AddDefaultHeader adds a new HTTP header to the default header in the request +// AddDefaultHeader adds a new HTTP header to the default header in the request. func (c *APIClient) AddDefaultHeader(key string, value string) { c.cfg.DefaultHeader[key] = value } -// callAPI do the request. -func (c *APIClient) callAPI(request *http.Request, useReadTransporter bool, requestConfiguration transport.RequestConfiguration) (*http.Response, []byte, error) { - callKind := call.Write - if useReadTransporter || request.Method == http.MethodGet { - callKind = call.Read - } - - resp, body, err := c.transport.Request(request.Context(), request, callKind, requestConfiguration) - if err != nil { - return nil, nil, fmt.Errorf("failed to do request: %w", err) - } - - return resp, body, nil -} - -// Allow modification of underlying config for alternate implementations and testing -// Caution: modifying the configuration while live can cause data races and potentially unwanted behavior +// Allow modification of underlying config for alternate implementations and testing. +// Caution: modifying the configuration while live can cause data races and potentially unwanted behavior. func (c *APIClient) GetConfiguration() *{{#lambda.titlecase}}{{#lambda.camelcase}}{{client}}{{/lambda.camelcase}}{{/lambda.titlecase}}Configuration { return c.cfg } @@ -187,7 +170,22 @@ func (c *APIClient) SetClientApiKey(apiKey string) error { return nil } -// prepareRequest build the request +// callAPI do the request. +func (c *APIClient) callAPI(request *http.Request, useReadTransporter bool, requestConfiguration transport.RequestConfiguration) (*http.Response, []byte, error) { + callKind := call.Write + if useReadTransporter || request.Method == http.MethodGet { + callKind = call.Read + } + + resp, body, err := c.transport.Request(request.Context(), request, callKind, requestConfiguration) + if err != nil { + return nil, nil, fmt.Errorf("failed to do request: %w", err) + } + + return resp, body, nil +} + +// prepareRequest build the request. func (c *APIClient) prepareRequest( ctx context.Context, path string, method string, @@ -222,7 +220,7 @@ func (c *APIClient) prepareRequest( if body != nil { bodyReader = body } - req, err = http.NewRequest(method, url.String(), bodyReader) + req, err = http.NewRequestWithContext(ctx, method, url.String(), bodyReader) if err != nil { return nil, fmt.Errorf("failed to create http request: %w", err) } @@ -272,8 +270,10 @@ func (c *APIClient) decode(v any, b []byte) error { } else { return errors.New("unknown type with GetActualInstance but no unmarshalObj.UnmarshalJSON defined") } - } else if err := json.Unmarshal(b, v); err != nil { // simple model - return fmt.Errorf("failed to unmarshal response body: %w", err) + } else { // simple model + if err := json.Unmarshal(b, v); err != nil { + return fmt.Errorf("failed to unmarshal response body: %w", err) + } } return nil @@ -306,12 +306,12 @@ func (c *APIClient) decodeError(res *http.Response, body []byte) error { return apiErr } -// Prevent trying to import "fmt" +// Prevent trying to import "fmt". 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 @@ -350,9 +350,9 @@ func setBody(body any, c compression.Compression) (*bytes.Buffer, error) { } type APIError struct { - Message string - Status int - AdditionalProperties map[string]any + Message string `json:"message"` + Status int `json:"status"` + AdditionalProperties map[string]any `json:"-"` } func (e APIError) Error() string { diff --git a/templates/go/configuration.mustache b/templates/go/configuration.mustache index 76cfaf08838..c301d631451 100644 --- a/templates/go/configuration.mustache +++ b/templates/go/configuration.mustache @@ -3,7 +3,6 @@ package {{packageName}} import ( "github.com/algolia/algoliasearch-client-go/v4/algolia/transport" - "github.com/algolia/algoliasearch-client-go/v4/algolia/ingestion" ) {{#hasRegionalHost}} @@ -18,7 +17,7 @@ const ( ) {{/hasRegionalHost}} -// {{#lambda.titlecase}}{{#lambda.camelcase}}{{client}}{{/lambda.camelcase}}{{/lambda.titlecase}}Configuration stores the configuration of the API client +// {{#lambda.titlecase}}{{#lambda.camelcase}}{{client}}{{/lambda.camelcase}}{{/lambda.titlecase}}Configuration stores the configuration of the API client. type {{#lambda.titlecase}}{{#lambda.camelcase}}{{client}}{{/lambda.camelcase}}{{/lambda.titlecase}}Configuration struct { transport.Configuration diff --git a/templates/go/guides/search/deleteMultipleIndices.mustache b/templates/go/guides/search/deleteMultipleIndices.mustache index 2e772b22cae..e003f223b01 100644 --- a/templates/go/guides/search/deleteMultipleIndices.mustache +++ b/templates/go/guides/search/deleteMultipleIndices.mustache @@ -19,8 +19,8 @@ func deleteMultipleIndices() { } // Primary indices don't have a `primary` key - primaryIndices := make([]search.FetchedIndex, len(indices.Items)) - replicaIndices := make([]search.FetchedIndex, len(indices.Items)) + primaryIndices := make([]search.FetchedIndex, 0, len(indices.Items)) + replicaIndices := make([]search.FetchedIndex, 0, len(indices.Items)) for _, index := range indices.Items { if index.Primary == nil { @@ -32,7 +32,7 @@ func deleteMultipleIndices() { // Delete primary indices first if len(primaryIndices) > 0 { - requests := make([]search.MultipleBatchRequest, len(primaryIndices)) + requests := make([]search.MultipleBatchRequest, 0, len(primaryIndices)) for _, index := range primaryIndices { requests = append(requests, search.MultipleBatchRequest{ @@ -51,7 +51,7 @@ func deleteMultipleIndices() { // Now, delete replica indices if len(replicaIndices) > 0 { - requests := make([]search.MultipleBatchRequest, len(primaryIndices)) + requests := make([]search.MultipleBatchRequest, 0, len(primaryIndices)) for _, index := range primaryIndices { requests = append(requests, search.MultipleBatchRequest{ diff --git a/templates/go/guides/search/mcmSearchWithout.mustache b/templates/go/guides/search/mcmSearchWithout.mustache index be1b99605e9..cae06a50ea2 100644 --- a/templates/go/guides/search/mcmSearchWithout.mustache +++ b/templates/go/guides/search/mcmSearchWithout.mustache @@ -13,7 +13,7 @@ func mcmSearchWithout() { return "", nil // Implement your logic here } - getIndexingApiKeyFor := func(_ string) (string, error) { + getIndexingAPIKeyFor := func(_ string) (string, error) { return "", nil // Implement your logic here } @@ -25,7 +25,7 @@ func mcmSearchWithout() { return } - apiKey, err := getIndexingApiKeyFor("user42") + apiKey, err := getIndexingAPIKeyFor("user42") if err != nil { fmt.Println(err) return diff --git a/templates/go/guides/search/saveImageClassifications.mustache b/templates/go/guides/search/saveImageClassifications.mustache index 32d1df0b72a..0c2aed4908b 100644 --- a/templates/go/guides/search/saveImageClassifications.mustache +++ b/templates/go/guides/search/saveImageClassifications.mustache @@ -14,7 +14,7 @@ func saveImageClassifications() { Objects []map[string]interface{} `json:"objects"` } - getImageLabels := func(imageURL, objectID string, scoreLimit float64) Image { + getImageLabels := func(imageURL, objectID string, _scoreLimit float64) Image { // Implement your image classification logic here return Image{ ImageURL: imageURL, diff --git a/templates/go/guides/search/saveObjectsModified.mustache b/templates/go/guides/search/saveObjectsModified.mustache index 803964a5ad8..3083edb28ee 100644 --- a/templates/go/guides/search/saveObjectsModified.mustache +++ b/templates/go/guides/search/saveObjectsModified.mustache @@ -24,11 +24,11 @@ func saveObjectsModified() { panic(err) } - records := make([]map[string]any, len(products)) + records := make([]map[string]any, 0, len(products)) for _, product := range products { reference := product["product_reference"].(string) - suffixes := make([]string, len(reference)-1) + suffixes := make([]string, 0, len(reference)-1) for i := len(reference); i > 1; i-- { suffixes = append(suffixes, reference[i:]) diff --git a/templates/go/guides/search/searchWithGAToken.mustache b/templates/go/guides/search/searchWithGAToken.mustache index 8d503f22b87..5328f7220a2 100644 --- a/templates/go/guides/search/searchWithGAToken.mustache +++ b/templates/go/guides/search/searchWithGAToken.mustache @@ -8,14 +8,14 @@ import ( {{> snippets/import}} -func getGoogleAnalyticsUserIdFromBrowserCookie(_ string) (string, error) { +func getGoogleAnalyticsUserIDFromBrowserCookie(_ string) (string, error) { return "", nil // Implement your logic here } func searchWithGAToken() { {{> snippets/init}} - userToken, err := getGoogleAnalyticsUserIdFromBrowserCookie("_ga") + userToken, err := getGoogleAnalyticsUserIDFromBrowserCookie("_ga") if err != nil { panic(err) } diff --git a/templates/go/guides/search/searchWithRuleContextBuyer.mustache b/templates/go/guides/search/searchWithRuleContextBuyer.mustache index c2f4b4ac95d..2306e8a414c 100644 --- a/templates/go/guides/search/searchWithRuleContextBuyer.mustache +++ b/templates/go/guides/search/searchWithRuleContextBuyer.mustache @@ -8,7 +8,7 @@ import ( {{> snippets/import}} -func getBuyerAccountId() (string, error) { +func getBuyerAccountID() (string, error) { return "", nil // Implement your logic here } @@ -16,7 +16,7 @@ func searchWithRuleContextBuyer() { {{> snippets/init}} // get the buyer account information - buyer, err := getBuyerAccountId() + buyer, err := getBuyerAccountID() if err != nil { panic(err) } diff --git a/templates/go/guides/search/setSettingsThenSaveObjects.mustache b/templates/go/guides/search/setSettingsThenSaveObjects.mustache index c0e7c4decca..206d06dece4 100644 --- a/templates/go/guides/search/setSettingsThenSaveObjects.mustache +++ b/templates/go/guides/search/setSettingsThenSaveObjects.mustache @@ -12,7 +12,7 @@ func getAppIDFor(_ string) (string, error) { return "", nil // Implement your logic here } -func getIndexingApiKeyFor(_ string) (string, error) { +func getIndexingAPIKeyFor(_ string) (string, error) { return "", nil // Implement your logic here } @@ -28,7 +28,7 @@ func setSettingsThenSaveObjects() { return } - apiKey, err := getIndexingApiKeyFor(playlist["user"].(string)) + apiKey, err := getIndexingAPIKeyFor(playlist["user"].(string)) if err != nil { fmt.Println(err) return diff --git a/templates/go/model.mustache b/templates/go/model.mustache index 0b3d8e9c147..35ee884d6ec 100644 --- a/templates/go/model.mustache +++ b/templates/go/model.mustache @@ -5,10 +5,8 @@ package {{packageName}} import ( "encoding/json" "fmt" + "github.com/algolia/algoliasearch-client-go/v4/algolia/utils" -{{#imports}} - "{{import}}" -{{/imports}} ) {{#model}} @@ -16,7 +14,7 @@ import ( {{> model_enum}} {{/isEnum}} {{^isEnum}} -{{#oneOf}}{{#-first}}{{> model_oneof}}{{/-first}}{{/oneOf}}{{^oneOf}}{{#anyOf}}{{#-first}}{{> model_anyof}}{{/-first}}{{/anyOf}}{{^anyOf}}{{> model_simple}}{{/anyOf}}{{/oneOf}} +{{#oneOf}}{{#-first}}{{> model_oneof}}{{/-first}}{{/oneOf}}{{^oneOf}}{{> model_simple}}{{/oneOf}} {{/isEnum}} {{/model}} {{/models}} diff --git a/templates/go/model_anyof.mustache b/templates/go/model_anyof.mustache deleted file mode 100644 index 35aaa0c03ce..00000000000 --- a/templates/go/model_anyof.mustache +++ /dev/null @@ -1,50 +0,0 @@ -// {{classname}} {{{description}}}{{^description}}struct for {{{classname}}}{{/description}} -type {{classname}} struct { - {{#anyOf}} - {{{.}}} *{{{.}}} - {{/anyOf}} -} - -// Unmarshal JSON data into any of the pointers in the struct -func (dst *{{classname}}) UnmarshalJSON(data []byte) error { - var err error - {{#isNullable}} - // this object is nullable so check if the payload is null or empty string - if string(data) == "" || string(data) == "{}" { - return nil - } - - {{/isNullable}} - {{#anyOf}} - // try to unmarshal JSON data into {{{.}}} - err = json.Unmarshal(data, &dst.{{{.}}}); - if err == nil { - json{{{.}}}, _ := json.Marshal(dst.{{{.}}}) - if string(json{{{.}}}) == "{}" { // empty struct - dst.{{{.}}} = nil - } else { - return nil // data stored in dst.{{{.}}}, return on the first match - } - } else { - dst.{{{.}}} = nil - } - - {{/anyOf}} - return fmt.Errorf("Data failed to match schemas in anyOf({{classname}})") -} - -// Marshal data from the first non-nil pointers in the struct to JSON -func (src *{{classname}}) MarshalJSON() ([]byte, error) { -{{#anyOf}} - if src.{{{.}}} != nil { - serialized, err := json.Marshal(&src.{{{.}}}) - if err != nil { - return nil, fmt.Errorf("failed to unmarshal any of {{.}} of {{classname}}: %w", err) - } - - return serialized, nil - } - -{{/anyOf}} - return nil, nil // no data in anyOf schemas -} diff --git a/templates/go/model_enum.mustache b/templates/go/model_enum.mustache index 967ce852281..7f85e8da1e0 100644 --- a/templates/go/model_enum.mustache +++ b/templates/go/model_enum.mustache @@ -1,4 +1,4 @@ -// {{{classname}}} {{{description}}}{{^description}}the model '{{{classname}}}'{{/description}} +// {{{classname}}} {{{description}}}{{^description}}the model '{{{classname}}}'.{{/description}} type {{{classname}}} {{{format}}}{{^format}}{{dataType}}{{/format}} // List of {{{name}}} @@ -12,7 +12,7 @@ const ( {{/allowableValues}} ) -// All allowed values of {{{classname}}} enum +// All allowed values of {{{classname}}} enum. var Allowed{{{classname}}}EnumValues = []{{{classname}}}{ {{#allowableValues}} {{#enumVars}} @@ -21,6 +21,17 @@ var Allowed{{{classname}}}EnumValues = []{{{classname}}}{ {{/allowableValues}} } +// New{{{classname}}}FromValue returns a pointer to a valid {{{classname}}}. +// for the value passed as argument, or an error if the value passed is not allowed by the enum. +func New{{{classname}}}FromValue(v {{{format}}}{{^format}}{{dataType}}{{/format}}) (*{{{classname}}}, error) { + ev := {{{classname}}}(v) + if ev.IsValid() { + return &ev, nil + } else { + return nil, fmt.Errorf("invalid value '%v' for {{{classname}}}: valid values are %v", v, Allowed{{{classname}}}EnumValues) + } +} + func (v *{{{classname}}}) UnmarshalJSON(src []byte) error { var value {{{format}}}{{^format}}{{dataType}}{{/format}} err := json.Unmarshal(src, &value) @@ -38,17 +49,6 @@ func (v *{{{classname}}}) UnmarshalJSON(src []byte) error { return fmt.Errorf("%+v is not a valid {{classname}}", value) } -// New{{{classname}}}FromValue returns a pointer to a valid {{{classname}}} -// for the value passed as argument, or an error if the value passed is not allowed by the enum -func New{{{classname}}}FromValue(v {{{format}}}{{^format}}{{dataType}}{{/format}}) (*{{{classname}}}, error) { - ev := {{{classname}}}(v) - if ev.IsValid() { - return &ev, nil - } else { - return nil, fmt.Errorf("invalid value '%v' for {{{classname}}}: valid values are %v", v, Allowed{{{classname}}}EnumValues) - } -} - // IsValid return true if the value is valid for the enum, false otherwise. func (v {{{classname}}}) IsValid() bool { for _, existing := range Allowed{{{classname}}}EnumValues { @@ -59,7 +59,7 @@ func (v {{{classname}}}) IsValid() bool { return false } -// Ptr returns reference to {{{name}}} value +// Ptr returns reference to {{{name}}} value. func (v {{{classname}}}) Ptr() *{{{classname}}} { return &v } diff --git a/templates/go/model_oneof.mustache b/templates/go/model_oneof.mustache index 483e1499613..1597649b2cb 100644 --- a/templates/go/model_oneof.mustache +++ b/templates/go/model_oneof.mustache @@ -1,4 +1,4 @@ -// {{classname}} - {{{description}}}{{^description}}struct for {{{classname}}}{{/description}} +// {{classname}} - {{{description}}}{{^description}}struct for {{{classname}}}.{{/description}} type {{classname}} struct { {{#oneOf}} {{#lambda.type-to-name}}{{{.}}}{{/lambda.type-to-name}} *{{{.}}} @@ -6,7 +6,7 @@ type {{classname}} struct { } {{#composedSchemas.oneOf}} -// {{{datatypeWithEnum}}}As{{classname}} is a convenience function that returns {{{datatypeWithEnum}}} wrapped in {{classname}} +// {{{datatypeWithEnum}}}As{{classname}} is a convenience function that returns {{{datatypeWithEnum}}} wrapped in {{classname}}. func {{#lambda.type-to-name}}{{{datatypeWithEnum}}}{{/lambda.type-to-name}}As{{classname}}(v {{#isModel}}*{{/isModel}}{{{datatypeWithEnum}}}) *{{classname}} { return &{{classname}}{ {{#lambda.type-to-name}}{{{datatypeWithEnum}}}{{/lambda.type-to-name}}: {{^isModel}}&{{/isModel}}v, @@ -15,7 +15,7 @@ func {{#lambda.type-to-name}}{{{datatypeWithEnum}}}{{/lambda.type-to-name}}As{{c {{/composedSchemas.oneOf}} -// Unmarshal JSON data into one of the pointers in the struct +// Unmarshal JSON data into one of the pointers in the struct. func (dst *{{classname}}) UnmarshalJSON(data []byte) error { var err error {{#isNullable}} @@ -46,10 +46,10 @@ func (dst *{{classname}}) UnmarshalJSON(data []byte) error { {{/vendorExtensions.x-discriminator-fields.size}} {{/composedSchemas.oneOf}} - return fmt.Errorf("Data failed to match schemas in oneOf({{classname}})") + return fmt.Errorf("data failed to match schemas in oneOf({{classname}})") } -// Marshal data from the first non-nil pointers in the struct to JSON +// Marshal data from the first non-nil pointers in the struct to JSON. func (src {{classname}}) MarshalJSON() ([]byte, error) { {{#oneOf}} if src.{{#lambda.type-to-name}}{{{.}}}{{/lambda.type-to-name}} != nil { @@ -65,7 +65,7 @@ func (src {{classname}}) MarshalJSON() ([]byte, error) { return nil, nil // no data in oneOf schemas } -// Get the actual instance +// Get the actual instance. func (obj {{classname}}) GetActualInstance() (any) { {{#oneOf}} if obj.{{#lambda.type-to-name}}{{{.}}}{{/lambda.type-to-name}} != nil { diff --git a/templates/go/model_simple.mustache b/templates/go/model_simple.mustache index 8c28c2c0aa5..f6bf23b2ae1 100644 --- a/templates/go/model_simple.mustache +++ b/templates/go/model_simple.mustache @@ -20,7 +20,7 @@ type {{classname}} struct { {{name}} {{^required}}{{^isNullable}}{{^isArray}}{{^isFreeFormObject}}*{{/isFreeFormObject}}{{/isArray}}{{/isNullable}}{{/required}}{{{dataType}}} `json:"{{baseName}}{{^required}},omitempty{{/required}}"` {{/vars}} {{#isAdditionalPropertiesTrue}} - AdditionalProperties map[string]any + AdditionalProperties map[string]any `json:"-"` {{/isAdditionalPropertiesTrue}} } diff --git a/templates/go/search_helpers.mustache b/templates/go/search_helpers.mustache index 200a3ff5f96..a297bec029f 100644 --- a/templates/go/search_helpers.mustache +++ b/templates/go/search_helpers.mustache @@ -468,7 +468,7 @@ func (c *APIClient) GetSecuredApiKeyRemainingValidity(securedApiKey string) (tim decoded, err := base64.StdEncoding.DecodeString(securedApiKey) if err != nil { - return 0, fmt.Errorf("unable to decode given secured API key: %s", err) + return 0, fmt.Errorf("unable to decode given secured API key: %w", err) } submatch := regexp.MustCompile(`validUntil=(\d{1,10})`).FindSubmatch(decoded) diff --git a/templates/go/snippets/.golangci.mustache b/templates/go/snippets/.golangci.mustache index 326e7421e1f..e3fe8593ce3 100644 --- a/templates/go/snippets/.golangci.mustache +++ b/templates/go/snippets/.golangci.mustache @@ -1,12 +1,54 @@ +version: "2" +run: + concurrency: 2 linters: + default: all disable: - - ineffassign - - staticcheck + - cyclop + - depguard + - dupl + - dupword + - exhaustruct + - forbidigo + - forcetypeassert + - funlen + - goconst + - godoclint + - godot + - gomoddirectives + - ireturn + - lll + - maintidx + - mnd + - noctx + - paralleltest + - tagliatelle + - testpackage + - tparallel + - unparam - unused - -issues: - exclude-generated: disable - -run: - concurrency: 2 - timeout: 10m \ No newline at end of file + - varnamelen + - wastedassign + - wsl + settings: + staticcheck: + checks: ["all", "-SA1019", "-SA4006"] + exclusions: + generated: disable + presets: + - comments + - std-error-handling + rules: + - linters: + - revive + text: "unused-parameter:" +formatters: + enable: + - gofmt + - gofumpt + - golines + settings: + golines: + max-len: 150 + exclusions: + generated: disable \ No newline at end of file diff --git a/templates/go/snippets/import.mustache b/templates/go/snippets/import.mustache index 9e6ac952e51..67d0b34473a 100644 --- a/templates/go/snippets/import.mustache +++ b/templates/go/snippets/import.mustache @@ -1 +1,4 @@ -import "github.com/algolia/algoliasearch-client-go/v4/algolia/{{clientImport}}" +import ( + "github.com/algolia/algoliasearch-client-go/v4/algolia/{{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 8f2b5c4204d..3788cb4dfef 100644 --- a/templates/go/snippets/method.mustache +++ b/templates/go/snippets/method.mustache @@ -5,7 +5,6 @@ package snippets {{> snippets/import}} // IMPORT< - {{#blocksRequests}} {{#snippets}} func SnippetFor{{#lambda.titlecase}}{{method}}{{/lambda.titlecase}}Of{{#lambda.pascalcase}}{{clientPrefix}}{{/lambda.pascalcase}}{{testIndex}}() { diff --git a/templates/go/tests/client/benchmark.mustache b/templates/go/tests/client/benchmark.mustache index 9f4b51370c5..7c1462fe531 100644 --- a/templates/go/tests/client/benchmark.mustache +++ b/templates/go/tests/client/benchmark.mustache @@ -3,7 +3,7 @@ package benchmark import ( "testing" - "regexp" + "github.com/stretchr/testify/require" @@ -12,6 +12,7 @@ import ( "github.com/algolia/algoliasearch-client-go/v4/algolia/{{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" ) {{#blocksBenchmark}} diff --git a/templates/go/tests/client/client.mustache b/templates/go/tests/client/client.mustache index cd5ced54cce..a597f36543e 100644 --- a/templates/go/tests/client/client.mustache +++ b/templates/go/tests/client/client.mustache @@ -5,7 +5,7 @@ import ( "encoding/json" "net/url" "testing" - "regexp" + "time" "github.com/kinbiko/jsonassert" "github.com/stretchr/testify/require" @@ -16,9 +16,12 @@ import ( "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" + "github.com/algolia/algoliasearch-client-go/v4/algolia/call" ) func create{{#lambda.titlecase}}{{clientPrefix}}{{/lambda.titlecase}}Client(t *testing.T) (*{{clientPrefix}}.APIClient, *tests.EchoRequester) { + t.Helper() + echo := &tests.EchoRequester{} cfg := {{clientPrefix}}.{{clientName}}Configuration{ Configuration: transport.Configuration{ diff --git a/templates/go/tests/client/tests.mustache b/templates/go/tests/client/tests.mustache index f63b9bc8509..242d198cbf3 100644 --- a/templates/go/tests/client/tests.mustache +++ b/templates/go/tests/client/tests.mustache @@ -29,7 +29,7 @@ func Test{{#lambda.titlecase}}{{clientPrefix}}{{testType}}{{/lambda.titlecase}}{ {{#dynamicTemplate}}{{/dynamicTemplate}} require.NoError(t, err) {{#testUserAgent}} - require.Regexp(t, regexp.MustCompile(`{{{match.value}}}`), echo.Header.Get("User-Agent")) + require.Regexp(t, `{{{match.value}}}`, echo.Header.Get("User-Agent")) {{/testUserAgent}} {{#testTimeouts}} require.Equal(t, int64({{{matchConnectTimeout}}}), echo.ConnectTimeout.Milliseconds()) diff --git a/templates/go/tests/e2e/e2e.mustache b/templates/go/tests/e2e/e2e.mustache index 2382998148c..23552e8e754 100644 --- a/templates/go/tests/e2e/e2e.mustache +++ b/templates/go/tests/e2e/e2e.mustache @@ -2,13 +2,16 @@ package e2e import ( + "encoding/json" "os" "testing" "github.com/stretchr/testify/require" - + "github.com/kinbiko/jsonassert" "github.com/joho/godotenv" + "gotests/tests" + "github.com/algolia/algoliasearch-client-go/v4/algolia/{{clientImport}}" ) @@ -30,8 +33,11 @@ func createE2E{{#lambda.titlecase}}{{clientPrefix}}{{/lambda.titlecase}}Client(t {{#blocksE2E}} func Test{{#lambda.titlecase}}{{clientPrefix}}{{/lambda.titlecase}}E2E_{{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}}(t *testing.T) { + t.Parallel() {{#tests}} t.Run("{{{testName}}}", func(t *testing.T) { + t.Parallel() + client := createE2E{{#lambda.titlecase}}{{clientPrefix}}{{/lambda.titlecase}}Client(t) res, err := {{> tests/method}} require.NoError(t, err) diff --git a/templates/go/tests/requests/helpers.mustache b/templates/go/tests/requests/helpers.mustache index e7e957c5179..f11bb7ecad1 100644 --- a/templates/go/tests/requests/helpers.mustache +++ b/templates/go/tests/requests/helpers.mustache @@ -1,4 +1,6 @@ func TestSearch_GenerateSecuredApiKey(t *testing.T) { + t.Parallel() + client, echo := createSearchClient(t) _ = echo @@ -18,6 +20,8 @@ func TestSearch_GenerateSecuredApiKey(t *testing.T) { } func TestSearch_GetSecuredApiKeyRemainingVaildity(t *testing.T) { + t.Parallel() + client, echo := createSearchClient(t) _ = echo diff --git a/templates/go/tests/requests/requests.mustache b/templates/go/tests/requests/requests.mustache index 7d71dd4290f..d1bb0c837b3 100644 --- a/templates/go/tests/requests/requests.mustache +++ b/templates/go/tests/requests/requests.mustache @@ -13,6 +13,7 @@ import ( "github.com/algolia/algoliasearch-client-go/v4/algolia/{{clientImport}}" "github.com/algolia/algoliasearch-client-go/v4/algolia/transport" + "github.com/algolia/algoliasearch-client-go/v4/algolia/utils" ) func create{{#lambda.titlecase}}{{clientPrefix}}{{/lambda.titlecase}}Client(t *testing.T) (*{{clientPrefix}}.APIClient, *tests.EchoRequester) { @@ -35,6 +36,8 @@ func create{{#lambda.titlecase}}{{clientPrefix}}{{/lambda.titlecase}}Client(t *t {{#blocksRequests}} func Test{{#lambda.titlecase}}{{clientPrefix}}{{/lambda.titlecase}}_{{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}}(t *testing.T) { + t.Parallel() + client, echo := create{{#lambda.titlecase}}{{clientPrefix}}{{/lambda.titlecase}}Client(t) _ = echo diff --git a/templates/javascript/clients/algoliasearch/builds/definition.mustache b/templates/javascript/clients/algoliasearch/builds/definition.mustache index 667622d70f3..9223733190c 100644 --- a/templates/javascript/clients/algoliasearch/builds/definition.mustache +++ b/templates/javascript/clients/algoliasearch/builds/definition.mustache @@ -53,7 +53,7 @@ export type Algoliasearch = SearchClient & { * @param partialUpdateObjects - The `partialUpdateObjects` object. * @param partialUpdateObjects.indexName - The `indexName` to update `objects` in. * @param partialUpdateObjects.objects - The array of `objects` to update in the given Algolia `indexName`. - * @param partialUpdateObjects.createIfNotExists - To be provided if non-existing objects are passed, otherwise, the call will fail.. + * @param partialUpdateObjects.createIfNotExists - To be provided if non-existing objects are passed, otherwise, the call will fail. * @param partialUpdateObjects.batchSize - The size of the chunk of `objects`. The number of `batch` calls will be equal to `length(objects) / batchSize`. Defaults to 1000. * @param partialUpdateObjects.waitForTasks - Whether or not we should wait until every `batch` tasks has been processed, this operation may slow the total execution time of this method but is more reliable. * @param requestOptions - The requestOptions to send along with the query, they will be forwarded to the `push` method and merged with the transporter requestOptions. diff --git a/templates/javascript/clients/client/api/helpers.mustache b/templates/javascript/clients/client/api/helpers.mustache index 13f659412a2..784ac0da0a1 100644 --- a/templates/javascript/clients/client/api/helpers.mustache +++ b/templates/javascript/clients/client/api/helpers.mustache @@ -366,7 +366,7 @@ async deleteObjects( * @param partialUpdateObjects - The `partialUpdateObjects` object. * @param partialUpdateObjects.indexName - The `indexName` to update `objects` in. * @param partialUpdateObjects.objects - The array of `objects` to update in the given Algolia `indexName`. - * @param partialUpdateObjects.createIfNotExists - To be provided if non-existing objects are passed, otherwise, the call will fail.. + * @param partialUpdateObjects.createIfNotExists - To be provided if non-existing objects are passed, otherwise, the call will fail. * @param partialUpdateObjects.batchSize - The size of the chunk of `objects`. The number of `batch` calls will be equal to `length(objects) / batchSize`. Defaults to 1000. * @param partialUpdateObjects.waitForTasks - Whether or not we should wait until every `batch` tasks has been processed, this operation may slow the total execution time of this method but is more reliable. * @param requestOptions - The requestOptions to send along with the query, they will be forwarded to the `getTask` method and merged with the transporter requestOptions. diff --git a/templates/php/api.mustache b/templates/php/api.mustache index 9fc271f71cb..7ba42deaf43 100644 --- a/templates/php/api.mustache +++ b/templates/php/api.mustache @@ -729,7 +729,7 @@ use Algolia\AlgoliaSearch\Exceptions\NotFoundException; * * @param string $indexName The `indexName` to replace `objects` in. * @param array $objects The array of `objects` to store in the given Algolia `indexName`. - * @param bool $createIfNotExists To be provided if non-existing objects are passed, otherwise, the call will fail.. + * @param bool $createIfNotExists To be provided if non-existing objects are passed, otherwise, the call will fail. * @param bool $waitForTasks Whether or not we should wait until every `batch` tasks has been processed, this operation may slow the total execution time of this method but is more reliable * @param int $batchSize The size of the chunk of `objects`. The number of `batch` calls will be equal to `length(objects) / batchSize`. Defaults to 1000. * @param array $requestOptions Request options @@ -746,7 +746,7 @@ use Algolia\AlgoliaSearch\Exceptions\NotFoundException; * * @param string $indexName the `indexName` to replace `objects` in * @param array $objects the array of `objects` to store in the given Algolia `indexName` - * @param bool $createIfNotExists To be provided if non-existing objects are passed, otherwise, the call will fail.. + * @param bool $createIfNotExists To be provided if non-existing objects are passed, otherwise, the call will fail. * @param bool $waitForTasks Whether or not we should wait until every `batch` tasks has been processed, this operation may slow the total execution time of this method but is more reliable * @param int $batchSize The size of the chunk of `objects`. The number of `push` calls will be equal to `length(objects) / batchSize`. Defaults to 1000. * @param array $requestOptions Request options diff --git a/tests/CTS/requests/common/customGet.json b/tests/CTS/requests/common/customGet.json index 6cb3f59206b..c6730b6cf60 100644 --- a/tests/CTS/requests/common/customGet.json +++ b/tests/CTS/requests/common/customGet.json @@ -30,7 +30,7 @@ "parameters": { "path": "test/all", "parameters": { - "query": "to be overriden" + "query": "to be overridden" } }, "requestOptions": { diff --git a/tests/output/go/.golangci.yml b/tests/output/go/.golangci.yml index b965a94c151..a81e164d960 100644 --- a/tests/output/go/.golangci.yml +++ b/tests/output/go/.golangci.yml @@ -1,14 +1,42 @@ -linters: - disable: - - ineffassign - - staticcheck - -issues: - exclude-generated: disable - - exclude: - - 'printf: non-constant format string in call to' - +version: "2" run: concurrency: 2 - timeout: 10m +linters: + default: all + disable: + - cyclop + - depguard + - dupl + - exhaustruct + - forcetypeassert + - funlen + - goconst + - godoclint + - gomoddirectives + - ireturn + - lll + - maintidx + - mnd + - paralleltest + - testpackage + - tparallel + - wastedassign + - wsl + settings: + staticcheck: + checks: ["all", "-SA1019", "-SA4006"] + exclusions: + generated: disable + presets: + - comments + - std-error-handling +formatters: + enable: + - gofmt + - gofumpt + - golines + settings: + golines: + max-len: 150 + exclusions: + generated: disable diff --git a/tests/output/go/tests/echo.go b/tests/output/go/tests/echo.go index 4f1cde69eb0..d37d00579d4 100644 --- a/tests/output/go/tests/echo.go +++ b/tests/output/go/tests/echo.go @@ -31,6 +31,7 @@ func (e *EchoRequester) Request(req *http.Request, timeout time.Duration, connec e.Header = req.Header e.Timeout = timeout e.ConnectTimeout = connectTimeout + if req.Body != nil { body, _ := io.ReadAll(req.Body) strBody := string(body) @@ -39,8 +40,10 @@ func (e *EchoRequester) Request(req *http.Request, timeout time.Duration, connec e.Body = nil } - var queryValues = strings.Split(req.URL.RawQuery, "&") + queryValues := strings.Split(req.URL.RawQuery, "&") + e.Query = url.Values{} + for _, queryValue := range queryValues { split := strings.Split(queryValue, "=") if len(split) == 2 { @@ -49,36 +52,43 @@ func (e *EchoRequester) Request(req *http.Request, timeout time.Duration, connec } return &http.Response{ - StatusCode: 200, + StatusCode: http.StatusOK, Body: io.NopCloser(bytes.NewBufferString("")), }, nil } func ZeroValue[T any]() T { var v T + return v } func Union(t *testing.T, expected any, received any) any { t.Helper() + if expected != nil { require.NotNil(t, received, expected) } - switch expected.(type) { + switch exp := expected.(type) { case map[string]any: res := map[string]any{} - for key, val := range expected.(map[string]any) { + + for key, val := range exp { require.Contains(t, received.(map[string]any), key) res[key] = Union(t, val, received.(map[string]any)[key]) } + return res case []any: res := []any{} - require.GreaterOrEqual(t, len(received.([]any)), len(expected.([]any))) - for i, val := range expected.([]any) { + + require.GreaterOrEqual(t, len(received.([]any)), len(exp)) + + for i, val := range exp { res = append(res, Union(t, val, received.([]any)[i])) } + return res default: return received