diff --git a/.devcontainer/README.md b/.devcontainer/README.md index 4e23f7c..99925f0 100644 --- a/.devcontainer/README.md +++ b/.devcontainer/README.md @@ -1,4 +1,9 @@ +
+ +
+
+ > **Remember to shutdown a GitHub Codespace when it is not in use!** # Dev Containers Quick Start diff --git a/.speakeasy/gen.lock b/.speakeasy/gen.lock index 73e4196..233a297 100644 --- a/.speakeasy/gen.lock +++ b/.speakeasy/gen.lock @@ -3,28 +3,30 @@ id: ddf9e346-bb43-4ccc-aaae-95e233eb6f3f management: docChecksum: 5be1033d3fcd17c8b64f613200c1ef01 docVersion: 1.0.0 - speakeasyVersion: 1.621.1 - generationVersion: 2.708.2 - releaseVersion: 0.0.2 - configChecksum: 0f69a66bb8df56df0a1727293f910ef9 + speakeasyVersion: 1.666.0 + generationVersion: 2.768.0 + releaseVersion: 0.1.0 + configChecksum: 271dbc53435475190d667d13b3793ca3 + repoURL: https://github.com/QuePlatform/GoSDK.git + installationURL: https://github.com/QuePlatform/GoSDK features: go: additionalDependencies: 0.1.0 constsAndDefaults: 0.1.12 - core: 3.11.0 + core: 3.13.5 defaultEnabledRetries: 0.2.0 devContainers: 2.90.0 envVarSecurityUsage: 0.3.2 globalSecurity: 2.82.12 globalSecurityCallbacks: 0.1.0 globalSecurityFlattening: 0.1.0 - globalServerURLs: 2.82.3 + globalServerURLs: 2.83.0 intellisenseMarkdownSupport: 0.1.0 - nullables: 0.2.0 + nullables: 0.2.1 responseFormat: 0.1.2 retries: 2.84.2 - sdkHooks: 0.2.0 - unions: 2.85.14 + sdkHooks: 0.3.0 + unions: 2.87.2 generatedFiles: - .devcontainer/README.md - .devcontainer/devcontainer.json @@ -122,7 +124,6 @@ generatedFiles: - types/bigint.go - types/date.go - types/datetime.go - - types/decimal.go - types/pointers.go - utility.go examples: diff --git a/.speakeasy/gen.yaml b/.speakeasy/gen.yaml index 12dbaf8..bca8c71 100644 --- a/.speakeasy/gen.yaml +++ b/.speakeasy/gen.yaml @@ -22,12 +22,15 @@ generation: hoistGlobalSecurity: true inferSSEOverload: true sdkHooksConfigAccess: true + schemas: + allOfMergeStrategy: shallowMerge + requestBodyFieldName: "" tests: generateTests: false generateNewTests: true skipResponseBodyAssertions: false go: - version: 0.0.2 + version: 0.1.0 additionalDependencies: {} baseErrorName: QueError clientServerStatusCodesAsErrors: true @@ -42,12 +45,16 @@ go: operations: models/operations shared: models/components webhooks: models/webhooks + includeEmptyObjects: false + inferUnionDiscriminators: false inputModelSuffix: input maxMethodParams: 4 methodArguments: require-security-and-request modulePath: github.com/QuePlatform/GoSDK + multipartArrayFormat: legacy nullableOptionalWrapper: true outputModelSuffix: output respectRequiredFields: false responseFormat: envelope-http sdkPackageName: Que + unionStrategy: left-to-right diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock index 577fba6..2b9e9c1 100644 --- a/.speakeasy/workflow.lock +++ b/.speakeasy/workflow.lock @@ -1,20 +1,21 @@ -speakeasyVersion: 1.621.1 +speakeasyVersion: 1.666.0 sources: Que API: sourceNamespace: que-api - sourceRevisionDigest: sha256:80df4c9999cdc7c286e30ee79425ec574be16294d3b8b890ffba773dce254dc8 - sourceBlobDigest: sha256:022738a40948c2fe68b0f5fa760cf5197b333d62458755a7aefcdbb8b02030e3 + sourceRevisionDigest: sha256:1d1dac444fb41dee5adefa3de97825285c766cfe0fc1c668895da3d1a71aeac2 + sourceBlobDigest: sha256:140578c495d7673e904df7fc110e6485e2382635f23ed86315ddfffdcac9dc7c tags: - latest + - speakeasy-sdk-regen-1759801402 - 1.0.0 targets: que: source: Que API sourceNamespace: que-api - sourceRevisionDigest: sha256:80df4c9999cdc7c286e30ee79425ec574be16294d3b8b890ffba773dce254dc8 - sourceBlobDigest: sha256:022738a40948c2fe68b0f5fa760cf5197b333d62458755a7aefcdbb8b02030e3 + sourceRevisionDigest: sha256:1d1dac444fb41dee5adefa3de97825285c766cfe0fc1c668895da3d1a71aeac2 + sourceBlobDigest: sha256:140578c495d7673e904df7fc110e6485e2382635f23ed86315ddfffdcac9dc7c codeSamplesNamespace: que-api-go-code-samples - codeSamplesRevisionDigest: sha256:f9ee0897034fac1730add87060d92762041043f0d4943dab3ce5d2d2cefd1dff + codeSamplesRevisionDigest: sha256:2b57aad98d03ba4da44a8a7bd4a0f76784cce9dc51e7595793f0f418a246d318 workflow: workflowVersion: 1.0.0 speakeasyVersion: latest diff --git a/README.md b/README.md index 7d0f0b3..eb6edb8 100644 --- a/README.md +++ b/README.md @@ -395,7 +395,8 @@ func main() { ctx := context.Background() s := que.New( - que.WithEnvironment(""), + que.WithServerIndex(0), + que.WithEnvironment("dev-api"), que.WithSecurity(os.Getenv("QUE_API_KEY_AUTH")), ) diff --git a/RELEASES.md b/RELEASES.md new file mode 100644 index 0000000..061a823 --- /dev/null +++ b/RELEASES.md @@ -0,0 +1,11 @@ + + +## 2025-12-02 01:55:48 +### Changes +Based on: +- OpenAPI Doc +- Speakeasy CLI 1.666.0 (2.768.0) https://github.com/speakeasy-api/speakeasy +### Generated +- [go v0.1.0] . +### Releases +- [Go v0.1.0] https://github.com/QuePlatform/GoSDK/releases/tag/v0.1.0 - . \ No newline at end of file diff --git a/go.mod b/go.mod index 87e09b9..6614a3d 100644 --- a/go.mod +++ b/go.mod @@ -2,10 +2,7 @@ module github.com/QuePlatform/GoSDK go 1.22 -require ( - github.com/ericlagergren/decimal v0.0.0-20221120152707-495c53812d05 - github.com/stretchr/testify v1.11.1 -) +require github.com/stretchr/testify v1.11.1 require ( github.com/davecgh/go-spew v1.1.1 // indirect diff --git a/go.sum b/go.sum index 6253552..c4c1710 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,5 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/ericlagergren/decimal v0.0.0-20221120152707-495c53812d05 h1:S92OBrGuLLZsyM5ybUzgc/mPjIYk2AZqufieooe98uw= -github.com/ericlagergren/decimal v0.0.0-20221120152707-495c53812d05/go.mod h1:M9R1FoZ3y//hwwnJtO51ypFGwm8ZfpxPT/ZLtO1mcgQ= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= diff --git a/internal/utils/form.go b/internal/utils/form.go index a3731aa..79eaf36 100644 --- a/internal/utils/form.go +++ b/internal/utils/form.go @@ -10,19 +10,19 @@ import ( "strings" "time" - "github.com/ericlagergren/decimal" - "github.com/QuePlatform/GoSDK/optionalnullable" "github.com/QuePlatform/GoSDK/types" ) -func populateForm(paramName string, explode bool, objType reflect.Type, objValue reflect.Value, delimiter string, defaultValue *string, getFieldName func(reflect.StructField) string) url.Values { +func populateForm(paramName string, explode bool, objType reflect.Type, objValue reflect.Value, delimiter string, defaultValue *string, allowEmptyValue map[string]struct{}, getFieldName func(reflect.StructField) string) url.Values { formValues := url.Values{} if isNil(objType, objValue) { if defaultValue != nil { formValues.Add(paramName, *defaultValue) + } else if _, ok := allowEmptyValue[paramName]; ok { + formValues.Add(paramName, "") } return formValues @@ -42,8 +42,6 @@ func populateForm(paramName string, explode bool, objType reflect.Type, objValue formValues.Add(paramName, valToString(objValue.Interface())) case big.Int: formValues.Add(paramName, valToString(objValue.Interface())) - case decimal.Big: - formValues.Add(paramName, valToString(objValue.Interface())) default: var items []string @@ -65,7 +63,13 @@ func populateForm(paramName string, explode bool, objType reflect.Type, objValue } if explode { - formValues.Add(fieldName, valToString(valType.Interface())) + if valType.Kind() == reflect.Slice || valType.Kind() == reflect.Array { + for i := 0; i < valType.Len(); i++ { + formValues.Add(fieldName, valToString(valType.Index(i).Interface())) + } + } else { + formValues.Add(fieldName, valToString(valType.Interface())) + } } else { items = append(items, fmt.Sprintf("%s%s%s", fieldName, delimiter, valToString(valType.Interface()))) } @@ -101,12 +105,31 @@ func populateForm(paramName string, explode bool, objType reflect.Type, objValue formValues.Add(paramName, strings.Join(items, delimiter)) } case reflect.Slice, reflect.Array: - values := parseDelimitedArray(explode, objValue, delimiter) - for _, v := range values { - formValues.Add(paramName, v) + if objValue.Len() == 0 { + if _, ok := allowEmptyValue[paramName]; ok { + formValues.Add(paramName, "") + } + } else { + values := parseDelimitedArray(explode, objValue, delimiter) + for _, v := range values { + formValues.Add(paramName, v) + } } default: - formValues.Add(paramName, valToString(objValue.Interface())) + // For string types, use the value directly without conversion + if objType.Kind() == reflect.String { + stringValue := objValue.String() + formValues.Add(paramName, stringValue) + } else { + stringValue := valToString(objValue.Interface()) + if stringValue == "" { + if _, ok := allowEmptyValue[paramName]; ok { + formValues.Add(paramName, "") + } + } else if stringValue != "" { + formValues.Add(paramName, stringValue) + } + } } return formValues diff --git a/internal/utils/json.go b/internal/utils/json.go index 4621c4d..db0e817 100644 --- a/internal/utils/json.go +++ b/internal/utils/json.go @@ -15,8 +15,6 @@ import ( "unsafe" "github.com/QuePlatform/GoSDK/types" - - "github.com/ericlagergren/decimal" ) func MarshalJSON(v interface{}, tag reflect.StructTag, topLevel bool) ([]byte, error) { @@ -41,21 +39,30 @@ func MarshalJSON(v interface{}, tag reflect.StructTag, topLevel bool) ([]byte, e fieldName := field.Name omitEmpty := false + omitZero := false jsonTag := field.Tag.Get("json") if jsonTag != "" { for _, tag := range strings.Split(jsonTag, ",") { if tag == "omitempty" { omitEmpty = true + } else if tag == "omitzero" { + omitZero = true } else { fieldName = tag } } } - if isNil(field.Type, fieldVal) && field.Tag.Get("const") == "" { - if omitEmpty { + if (omitEmpty || omitZero) && field.Tag.Get("const") == "" { + // Both omitempty and omitzero skip zero values (including nil) + if isNil(field.Type, fieldVal) { + continue + } + + if omitZero && fieldVal.IsZero() { continue } + } if !field.IsExported() && field.Tag.Get("const") == "" { @@ -156,7 +163,7 @@ func UnmarshalJSON(b []byte, v interface{}, tag reflect.StructTag, topLevel bool jsonTag := field.Tag.Get("json") if jsonTag != "" { for _, tag := range strings.Split(jsonTag, ",") { - if tag != "omitempty" { + if tag != "omitempty" && tag != "omitzero" { fieldName = tag } } @@ -345,17 +352,6 @@ func marshalValue(v interface{}, tag reflect.StructTag) (json.RawMessage, error) b := val.Interface().(big.Int) return []byte(fmt.Sprintf(`"%s"`, (&b).String())), nil } - case reflect.TypeOf(decimal.Big{}): - format := tag.Get("decimal") - if format == "number" { - b := val.Interface().(decimal.Big) - f, ok := (&b).Float64() - if ok { - return []byte(b.String()), nil - } - - return []byte(fmt.Sprintf(`%f`, f)), nil - } } } @@ -386,11 +382,6 @@ func handleDefaultConstValue(tagValue string, val interface{}, tag reflect.Struc if format == "string" { return []byte(fmt.Sprintf(`"%s"`, tagValue)) } - case reflect.TypeOf(decimal.Big{}): - decimalTag := tag.Get("decimal") - if decimalTag != "number" { - return []byte(fmt.Sprintf(`"%s"`, tagValue)) - } case reflect.TypeOf(types.Date{}): return []byte(fmt.Sprintf(`"%s"`, tagValue)) default: @@ -571,27 +562,6 @@ func unmarshalValue(value json.RawMessage, v reflect.Value, tag reflect.StructTa v.Set(reflect.ValueOf(b)) return nil - case reflect.TypeOf(decimal.Big{}): - var d *decimal.Big - format := tag.Get("decimal") - if format == "number" { - var ok bool - d, ok = new(decimal.Big).SetString(string(value)) - if !ok { - return fmt.Errorf("failed to parse number as decimal.Big") - } - } else { - if err := json.Unmarshal(value, &d); err != nil { - return err - } - } - - if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Ptr { - v = v.Elem() - } - - v.Set(reflect.ValueOf(d)) - return nil case reflect.TypeOf(types.Date{}): var s string @@ -656,8 +626,6 @@ func isComplexValueType(typ reflect.Type) bool { fallthrough case reflect.TypeOf(big.Int{}): fallthrough - case reflect.TypeOf(decimal.Big{}): - fallthrough case reflect.TypeOf(types.Date{}): return true } @@ -677,3 +645,269 @@ func isModelType(typ reflect.Type) bool { return false } + +// CalculateJSONSize returns the byte size of the JSON representation of a value. +// This is used to determine which union type variant has the most data. +func CalculateJSONSize(v interface{}) int { + data, err := json.Marshal(v) + if err != nil { + return 0 + } + return len(data) +} + +// UnionCandidate represents a candidate type during union deserialization +type UnionCandidate struct { + FieldCount int + InexactCount int // Count of fields with unknown/unrecognized enum values + Size int + Type any // The union type enum value + Value any // The unmarshaled value +} + +// FieldCounts holds the result of counting fields in a value +type FieldCounts struct { + Total int // Total number of populated fields + Inexact int // Number of fields with unknown/unrecognized open enum values +} + +// CountFieldsWithInexact recursively counts fields and tracks inexact matches (unknown open enum values). +func CountFieldsWithInexact(v interface{}) FieldCounts { + if v == nil { + return FieldCounts{} + } + + typ := reflect.TypeOf(v) + val := reflect.ValueOf(v) + + // Dereference pointers + for typ.Kind() == reflect.Ptr { + if val.IsNil() { + return FieldCounts{} + } + typ = typ.Elem() + val = val.Elem() + } + + return countFieldsRecursive(typ, val) +} + +// PickBestCandidate selects the best union type candidate using a multi-stage filtering approach: +// 1. If multiple candidates, filter by field count (keep only those with max field count) +// 2. If still multiple, filter by inexact count (keep only those with min inexact count) +// 3. If still multiple, filter by JSON size (keep only those with max size) +// 4. Return the first remaining candidate +func PickBestCandidate(candidates []UnionCandidate) *UnionCandidate { + if len(candidates) == 0 { + return nil + } + + if len(candidates) == 1 { + return &candidates[0] + } + + // Filter by field count if we have multiple candidates + if len(candidates) > 1 { + maxFieldCount := -1 + for i := range candidates { + fieldCounts := CountFieldsWithInexact(candidates[i].Value) + candidates[i].FieldCount = fieldCounts.Total + candidates[i].InexactCount = fieldCounts.Inexact + if candidates[i].FieldCount > maxFieldCount { + maxFieldCount = candidates[i].FieldCount + } + } + + // Keep only candidates with maximum field count + filtered := make([]UnionCandidate, 0, len(candidates)) + for _, c := range candidates { + if c.FieldCount == maxFieldCount { + filtered = append(filtered, c) + } + } + candidates = filtered + } + + if len(candidates) == 1 { + return &candidates[0] + } + + // Filter by inexact count if we still have multiple candidates + // Prefer candidates with fewer unknown/unrecognized enum values + if len(candidates) > 1 { + minInexactCount := int(^uint(0) >> 1) // max int + for _, c := range candidates { + if c.InexactCount < minInexactCount { + minInexactCount = c.InexactCount + } + } + + // Keep only candidates with minimum inexact count + filtered := make([]UnionCandidate, 0, len(candidates)) + for _, c := range candidates { + if c.InexactCount == minInexactCount { + filtered = append(filtered, c) + } + } + candidates = filtered + } + + if len(candidates) == 1 { + return &candidates[0] + } + + // Filter by JSON size if we still have multiple candidates + if len(candidates) > 1 { + maxSize := -1 + for i := range candidates { + candidates[i].Size = CalculateJSONSize(candidates[i].Value) + if candidates[i].Size > maxSize { + maxSize = candidates[i].Size + } + } + + // Keep only candidates with maximum size + filtered := make([]UnionCandidate, 0, len(candidates)) + for _, c := range candidates { + if c.Size == maxSize { + filtered = append(filtered, c) + } + } + candidates = filtered + } + + // Pick the first remaining candidate + return &candidates[0] +} + +func countFieldsRecursive(typ reflect.Type, val reflect.Value) FieldCounts { + counts := FieldCounts{} + + // Check if the value has an IsExact() method (for open enums) + // Try both the value and its pointer + if val.CanInterface() && val.CanAddr() { + ptrVal := val.Addr() + if method := ptrVal.MethodByName("IsExact"); method.IsValid() { + results := method.Call(nil) + if len(results) == 1 && results[0].Kind() == reflect.Bool { + isExact := results[0].Bool() + counts.Total = 1 + if !isExact { + counts.Inexact = 1 // Unknown enum value + } + return counts + } + } + } + + switch typ.Kind() { + case reflect.Struct: + // Handle special types + switch typ { + case reflect.TypeOf(time.Time{}): + if !val.Interface().(time.Time).IsZero() { + return FieldCounts{Total: 1} + } + return FieldCounts{} + case reflect.TypeOf(big.Int{}): + b := val.Interface().(big.Int) + if b.Sign() != 0 { + return FieldCounts{Total: 1} + } + return FieldCounts{} + case reflect.TypeOf(types.Date{}): + // Date is always counted if it exists + return FieldCounts{Total: 1} + } + + // For regular structs, count non-zero fields + for i := 0; i < typ.NumField(); i++ { + field := typ.Field(i) + fieldVal := val.Field(i) + + // Skip unexported fields and const fields + if !field.IsExported() || field.Tag.Get("const") != "" { + continue + } + + // Skip fields tagged with json:"-" + jsonTag := field.Tag.Get("json") + if jsonTag == "-" { + continue + } + + fieldTyp := field.Type + // Dereference pointer types for the field + for fieldTyp.Kind() == reflect.Ptr { + if fieldVal.IsNil() { + break + } + fieldTyp = fieldTyp.Elem() + fieldVal = fieldVal.Elem() + } + + if !isNil(field.Type, val.Field(i)) { + fieldCounts := countFieldsRecursive(fieldTyp, fieldVal) + counts.Total += fieldCounts.Total + counts.Inexact += fieldCounts.Inexact + } + } + + case reflect.Slice, reflect.Array: + if val.IsNil() || val.Len() == 0 { + return FieldCounts{} + } + // Count each array/slice element + for i := 0; i < val.Len(); i++ { + itemVal := val.Index(i) + itemTyp := itemVal.Type() + + // Dereference pointer types + for itemTyp.Kind() == reflect.Ptr { + if itemVal.IsNil() { + break + } + itemTyp = itemTyp.Elem() + itemVal = itemVal.Elem() + } + + if !isNil(itemTyp, itemVal) { + itemCounts := countFieldsRecursive(itemTyp, itemVal) + counts.Total += itemCounts.Total + counts.Inexact += itemCounts.Inexact + } + } + + case reflect.String: + if val.String() != "" { + counts.Total = 1 + } + + case reflect.Bool: + // Bools always count as a field (even if false) + counts.Total = 1 + + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + if val.Int() != 0 { + counts.Total = 1 + } + + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + if val.Uint() != 0 { + counts.Total = 1 + } + + case reflect.Float32, reflect.Float64: + if val.Float() != 0 { + counts.Total = 1 + } + + default: + // For any other type, if it's not zero, count it as 1 + if !val.IsZero() { + counts.Total = 1 + } + } + + return counts +} diff --git a/internal/utils/pathparams.go b/internal/utils/pathparams.go index de1e909..3f053d6 100644 --- a/internal/utils/pathparams.go +++ b/internal/utils/pathparams.go @@ -11,8 +11,6 @@ import ( "strings" "time" - "github.com/ericlagergren/decimal" - "github.com/QuePlatform/GoSDK/optionalnullable" "github.com/QuePlatform/GoSDK/types" ) @@ -146,8 +144,6 @@ func getSimplePathParams(parentName string, objType reflect.Type, objValue refle pathParams[parentName] = valToString(objValue.Interface()) case big.Int: pathParams[parentName] = valToString(objValue.Interface()) - case decimal.Big: - pathParams[parentName] = valToString(objValue.Interface()) default: var ppVals []string for i := 0; i < objType.NumField(); i++ { diff --git a/internal/utils/queryparams.go b/internal/utils/queryparams.go index 2bb8071..07edb10 100644 --- a/internal/utils/queryparams.go +++ b/internal/utils/queryparams.go @@ -12,13 +12,11 @@ import ( "reflect" "time" - "github.com/ericlagergren/decimal" - "github.com/QuePlatform/GoSDK/optionalnullable" "github.com/QuePlatform/GoSDK/types" ) -func PopulateQueryParams(_ context.Context, req *http.Request, queryParams interface{}, globals interface{}) error { +func PopulateQueryParams(_ context.Context, req *http.Request, queryParams interface{}, globals interface{}, allowEmptyValue map[string]struct{}) error { // Query parameters may already be present from overriding URL if req.URL.RawQuery != "" { return nil @@ -26,13 +24,13 @@ func PopulateQueryParams(_ context.Context, req *http.Request, queryParams inter values := url.Values{} - globalsAlreadyPopulated, err := populateQueryParams(queryParams, globals, values, []string{}) + globalsAlreadyPopulated, err := populateQueryParams(queryParams, globals, values, []string{}, allowEmptyValue) if err != nil { return err } if globals != nil { - _, err = populateQueryParams(globals, nil, values, globalsAlreadyPopulated) + _, err = populateQueryParams(globals, nil, values, globalsAlreadyPopulated, allowEmptyValue) if err != nil { return err } @@ -43,11 +41,14 @@ func PopulateQueryParams(_ context.Context, req *http.Request, queryParams inter return nil } -func populateQueryParams(queryParams interface{}, globals interface{}, values url.Values, skipFields []string) ([]string, error) { - queryParamsStructType, queryParamsValType := dereferencePointers(reflect.TypeOf(queryParams), reflect.ValueOf(queryParams)) +func populateQueryParams(queryParams interface{}, globals interface{}, values url.Values, skipFields []string, allowEmptyValue map[string]struct{}) ([]string, error) { + queryParamsVal := reflect.ValueOf(queryParams) + if queryParamsVal.Kind() == reflect.Pointer && queryParamsVal.IsNil() { + return nil, nil + } + queryParamsStructType, queryParamsValType := dereferencePointers(reflect.TypeOf(queryParams), queryParamsVal) globalsAlreadyPopulated := []string{} - for i := 0; i < queryParamsStructType.NumField(); i++ { fieldType := queryParamsStructType.Field(i) valType := queryParamsValType.Field(i) @@ -100,14 +101,14 @@ func populateQueryParams(queryParams interface{}, globals interface{}, values ur } } case "form": - vals := populateFormParams(qpTag, fieldType.Type, valType, ",", defaultValue) + vals := populateFormParams(qpTag, fieldType.Type, valType, ",", defaultValue, allowEmptyValue) for k, v := range vals { for _, vv := range v { values.Add(k, vv) } } case "pipeDelimited": - vals := populateFormParams(qpTag, fieldType.Type, valType, "|", defaultValue) + vals := populateFormParams(qpTag, fieldType.Type, valType, "|", defaultValue, allowEmptyValue) for k, v := range vals { for _, vv := range v { values.Add(k, vv) @@ -246,7 +247,7 @@ func populateDeepObjectParamsStruct(qsValues url.Values, priorScope string, stru populateDeepObjectParamsMap(qsValues, scope, fieldValue) case reflect.Struct: switch fieldValue.Type() { - case reflect.TypeOf(big.Int{}), reflect.TypeOf(decimal.Big{}), reflect.TypeOf(time.Time{}), reflect.TypeOf(types.Date{}): + case reflect.TypeOf(big.Int{}), reflect.TypeOf(time.Time{}), reflect.TypeOf(types.Date{}): qsValues.Add(scope, valToString(fieldValue.Interface())) continue @@ -259,8 +260,8 @@ func populateDeepObjectParamsStruct(qsValues url.Values, priorScope string, stru } } -func populateFormParams(tag *paramTag, objType reflect.Type, objValue reflect.Value, delimiter string, defaultValue *string) url.Values { - return populateForm(tag.ParamName, tag.Explode, objType, objValue, delimiter, defaultValue, func(fieldType reflect.StructField) string { +func populateFormParams(tag *paramTag, objType reflect.Type, objValue reflect.Value, delimiter string, defaultValue *string, allowEmptyValue map[string]struct{}) url.Values { + return populateForm(tag.ParamName, tag.Explode, objType, objValue, delimiter, defaultValue, allowEmptyValue, func(fieldType reflect.StructField) string { qpTag := parseQueryParamTag(fieldType) if qpTag == nil { return "" diff --git a/internal/utils/requestbody.go b/internal/utils/requestbody.go index 93167af..74f9b51 100644 --- a/internal/utils/requestbody.go +++ b/internal/utils/requestbody.go @@ -207,7 +207,7 @@ func encodeMultipartFormData(w io.Writer, data interface{}) (string, error) { case reflect.Slice, reflect.Array: values := parseDelimitedArray(true, valType, ",") for _, v := range values { - if err := writer.WriteField(tag.Name+"[]", v); err != nil { + if err := writer.WriteField(tag.Name, v); err != nil { writer.Close() return "", err } @@ -325,7 +325,7 @@ func encodeFormData(fieldName string, w io.Writer, data interface{}) error { switch tag.Style { // TODO: support other styles case "form": - values := populateForm(tag.Name, tag.Explode, fieldType, valType, ",", nil, func(sf reflect.StructField) string { + values := populateForm(tag.Name, tag.Explode, fieldType, valType, ",", nil, nil, func(sf reflect.StructField) string { tag := parseFormTag(field) if tag == nil { return "" diff --git a/internal/utils/utils.go b/internal/utils/utils.go index 9b9591e..ee4300f 100644 --- a/internal/utils/utils.go +++ b/internal/utils/utils.go @@ -15,8 +15,6 @@ import ( "strconv" "strings" "time" - - "github.com/ericlagergren/decimal" ) const ( @@ -227,8 +225,6 @@ func valToString(val interface{}) string { return v.Format(time.RFC3339Nano) case big.Int: return v.String() - case decimal.Big: - return v.String() default: return fmt.Sprintf("%v", v) } @@ -289,6 +285,21 @@ func isNil(typ reflect.Type, val reflect.Value) bool { return false } +func isEmptyContainer(typ reflect.Type, val reflect.Value) bool { + if isNil(typ, val) { + return true + } + + switch typ.Kind() { + case reflect.Slice, reflect.Array: + return val.Len() == 0 + case reflect.Map: + return val.Len() == 0 + default: + return false + } +} + func isZeroValue(v reflect.Value) bool { switch v.Kind() { case reflect.String: diff --git a/models/components/assetrefdto.go b/models/components/assetrefdto.go index f3555c3..e9eeaf8 100644 --- a/models/components/assetrefdto.go +++ b/models/components/assetrefdto.go @@ -17,8 +17,8 @@ const ( // AssetRefDto - A reference to a digital asset, either stored in S3 or accessible via URL. Files are streamed efficiently to temporary storage during processing to minimize memory usage. type AssetRefDto struct { - S3 *S3 `queryParam:"inline" name:"AssetRefDto"` - PresignedURL *PresignedURL `queryParam:"inline" name:"AssetRefDto"` + S3 *S3 `queryParam:"inline,name=AssetRefDto"` + PresignedURL *PresignedURL `queryParam:"inline,name=AssetRefDto"` Type AssetRefDtoType } diff --git a/models/components/cawgidentitydto.go b/models/components/cawgidentitydto.go index a149ace..1ef6ddf 100644 --- a/models/components/cawgidentitydto.go +++ b/models/components/cawgidentitydto.go @@ -116,8 +116,8 @@ const ( ) type Signer struct { - SignerUseMainSigner *SignerUseMainSigner `queryParam:"inline" name:"signer"` - SignerSeparate *SignerSeparate `queryParam:"inline" name:"signer"` + SignerUseMainSigner *SignerUseMainSigner `queryParam:"inline,name=signer"` + SignerSeparate *SignerSeparate `queryParam:"inline,name=signer"` Type SignerType } diff --git a/models/components/signerrefdto.go b/models/components/signerrefdto.go index 4139fc5..7a5f833 100644 --- a/models/components/signerrefdto.go +++ b/models/components/signerrefdto.go @@ -140,8 +140,8 @@ const ( // SignerRefDto - Reference to credentials for signing. type SignerRefDto struct { - SignerRefDtoEnv *SignerRefDtoEnv `queryParam:"inline" name:"SignerRefDto"` - SignerRefDtoLocal *SignerRefDtoLocal `queryParam:"inline" name:"SignerRefDto"` + SignerRefDtoEnv *SignerRefDtoEnv `queryParam:"inline,name=SignerRefDto"` + SignerRefDtoLocal *SignerRefDtoLocal `queryParam:"inline,name=SignerRefDto"` Type SignerRefDtoType } diff --git a/que.go b/que.go index ee0a43d..dc9046f 100644 --- a/que.go +++ b/que.go @@ -2,7 +2,7 @@ package que -// Generated from OpenAPI doc version 1.0.0 and generator version 2.708.2 +// Generated from OpenAPI doc version 1.0.0 and generator version 2.768.0 import ( "bytes" @@ -167,9 +167,9 @@ func WithTimeout(timeout time.Duration) SDKOption { // New creates a new instance of the SDK with the provided options func New(opts ...SDKOption) *Que { sdk := &Que{ - SDKVersion: "0.0.2", + SDKVersion: "0.1.0", sdkConfiguration: config.SDKConfiguration{ - UserAgent: "speakeasy-sdk/go 0.0.2 2.708.2 1.0.0 github.com/QuePlatform/GoSDK", + UserAgent: "speakeasy-sdk/go 0.1.0 2.768.0 1.0.0 github.com/QuePlatform/GoSDK", ServerList: ServerList, ServerVariables: []map[string]string{ { diff --git a/types/decimal.go b/types/decimal.go deleted file mode 100644 index d8429bc..0000000 --- a/types/decimal.go +++ /dev/null @@ -1,20 +0,0 @@ -// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. - -package types - -import ( - "fmt" - - "github.com/ericlagergren/decimal" -) - -// MustNewDecimalFromString returns an instance of Decimal from a string -// Avoid using this function in production code. -func MustNewDecimalFromString(s string) *decimal.Big { - d, ok := new(decimal.Big).SetString(s) - if !ok { - panic(fmt.Errorf("failed to parse string as decimal.Big")) - } - - return d -}