mirror of https://github.com/stashapp/stash.git
239 lines
6.4 KiB
Go
239 lines
6.4 KiB
Go
package clientgen
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"go/types"
|
|
|
|
"github.com/99designs/gqlgen/codegen/templates"
|
|
"github.com/Yamashou/gqlgenc/config"
|
|
"github.com/vektah/gqlparser/v2/ast"
|
|
"github.com/vektah/gqlparser/v2/formatter"
|
|
)
|
|
|
|
type Source struct {
|
|
schema *ast.Schema
|
|
queryDocument *ast.QueryDocument
|
|
sourceGenerator *SourceGenerator
|
|
generateConfig *config.GenerateConfig
|
|
}
|
|
|
|
func NewSource(schema *ast.Schema, queryDocument *ast.QueryDocument, sourceGenerator *SourceGenerator, generateConfig *config.GenerateConfig) *Source {
|
|
return &Source{
|
|
schema: schema,
|
|
queryDocument: queryDocument,
|
|
sourceGenerator: sourceGenerator,
|
|
generateConfig: generateConfig,
|
|
}
|
|
}
|
|
|
|
type Fragment struct {
|
|
Name string
|
|
Type types.Type
|
|
}
|
|
|
|
func (s *Source) Fragments() ([]*Fragment, error) {
|
|
fragments := make([]*Fragment, 0, len(s.queryDocument.Fragments))
|
|
for _, fragment := range s.queryDocument.Fragments {
|
|
responseFields := s.sourceGenerator.NewResponseFields(fragment.SelectionSet)
|
|
if s.sourceGenerator.cfg.Models.Exists(fragment.Name) {
|
|
return nil, fmt.Errorf("%s is duplicated", fragment.Name)
|
|
}
|
|
|
|
fragment := &Fragment{
|
|
Name: fragment.Name,
|
|
Type: responseFields.StructType(),
|
|
}
|
|
|
|
fragments = append(fragments, fragment)
|
|
}
|
|
|
|
for _, fragment := range fragments {
|
|
name := fragment.Name
|
|
s.sourceGenerator.cfg.Models.Add(
|
|
name,
|
|
fmt.Sprintf("%s.%s", s.sourceGenerator.client.Pkg(), templates.ToGo(name)),
|
|
)
|
|
}
|
|
|
|
return fragments, nil
|
|
}
|
|
|
|
type Operation struct {
|
|
Name string
|
|
ResponseStructName string
|
|
Operation string
|
|
Args []*Argument
|
|
VariableDefinitions ast.VariableDefinitionList
|
|
}
|
|
|
|
func NewOperation(operation *ast.OperationDefinition, queryDocument *ast.QueryDocument, args []*Argument, generateConfig *config.GenerateConfig) *Operation {
|
|
return &Operation{
|
|
Name: operation.Name,
|
|
ResponseStructName: getResponseStructName(operation, generateConfig),
|
|
Operation: queryString(queryDocument),
|
|
Args: args,
|
|
VariableDefinitions: operation.VariableDefinitions,
|
|
}
|
|
}
|
|
|
|
func (s *Source) Operations(queryDocuments []*ast.QueryDocument) ([]*Operation, error) {
|
|
operations := make([]*Operation, 0, len(s.queryDocument.Operations))
|
|
|
|
operationNames := make(map[string]struct{})
|
|
|
|
queryDocumentsMap := queryDocumentMapByOperationName(queryDocuments)
|
|
operationArgsMap := s.operationArgsMapByOperationName()
|
|
for _, operation := range s.queryDocument.Operations {
|
|
queryDocument := queryDocumentsMap[operation.Name]
|
|
|
|
_, exist := operationNames[templates.ToGo(operation.Name)]
|
|
if exist {
|
|
return nil, fmt.Errorf("duplicate operation: %s", operation.Name)
|
|
}
|
|
operationNames[templates.ToGo(operation.Name)] = struct{}{}
|
|
|
|
args := operationArgsMap[operation.Name]
|
|
operations = append(operations, NewOperation(
|
|
operation,
|
|
queryDocument,
|
|
args,
|
|
s.generateConfig,
|
|
))
|
|
}
|
|
|
|
return operations, nil
|
|
}
|
|
|
|
func (s *Source) operationArgsMapByOperationName() map[string][]*Argument {
|
|
operationArgsMap := make(map[string][]*Argument)
|
|
for _, operation := range s.queryDocument.Operations {
|
|
operationArgsMap[operation.Name] = s.sourceGenerator.OperationArguments(operation.VariableDefinitions)
|
|
}
|
|
|
|
return operationArgsMap
|
|
}
|
|
|
|
func queryDocumentMapByOperationName(queryDocuments []*ast.QueryDocument) map[string]*ast.QueryDocument {
|
|
queryDocumentMap := make(map[string]*ast.QueryDocument)
|
|
for _, queryDocument := range queryDocuments {
|
|
operation := queryDocument.Operations[0]
|
|
queryDocumentMap[operation.Name] = queryDocument
|
|
}
|
|
|
|
return queryDocumentMap
|
|
}
|
|
|
|
func queryString(queryDocument *ast.QueryDocument) string {
|
|
var buf bytes.Buffer
|
|
astFormatter := formatter.NewFormatter(&buf)
|
|
astFormatter.FormatQueryDocument(queryDocument)
|
|
|
|
return buf.String()
|
|
}
|
|
|
|
type OperationResponse struct {
|
|
Name string
|
|
Type types.Type
|
|
}
|
|
|
|
func (s *Source) OperationResponses() ([]*OperationResponse, error) {
|
|
operationResponse := make([]*OperationResponse, 0, len(s.queryDocument.Operations))
|
|
for _, operation := range s.queryDocument.Operations {
|
|
responseFields := s.sourceGenerator.NewResponseFields(operation.SelectionSet)
|
|
name := getResponseStructName(operation, s.generateConfig)
|
|
if s.sourceGenerator.cfg.Models.Exists(name) {
|
|
return nil, fmt.Errorf("%s is duplicated", name)
|
|
}
|
|
operationResponse = append(operationResponse, &OperationResponse{
|
|
Name: name,
|
|
Type: responseFields.StructType(),
|
|
})
|
|
}
|
|
|
|
for _, operationResponse := range operationResponse {
|
|
name := operationResponse.Name
|
|
s.sourceGenerator.cfg.Models.Add(
|
|
name,
|
|
fmt.Sprintf("%s.%s", s.sourceGenerator.client.Pkg(), templates.ToGo(name)),
|
|
)
|
|
}
|
|
|
|
return operationResponse, nil
|
|
}
|
|
|
|
type Query struct {
|
|
Name string
|
|
Type types.Type
|
|
}
|
|
|
|
func (s *Source) Query() (*Query, error) {
|
|
fields, err := s.sourceGenerator.NewResponseFieldsByDefinition(s.schema.Query)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("generate failed for query struct type : %w", err)
|
|
}
|
|
|
|
s.sourceGenerator.cfg.Models.Add(
|
|
s.schema.Query.Name,
|
|
fmt.Sprintf("%s.%s", s.sourceGenerator.client.Pkg(), templates.ToGo(s.schema.Query.Name)),
|
|
)
|
|
|
|
return &Query{
|
|
Name: s.schema.Query.Name,
|
|
Type: fields.StructType(),
|
|
}, nil
|
|
}
|
|
|
|
type Mutation struct {
|
|
Name string
|
|
Type types.Type
|
|
}
|
|
|
|
func (s *Source) Mutation() (*Mutation, error) {
|
|
if s.schema.Mutation == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
fields, err := s.sourceGenerator.NewResponseFieldsByDefinition(s.schema.Mutation)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("generate failed for mutation struct type : %w", err)
|
|
}
|
|
|
|
s.sourceGenerator.cfg.Models.Add(
|
|
s.schema.Mutation.Name,
|
|
fmt.Sprintf("%s.%s", s.sourceGenerator.client.Pkg(), templates.ToGo(s.schema.Mutation.Name)),
|
|
)
|
|
|
|
return &Mutation{
|
|
Name: s.schema.Mutation.Name,
|
|
Type: fields.StructType(),
|
|
}, nil
|
|
}
|
|
|
|
func getResponseStructName(operation *ast.OperationDefinition, generateConfig *config.GenerateConfig) string {
|
|
name := operation.Name
|
|
if generateConfig != nil {
|
|
if generateConfig.Prefix != nil {
|
|
if operation.Operation == ast.Mutation {
|
|
name = fmt.Sprintf("%s%s", generateConfig.Prefix.Mutation, name)
|
|
}
|
|
|
|
if operation.Operation == ast.Query {
|
|
name = fmt.Sprintf("%s%s", generateConfig.Prefix.Query, name)
|
|
}
|
|
}
|
|
|
|
if generateConfig.Suffix != nil {
|
|
if operation.Operation == ast.Mutation {
|
|
name = fmt.Sprintf("%s%s", name, generateConfig.Suffix.Mutation)
|
|
}
|
|
|
|
if operation.Operation == ast.Query {
|
|
name = fmt.Sprintf("%s%s", name, generateConfig.Suffix.Query)
|
|
}
|
|
}
|
|
}
|
|
|
|
return name
|
|
}
|