package graphql type Payload[T any, P any] struct { OutermostLayer ContainerLayer[T, P] } func (q *Payload[T, P]) GetValue() T { if q.OutermostLayer == nil { var res T return res } layer := q.OutermostLayer for layer.GetInnerLayer() != nil { layer = layer.GetInnerLayer() } return layer.GetValue() } func NewPayload[T any, P any](gqlType string, containerLayers ...string) *Payload[T, P] { if len(containerLayers) == 0 { return &Payload[T, P]{ OutermostLayer: NewWrapper[T, P](gqlType), } } var buildLayer func(index int) ContainerLayer[T, P] buildLayer = func(index int) ContainerLayer[T, P] { if index == len(containerLayers) { return NewWrapper[T, P](gqlType) } return &NestedLayer[T, P]{ gqlType: containerLayers[index], InnerLayer: buildLayer(index + 1), } } return &Payload[T, P]{OutermostLayer: buildLayer(0)} } type ContainerLayer[T any, P any] interface { GetInnerLayer() ContainerLayer[T, P] GetValue() T GetGraphQLType() string } type NestedLayer[T any, P any] struct { gqlType string `graphql:"-"` InnerLayer ContainerLayer[T, P] } func (nl *NestedLayer[T, P]) GetInnerLayer() ContainerLayer[T, P] { return nl.InnerLayer } func (nl *NestedLayer[T, P]) GetValue() T { var res T return res } func (nl *NestedLayer[T, P]) GetGraphQLType() string { return nl.gqlType } type Wrapper[T any, P any] struct { gqlType string `graphql:"-"` Value T } func (w Wrapper[T, P]) GetInnerLayer() ContainerLayer[T, P] { return nil } func (w Wrapper[T, P]) GetValue() T { return w.Value } func (w Wrapper[T, P]) GetGraphQLWrapped() T { return w.Value } func (w Wrapper[T, P]) GetGraphQLType() string { return w.gqlType } func NewWrapper[T any, P any](gqlType string) *Wrapper[T, P] { return &Wrapper[T, P]{ gqlType: gqlType, } }