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