From 7483296a2abfd754f03c3d65290aa11d2d286448 Mon Sep 17 00:00:00 2001 From: General Kroll Date: Fri, 27 Feb 2026 01:38:15 +1100 Subject: [PATCH] late-binding-armoury --- internal/anysdk/http_armoury.go | 24 +++++++++--- internal/anysdk/request.go | 65 +++++++++++++++++++++++++------- public/formulation/interfaces.go | 2 + public/formulation/wrappers.go | 21 +++++++++++ 4 files changed, 93 insertions(+), 19 deletions(-) diff --git a/internal/anysdk/http_armoury.go b/internal/anysdk/http_armoury.go index d3aa4eb..09f51f2 100644 --- a/internal/anysdk/http_armoury.go +++ b/internal/anysdk/http_armoury.go @@ -12,12 +12,23 @@ type HTTPArmoury interface { SetRequestParams([]HTTPArmouryParameters) SetRequestSchema(Schema) SetResponseSchema(Schema) + MergeLateBindingMaps(map[int]map[string]any) (HTTPArmoury, error) } type standardHTTPArmoury struct { - RequestParams []HTTPArmouryParameters - RequestSchema Schema - ResponseSchema Schema + RequestParams []HTTPArmouryParameters + RequestSchema Schema + ResponseSchema Schema + parentPreparator HTTPPreparator + prepcfg HTTPPreparatorConfig // memory of how it was prepared +} + +func (ih *standardHTTPArmoury) MergeLateBindingMaps(m map[int]map[string]any) (HTTPArmoury, error) { + clonedParent, err := ih.parentPreparator.MergeParams(m) + if err != nil { + return nil, err + } + return clonedParent.BuildHTTPRequestCtx(ih.prepcfg) } func (ih *standardHTTPArmoury) GetRequestParams() []HTTPArmouryParameters { @@ -48,6 +59,9 @@ func (ih *standardHTTPArmoury) GetResponseSchema() Schema { return ih.ResponseSchema } -func NewHTTPArmoury() HTTPArmoury { - return &standardHTTPArmoury{} +func NewHTTPArmoury(parentPreparator HTTPPreparator, prepCfg HTTPPreparatorConfig) HTTPArmoury { + return &standardHTTPArmoury{ + parentPreparator: parentPreparator, + prepcfg: prepCfg, + } } diff --git a/internal/anysdk/request.go b/internal/anysdk/request.go index 8f322a9..1d914de 100644 --- a/internal/anysdk/request.go +++ b/internal/anysdk/request.go @@ -35,13 +35,14 @@ func NewHTTPPreparatorConfig(isFromAnnotation bool) HTTPPreparatorConfig { type HTTPPreparator interface { BuildHTTPRequestCtx(HTTPPreparatorConfig) (HTTPArmoury, error) + MergeParams(map[int]map[string]any) (HTTPPreparator, error) } type standardHTTPPreparator struct { prov Provider m OperationStore svc Service - paramMap map[int]map[string]interface{} + paramMap map[int]map[string]any execContext ExecContext logger *logrus.Logger parameters streaming.MapStream @@ -52,7 +53,7 @@ func NewHTTPPreparator( prov Provider, svc Service, m OperationStore, - paramMap map[int]map[string]interface{}, + paramMap map[int]map[string]any, parameters streaming.MapStream, execContext ExecContext, logger *logrus.Logger, @@ -64,7 +65,7 @@ func newHTTPPreparator( prov Provider, svc Service, m OperationStore, - paramMap map[int]map[string]interface{}, + paramMap map[int]map[string]any, parameters streaming.MapStream, execContext ExecContext, logger *logrus.Logger, @@ -84,17 +85,53 @@ func newHTTPPreparator( } } +func (pr *standardHTTPPreparator) clone() *standardHTTPPreparator { + newParamMap := make(map[int]map[string]any) + for k, v := range pr.paramMap { + cloneSubMap := make(map[string]any) + for subK, subV := range v { + cloneSubMap[subK] = subV + } + newParamMap[k] = cloneSubMap + } + return &standardHTTPPreparator{ + prov: pr.prov, + m: pr.m, + svc: pr.svc, + paramMap: newParamMap, + parameters: pr.parameters, + execContext: pr.execContext, + logger: pr.logger, + } +} + +func (pr *standardHTTPPreparator) MergeParams(maps map[int]map[string]any) (HTTPPreparator, error) { + rv := pr.clone() + if len(maps) > 1 { + return nil, fmt.Errorf("multiple maps provided for merging, cartesian product not yet supported") + } + for k, v := range maps { + if _, exists := rv.paramMap[k]; !exists { + rv.paramMap[k] = make(map[string]any) + } + for subK, subV := range v { + rv.paramMap[k][subK] = subV + } + } + return rv, nil +} + //nolint:funlen,gocognit // TODO: review func (pr *standardHTTPPreparator) BuildHTTPRequestCtx(cfg HTTPPreparatorConfig) (HTTPArmoury, error) { if cfg.IsFromAnnotation() { - return pr.buildHTTPRequestCtxFromAnnotation() + return pr.buildHTTPRequestCtxFromAnnotation(cfg) } method, methodOk := pr.m.(StandardOperationStore) if !methodOk { return nil, fmt.Errorf("operation store is not a standard operation store") } var err error - httpArmoury := NewHTTPArmoury() + httpArmoury := NewHTTPArmoury(pr, cfg) var requestSchema, responseSchema Schema req, reqExists := pr.m.GetRequest() if reqExists && req.GetSchema() != nil { @@ -133,7 +170,7 @@ func (pr *standardHTTPPreparator) BuildHTTPRequestCtx(cfg HTTPPreparatorConfig) params.SetRequestBody(bm) } } else if params.GetRequestBody() != nil && len(params.GetRequestBody()) != 0 { - m := make(map[string]interface{}) + m := make(map[string]any) baseRequestBytes := method.getBaseRequestBodyBytes() if len(baseRequestBytes) > 0 { mapErr := json.Unmarshal(baseRequestBytes, &m) @@ -175,7 +212,7 @@ func (pr *standardHTTPPreparator) BuildHTTPRequestCtx(cfg HTTPPreparatorConfig) if len(p.GetParameters().GetRequestBody()) == 0 && len(method.getDefaultRequestBodyBytes()) == 0 { p.SetRequestBodyMap(nil) } else if len(method.getDefaultRequestBodyBytes()) > 0 && len(p.GetParameters().GetRequestBody()) == 0 { - bm := make(map[string]interface{}) + bm := make(map[string]any) // TODO: support types other than json err := json.Unmarshal(method.getDefaultRequestBodyBytes(), &bm) if err == nil { @@ -211,8 +248,8 @@ func (pr *standardHTTPPreparator) BuildHTTPRequestCtx(cfg HTTPPreparatorConfig) func awsContextHousekeeping( ctx context.Context, method OperationStore, - contextParams map[string]interface{}, - parameters map[string]interface{}, + contextParams map[string]any, + parameters map[string]any, ) context.Context { svcName := method.getServiceNameForProvider() ctx = context.WithValue(ctx, "service", svcName) //nolint:revive,staticcheck // TODO: add custom context type @@ -253,9 +290,9 @@ func getRequest( } //nolint:funlen,gocognit // acceptable -func (pr *standardHTTPPreparator) buildHTTPRequestCtxFromAnnotation() (HTTPArmoury, error) { +func (pr *standardHTTPPreparator) buildHTTPRequestCtxFromAnnotation(cfg HTTPPreparatorConfig) (HTTPArmoury, error) { var err error - httpArmoury := NewHTTPArmoury() + httpArmoury := NewHTTPArmoury(pr, cfg) var requestSchema, responseSchema Schema httpMethod, httpMethodOk := pr.m.(StandardOperationStore) if !httpMethodOk { @@ -272,7 +309,7 @@ func (pr *standardHTTPPreparator) buildHTTPRequestCtxFromAnnotation() (HTTPArmou httpArmoury.SetRequestSchema(requestSchema) httpArmoury.SetResponseSchema(responseSchema) - paramMap := make(map[int]map[string]interface{}) + paramMap := make(map[int]map[string]any) i := 0 for { out, oErr := pr.parameters.Read() @@ -306,7 +343,7 @@ func (pr *standardHTTPPreparator) buildHTTPRequestCtxFromAnnotation() (HTTPArmou } params.SetRequestBody(pr.execContext.GetExecPayload().GetPayloadMap()) } else if params.GetRequestBody() != nil && len(params.GetRequestBody()) != 0 { - m := make(map[string]interface{}) + m := make(map[string]any) baseRequestBytes := httpMethod.getBaseRequestBodyBytes() if len(baseRequestBytes) > 0 { mapErr := json.Unmarshal(baseRequestBytes, &m) @@ -348,7 +385,7 @@ func (pr *standardHTTPPreparator) buildHTTPRequestCtxFromAnnotation() (HTTPArmou if len(p.GetParameters().GetRequestBody()) == 0 && len(httpMethod.getDefaultRequestBodyBytes()) == 0 { p.SetRequestBodyMap(nil) } else if len(httpMethod.getDefaultRequestBodyBytes()) > 0 { - bm := make(map[string]interface{}) + bm := make(map[string]any) // TODO: support types other than json err := json.Unmarshal(httpMethod.getDefaultRequestBodyBytes(), &bm) if err == nil { diff --git a/public/formulation/interfaces.go b/public/formulation/interfaces.go index ed85763..4856248 100644 --- a/public/formulation/interfaces.go +++ b/public/formulation/interfaces.go @@ -92,6 +92,7 @@ type HTTPArmoury interface { SetRequestParams([]HTTPArmouryParameters) SetRequestSchema(Schema) SetResponseSchema(Schema) + MergeLateBindingMaps(m map[int]map[string]any) (HTTPArmoury, error) unwrap() anysdk.HTTPArmoury } @@ -111,6 +112,7 @@ type HTTPArmouryParameters interface { // HTTPPreparator mirrors methods on HTTPPreparator type HTTPPreparator interface { BuildHTTPRequestCtx(p0 anysdk.HTTPPreparatorConfig) (HTTPArmoury, error) + MergeParams(map[int]map[string]any) (HTTPPreparator, error) unwrap() anysdk.HTTPPreparator } diff --git a/public/formulation/wrappers.go b/public/formulation/wrappers.go index 84a95ed..279903b 100644 --- a/public/formulation/wrappers.go +++ b/public/formulation/wrappers.go @@ -538,6 +538,11 @@ type wrappedHTTPArmoury struct { inner anysdk.HTTPArmoury } +func (w *wrappedHTTPArmoury) MergeLateBindingMaps(m map[int]map[string]any) (HTTPArmoury, error) { + r0, r1 := w.inner.MergeLateBindingMaps(m) + return &wrappedHTTPArmoury{inner: r0}, r1 +} + func (w *wrappedHTTPArmoury) AddRequestParams(p HTTPArmouryParameters) { w.inner.AddRequestParams(p.unwrap()) } @@ -629,6 +634,14 @@ type wrappedHTTPPreparator struct { inner anysdk.HTTPPreparator } +func (w *wrappedHTTPPreparator) MergeParams(m map[int]map[string]any) (HTTPPreparator, error) { + r0, r1 := w.inner.MergeParams(m) + if r1 != nil { + return nil, r1 + } + return &wrappedHTTPPreparator{inner: r0}, nil +} + func (w *wrappedHTTPPreparator) unwrap() anysdk.HTTPPreparator { return w.inner } @@ -2702,6 +2715,14 @@ type reverseWrappedHTTPArmoury struct { inner HTTPArmoury } +func (w *reverseWrappedHTTPArmoury) MergeLateBindingMaps(m map[int]map[string]any) (anysdk.HTTPArmoury, error) { + r0, r1 := w.inner.MergeLateBindingMaps(m) + if r1 != nil { + return nil, r1 + } + return &reverseWrappedHTTPArmoury{inner: r0}, nil +} + func (w *reverseWrappedHTTPArmoury) AddRequestParams(params anysdk.HTTPArmouryParameters) { p := &wrappedHTTPArmouryParameters{inner: params} w.inner.AddRequestParams(p)