mirror of
https://github.com/stashapp/stash.git
synced 2025-12-18 21:04:37 +03:00
Stash box client interface (#751)
* Add gql client generation files * Update dependencies * Add stash-box client generation to the makefile * Move scraped scene object matchers to models * Add stash-box to scrape with dropdown * Add scrape scene from fingerprint in UI
This commit is contained in:
7
vendor/github.com/Yamashou/gqlgenc/.gitignore
generated
vendored
Normal file
7
vendor/github.com/Yamashou/gqlgenc/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
/.gqlgenc.yml
|
||||
/models_gen.go
|
||||
/**/.graphqlconfig
|
||||
/schema.graphql
|
||||
/client.go
|
||||
/query/
|
||||
/.idea/
|
||||
65
vendor/github.com/Yamashou/gqlgenc/.golangci.yml
generated
vendored
Normal file
65
vendor/github.com/Yamashou/gqlgenc/.golangci.yml
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
# See https://github.com/golangci/golangci-lint/blob/master/.golangci.example.yml
|
||||
run:
|
||||
linters-settings:
|
||||
govet:
|
||||
enable-all: true
|
||||
disable:
|
||||
- shadow
|
||||
unused:
|
||||
check-exported: true
|
||||
unparam:
|
||||
check-exported: true
|
||||
varcheck:
|
||||
exported-fields: true
|
||||
structcheck:
|
||||
exported-fields: true
|
||||
nakedret:
|
||||
max-func-lines: 1
|
||||
|
||||
linters:
|
||||
enable-all: true
|
||||
disable:
|
||||
- testpackage
|
||||
- nestif
|
||||
- godot
|
||||
- wsl
|
||||
- lll
|
||||
- dupl
|
||||
- funlen
|
||||
- gochecknoinits
|
||||
- gochecknoglobals
|
||||
- godox
|
||||
- maligned
|
||||
- gocognit
|
||||
- gocyclo
|
||||
- interfacer
|
||||
- gomnd
|
||||
- goerr113
|
||||
fast: false
|
||||
|
||||
issues:
|
||||
exclude-rules:
|
||||
# Test
|
||||
- path: _test\.go
|
||||
text: "Using the variable on range scope `tt` in function literal"
|
||||
linters:
|
||||
- scopelint
|
||||
- path: _test\.go
|
||||
linters:
|
||||
- unused
|
||||
- structcheck
|
||||
- path: introspection/type.go
|
||||
linters:
|
||||
- structcheck # These types fits IntrospectionQuery
|
||||
- path: config/config.go
|
||||
text: "`Query` is unused" # used in main.go
|
||||
linters:
|
||||
- structcheck
|
||||
- path: graphqljson/graphql.go
|
||||
text: "`Extensions` is unused" # used in line 48
|
||||
linters:
|
||||
- structcheck
|
||||
- path: introspection/query.go
|
||||
text: "`Introspection` is unused" # used in config/config.go
|
||||
linters:
|
||||
- varcheck
|
||||
21
vendor/github.com/Yamashou/gqlgenc/LICENSE
generated
vendored
Normal file
21
vendor/github.com/Yamashou/gqlgenc/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Yamashou
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
10
vendor/github.com/Yamashou/gqlgenc/Makefile
generated
vendored
Normal file
10
vendor/github.com/Yamashou/gqlgenc/Makefile
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
MAKEFLAGS=--no-builtin-rules --no-builtin-variables --always-make
|
||||
|
||||
fmt:
|
||||
gofumports -local github.com/Yamashou/gqlgenc -w .
|
||||
|
||||
lint:
|
||||
golangci-lint run
|
||||
|
||||
test:
|
||||
go test -v ./...
|
||||
118
vendor/github.com/Yamashou/gqlgenc/README.md
generated
vendored
Normal file
118
vendor/github.com/Yamashou/gqlgenc/README.md
generated
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
# gqlgenc
|
||||
|
||||
## What is gqlgenc ?
|
||||
|
||||
This is Go library for building GraphQL client with [gqlgen](https://github.com/99designs/gqlgen)
|
||||
|
||||
## Motivation
|
||||
|
||||
Now, if you build GraphQL api client for Go, have choice:
|
||||
|
||||
- [github.com/shurcooL/graphql](https://github.com/shurcooL/graphql)
|
||||
- [github.com/machinebox/graphql](https://github.com/machinebox/graphql)
|
||||
|
||||
These libraries are very simple and easy to handle.
|
||||
However, as I work with [gqlgen](https://github.com/99designs/gqlgen) and [graphql-code-generator](https://graphql-code-generator.com/) every day, I find out the beauty of automatic generation.
|
||||
So I want to automatically generate types.
|
||||
|
||||
## Installation
|
||||
|
||||
```shell script
|
||||
go get -u github.com/Yamashou/gqlgenc
|
||||
```
|
||||
|
||||
## How to use
|
||||
|
||||
### Client Codes Only
|
||||
|
||||
gqlgenc base is gqlgen with [plugins](https://gqlgen.com/reference/plugins/). So the setting is yaml in each format.
|
||||
gqlgenc can be configured using a .gqlgenc.yml file,
|
||||
|
||||
```yaml
|
||||
|
||||
model:
|
||||
package: generated
|
||||
filename: ./models_gen.go # https://github.com/99designs/gqlgen/tree/master/plugin/modelgen
|
||||
client:
|
||||
package: generated
|
||||
filename: ./client.go # Where should any generated client go?
|
||||
models:
|
||||
Int:
|
||||
model: github.com/99designs/gqlgen/graphql.Int64
|
||||
Date:
|
||||
model: github.com/99designs/gqlgen/graphql.Time
|
||||
endpoint:
|
||||
url: https://api.annict.com/graphql # Where do you want to send your request?
|
||||
headers: # If you need header for getting introspection query, set it
|
||||
Authorization: "Bearer ${ANNICT_KEY}" # support environment variables
|
||||
query:
|
||||
- "./query/*.graphql" # Where are all the query files located?
|
||||
```
|
||||
|
||||
Execute the following command on same directory for .gqlgenc.yaml
|
||||
|
||||
```shell script
|
||||
gqlgenc
|
||||
```
|
||||
|
||||
### With gqlgen
|
||||
|
||||
Do this when creating a server and client for Go.
|
||||
You create your own entrypoint for gqlgen.
|
||||
This use case is very useful for testing your server.
|
||||
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/Yamashou/gqlgenc/clientgen"
|
||||
|
||||
"github.com/99designs/gqlgen/api"
|
||||
"github.com/99designs/gqlgen/codegen/config"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cfg, err := config.LoadConfigFromDefaultLocations()
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "failed to load config", err.Error())
|
||||
os.Exit(2)
|
||||
}
|
||||
queries := []string{"client.query", "fragemt.query"}
|
||||
clientPackage := config.PackageConfig{
|
||||
Filename: "./client.go",
|
||||
Package: "gen",
|
||||
}
|
||||
|
||||
clientPlugin := clientgen.New(queries, clientPackage)
|
||||
err = api.Generate(cfg,
|
||||
api.AddPlugin(clientPlugin),
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err.Error())
|
||||
os.Exit(3)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Documents
|
||||
|
||||
- [How to configure gqlgen using gqlgen.yml](https://gqlgen.com/config/)
|
||||
- [How to write plugins for gqlgen](https://gqlgen.com/reference/plugins/)
|
||||
|
||||
|
||||
## Comments
|
||||
|
||||
### Japanese Comments
|
||||
These codes have Japanese comments. Replace with English.
|
||||
|
||||
### Subscription
|
||||
|
||||
This client does not support subscription. If you need a subscription, please create an issue or pull request.
|
||||
|
||||
### Pre-conditions
|
||||
|
||||
[clientgen](https://github.com/Yamashou/gqlgenc/tree/master/clientgen) is created based on [modelgen](https://github.com/99designs/gqlgen/tree/master/plugin/modelgen). So if you don't have a modelgen, it may be a mysterious move.
|
||||
88
vendor/github.com/Yamashou/gqlgenc/client/client.go
generated
vendored
Normal file
88
vendor/github.com/Yamashou/gqlgenc/client/client.go
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/Yamashou/gqlgenc/graphqljson"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
type HTTPRequestOption func(req *http.Request)
|
||||
|
||||
type Client struct {
|
||||
Client *http.Client
|
||||
BaseURL string
|
||||
HTTPRequestOptions []HTTPRequestOption
|
||||
}
|
||||
|
||||
// Request represents an outgoing GraphQL request
|
||||
type Request struct {
|
||||
Query string `json:"query"`
|
||||
Variables map[string]interface{} `json:"variables,omitempty"`
|
||||
OperationName string `json:"operationName,omitempty"`
|
||||
}
|
||||
|
||||
func NewClient(client *http.Client, baseURL string, options ...HTTPRequestOption) *Client {
|
||||
return &Client{
|
||||
Client: client,
|
||||
BaseURL: baseURL,
|
||||
HTTPRequestOptions: options,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) newRequest(ctx context.Context, query string, vars map[string]interface{}, httpRequestOptions []HTTPRequestOption) (*http.Request, error) {
|
||||
r := &Request{
|
||||
Query: query,
|
||||
Variables: vars,
|
||||
OperationName: "",
|
||||
}
|
||||
|
||||
requestBody, err := json.Marshal(r)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("encode: %w", err)
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.BaseURL, bytes.NewBuffer(requestBody))
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("create request struct failed: %w", err)
|
||||
}
|
||||
|
||||
for _, httpRequestOption := range c.HTTPRequestOptions {
|
||||
httpRequestOption(req)
|
||||
}
|
||||
for _, httpRequestOption := range httpRequestOptions {
|
||||
httpRequestOption(req)
|
||||
}
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
// Post sends a http POST request to the graphql endpoint with the given query then unpacks
|
||||
// the response into the given object.
|
||||
func (c *Client) Post(ctx context.Context, query string, respData interface{}, vars map[string]interface{}, httpRequestOptions ...HTTPRequestOption) error {
|
||||
req, err := c.newRequest(ctx, query, vars, httpRequestOptions)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("don't create request: %w", err)
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json; charset=utf-8")
|
||||
req.Header.Set("Accept", "application/json; charset=utf-8")
|
||||
|
||||
resp, err := c.Client.Do(req)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("request failed: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if err := graphqljson.Unmarshal(resp.Body, respData); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if resp.StatusCode < 200 || 299 < resp.StatusCode {
|
||||
return xerrors.Errorf("http status code: %v", resp.StatusCode)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
76
vendor/github.com/Yamashou/gqlgenc/clientgen/client.go
generated
vendored
Normal file
76
vendor/github.com/Yamashou/gqlgenc/clientgen/client.go
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
package clientgen
|
||||
|
||||
import (
|
||||
"github.com/99designs/gqlgen/codegen/config"
|
||||
"github.com/99designs/gqlgen/plugin"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
var _ plugin.ConfigMutator = &Plugin{}
|
||||
|
||||
type Plugin struct {
|
||||
queryFilePaths []string
|
||||
Client config.PackageConfig
|
||||
}
|
||||
|
||||
func New(queryFilePaths []string, client config.PackageConfig) *Plugin {
|
||||
return &Plugin{
|
||||
queryFilePaths: queryFilePaths,
|
||||
Client: client,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Plugin) Name() string {
|
||||
return "clientgen"
|
||||
}
|
||||
|
||||
func (p *Plugin) MutateConfig(cfg *config.Config) error {
|
||||
querySources, err := LoadQuerySources(p.queryFilePaths)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("load query sources failed: %w", err)
|
||||
}
|
||||
|
||||
// 1. 全体のqueryDocumentを1度にparse
|
||||
// 1. Parse document from source of query
|
||||
queryDocument, err := ParseQueryDocuments(cfg.Schema, querySources)
|
||||
if err != nil {
|
||||
return xerrors.Errorf(": %w", err)
|
||||
}
|
||||
|
||||
// 2. OperationごとのqueryDocumentを作成
|
||||
// 2. Separate documents for each operation
|
||||
queryDocuments, err := QueryDocumentsByOperations(cfg.Schema, queryDocument.Operations)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("parse query document failed: %w", err)
|
||||
}
|
||||
|
||||
// 3. テンプレートと情報ソースを元にコード生成
|
||||
// 3. Generate code from template and document source
|
||||
sourceGenerator := NewSourceGenerator(cfg, p.Client)
|
||||
source := NewSource(cfg.Schema, queryDocument, sourceGenerator)
|
||||
query, err := source.Query()
|
||||
if err != nil {
|
||||
return xerrors.Errorf("generating query object: %w", err)
|
||||
}
|
||||
|
||||
mutation, err := source.Mutation()
|
||||
if err != nil {
|
||||
return xerrors.Errorf("generating mutation object: %w", err)
|
||||
}
|
||||
|
||||
fragments, err := source.Fragments()
|
||||
if err != nil {
|
||||
return xerrors.Errorf("generating fragment failed: %w", err)
|
||||
}
|
||||
|
||||
operationResponses, err := source.OperationResponses()
|
||||
if err != nil {
|
||||
return xerrors.Errorf("generating operation response failed: %w", err)
|
||||
}
|
||||
|
||||
if err := RenderTemplate(cfg, query, mutation, fragments, source.Operations(queryDocuments), operationResponses, p.Client); err != nil {
|
||||
return xerrors.Errorf("template failed: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
93
vendor/github.com/Yamashou/gqlgenc/clientgen/query.go
generated
vendored
Normal file
93
vendor/github.com/Yamashou/gqlgenc/clientgen/query.go
generated
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
package clientgen
|
||||
|
||||
import (
|
||||
"github.com/vektah/gqlparser/v2/ast"
|
||||
"github.com/vektah/gqlparser/v2/parser"
|
||||
"github.com/vektah/gqlparser/v2/validator"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
func ParseQueryDocuments(schema *ast.Schema, querySources []*ast.Source) (*ast.QueryDocument, error) {
|
||||
var queryDocument ast.QueryDocument
|
||||
for _, querySource := range querySources {
|
||||
query, gqlerr := parser.ParseQuery(querySource)
|
||||
if gqlerr != nil {
|
||||
return nil, xerrors.Errorf(": %w", gqlerr)
|
||||
}
|
||||
|
||||
mergeQueryDocument(&queryDocument, query)
|
||||
}
|
||||
|
||||
if errs := validator.Validate(schema, &queryDocument); errs != nil {
|
||||
return nil, xerrors.Errorf(": %w", errs)
|
||||
}
|
||||
|
||||
return &queryDocument, nil
|
||||
}
|
||||
|
||||
func mergeQueryDocument(q, other *ast.QueryDocument) {
|
||||
q.Operations = append(q.Operations, other.Operations...)
|
||||
q.Fragments = append(q.Fragments, other.Fragments...)
|
||||
}
|
||||
|
||||
func QueryDocumentsByOperations(schema *ast.Schema, operations ast.OperationList) ([]*ast.QueryDocument, error) {
|
||||
queryDocuments := make([]*ast.QueryDocument, 0, len(operations))
|
||||
for _, operation := range operations {
|
||||
fragments := fragmentsInOperationDefinition(operation)
|
||||
|
||||
queryDocument := &ast.QueryDocument{
|
||||
Operations: ast.OperationList{operation},
|
||||
Fragments: fragments,
|
||||
Position: nil,
|
||||
}
|
||||
|
||||
if errs := validator.Validate(schema, queryDocument); errs != nil {
|
||||
return nil, xerrors.Errorf(": %w", errs)
|
||||
}
|
||||
|
||||
queryDocuments = append(queryDocuments, queryDocument)
|
||||
}
|
||||
|
||||
return queryDocuments, nil
|
||||
}
|
||||
|
||||
func fragmentsInOperationDefinition(operation *ast.OperationDefinition) ast.FragmentDefinitionList {
|
||||
fragments := fragmentsInOperationWalker(operation.SelectionSet)
|
||||
uniqueFragments := fragmentsUnique(fragments)
|
||||
|
||||
return uniqueFragments
|
||||
}
|
||||
|
||||
func fragmentsUnique(fragments ast.FragmentDefinitionList) ast.FragmentDefinitionList {
|
||||
uniqueMap := make(map[string]*ast.FragmentDefinition)
|
||||
for _, fragment := range fragments {
|
||||
uniqueMap[fragment.Name] = fragment
|
||||
}
|
||||
|
||||
uniqueFragments := make(ast.FragmentDefinitionList, 0, len(uniqueMap))
|
||||
for _, fragment := range uniqueMap {
|
||||
uniqueFragments = append(uniqueFragments, fragment)
|
||||
}
|
||||
|
||||
return uniqueFragments
|
||||
}
|
||||
|
||||
func fragmentsInOperationWalker(selectionSet ast.SelectionSet) ast.FragmentDefinitionList {
|
||||
var fragments ast.FragmentDefinitionList
|
||||
for _, selection := range selectionSet {
|
||||
var selectionSet ast.SelectionSet
|
||||
switch selection := selection.(type) {
|
||||
case *ast.Field:
|
||||
selectionSet = selection.SelectionSet
|
||||
case *ast.InlineFragment:
|
||||
selectionSet = selection.SelectionSet
|
||||
case *ast.FragmentSpread:
|
||||
fragments = append(fragments, selection.Definition)
|
||||
selectionSet = selection.Definition.SelectionSet
|
||||
}
|
||||
|
||||
fragments = append(fragments, fragmentsInOperationWalker(selectionSet)...)
|
||||
}
|
||||
|
||||
return fragments
|
||||
}
|
||||
106
vendor/github.com/Yamashou/gqlgenc/clientgen/query_source.go
generated
vendored
Normal file
106
vendor/github.com/Yamashou/gqlgenc/clientgen/query_source.go
generated
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
Copyright (c) 2020 gqlgen authors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
package clientgen
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/99designs/gqlgen/codegen/config"
|
||||
"github.com/vektah/gqlparser/v2/ast"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
var path2regex = strings.NewReplacer(
|
||||
`.`, `\.`,
|
||||
`*`, `.+`,
|
||||
`\`, `[\\/]`,
|
||||
`/`, `[\\/]`,
|
||||
)
|
||||
|
||||
// LoadQuerySourceなどは、gqlgenがLoadConfigでSchemaを読み込む時の実装をコピーして一部修正している
|
||||
// **/test/*.graphqlなどに対応している
|
||||
func LoadQuerySources(queryFileNames []string) ([]*ast.Source, error) {
|
||||
var noGlobQueryFileNames config.StringList
|
||||
|
||||
var err error
|
||||
preGlobbing := queryFileNames
|
||||
for _, f := range preGlobbing {
|
||||
var matches []string
|
||||
|
||||
// for ** we want to override default globbing patterns and walk all
|
||||
// subdirectories to match schema files.
|
||||
if strings.Contains(f, "**") {
|
||||
pathParts := strings.SplitN(f, "**", 2)
|
||||
rest := strings.TrimPrefix(strings.TrimPrefix(pathParts[1], `\`), `/`)
|
||||
// turn the rest of the glob into a regex, anchored only at the end because ** allows
|
||||
// for any number of dirs in between and walk will let us match against the full path name
|
||||
globRe := regexp.MustCompile(path2regex.Replace(rest) + `$`)
|
||||
|
||||
if err := filepath.Walk(pathParts[0], func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if globRe.MatchString(strings.TrimPrefix(path, pathParts[0])) {
|
||||
matches = append(matches, path)
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, xerrors.Errorf("failed to walk schema at root: %w", pathParts[0])
|
||||
}
|
||||
} else {
|
||||
matches, err = filepath.Glob(f)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to glob schema filename %v: %w", f, err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, m := range matches {
|
||||
if noGlobQueryFileNames.Has(m) {
|
||||
continue
|
||||
}
|
||||
|
||||
noGlobQueryFileNames = append(noGlobQueryFileNames, m)
|
||||
}
|
||||
}
|
||||
|
||||
querySources := make([]*ast.Source, 0, len(noGlobQueryFileNames))
|
||||
for _, filename := range noGlobQueryFileNames {
|
||||
filename = filepath.ToSlash(filename)
|
||||
var err error
|
||||
var schemaRaw []byte
|
||||
schemaRaw, err = ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("unable to open schema: %w", err)
|
||||
}
|
||||
|
||||
querySources = append(querySources, &ast.Source{Name: filename, Input: string(schemaRaw)})
|
||||
}
|
||||
|
||||
return querySources, nil
|
||||
}
|
||||
193
vendor/github.com/Yamashou/gqlgenc/clientgen/source.go
generated
vendored
Normal file
193
vendor/github.com/Yamashou/gqlgenc/clientgen/source.go
generated
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
package clientgen
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/types"
|
||||
|
||||
"github.com/99designs/gqlgen/codegen/templates"
|
||||
"github.com/vektah/gqlparser/v2/ast"
|
||||
"github.com/vektah/gqlparser/v2/formatter"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
type Source struct {
|
||||
schema *ast.Schema
|
||||
queryDocument *ast.QueryDocument
|
||||
sourceGenerator *SourceGenerator
|
||||
}
|
||||
|
||||
func NewSource(schema *ast.Schema, queryDocument *ast.QueryDocument, sourceGenerator *SourceGenerator) *Source {
|
||||
return &Source{
|
||||
schema: schema,
|
||||
queryDocument: queryDocument,
|
||||
sourceGenerator: sourceGenerator,
|
||||
}
|
||||
}
|
||||
|
||||
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, xerrors.New(fmt.Sprintf("%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) *Operation {
|
||||
return &Operation{
|
||||
Name: operation.Name,
|
||||
ResponseStructName: getResponseStructName(operation),
|
||||
Operation: queryString(queryDocument),
|
||||
Args: args,
|
||||
VariableDefinitions: operation.VariableDefinitions,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Source) Operations(queryDocuments []*ast.QueryDocument) []*Operation {
|
||||
operations := make([]*Operation, 0, len(s.queryDocument.Operations))
|
||||
|
||||
queryDocumentsMap := queryDocumentMapByOperationName(queryDocuments)
|
||||
operationArgsMap := s.operationArgsMapByOperationName()
|
||||
for _, operation := range s.queryDocument.Operations {
|
||||
queryDocument := queryDocumentsMap[operation.Name]
|
||||
args := operationArgsMap[operation.Name]
|
||||
operations = append(operations, NewOperation(
|
||||
operation,
|
||||
queryDocument,
|
||||
args,
|
||||
))
|
||||
}
|
||||
|
||||
return operations
|
||||
}
|
||||
|
||||
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)
|
||||
if s.sourceGenerator.cfg.Models.Exists(name) {
|
||||
return nil, xerrors.New(fmt.Sprintf("%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, xerrors.Errorf("generate failed for query struct type : %w", err)
|
||||
}
|
||||
|
||||
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) {
|
||||
fields, err := s.sourceGenerator.NewResponseFieldsByDefinition(s.schema.Mutation)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("generate failed for mutation struct type : %w", err)
|
||||
}
|
||||
|
||||
return &Mutation{
|
||||
Name: s.schema.Mutation.Name,
|
||||
Type: fields.StructType(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getResponseStructName(operation *ast.OperationDefinition) string {
|
||||
if operation.Operation == ast.Mutation {
|
||||
return fmt.Sprintf("%sPayload", operation.Name)
|
||||
}
|
||||
|
||||
return operation.Name
|
||||
}
|
||||
204
vendor/github.com/Yamashou/gqlgenc/clientgen/source_generator.go
generated
vendored
Normal file
204
vendor/github.com/Yamashou/gqlgenc/clientgen/source_generator.go
generated
vendored
Normal file
@@ -0,0 +1,204 @@
|
||||
package clientgen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/types"
|
||||
"strings"
|
||||
|
||||
"github.com/99designs/gqlgen/codegen/config"
|
||||
"github.com/99designs/gqlgen/codegen/templates"
|
||||
"github.com/vektah/gqlparser/v2/ast"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
type Argument struct {
|
||||
Variable string
|
||||
Type types.Type
|
||||
}
|
||||
|
||||
type ResponseField struct {
|
||||
Name string
|
||||
IsFragmentSpread bool
|
||||
IsInlineFragment bool
|
||||
Type types.Type
|
||||
Tags []string
|
||||
ResponseFields ResponseFieldList
|
||||
}
|
||||
|
||||
type ResponseFieldList []*ResponseField
|
||||
|
||||
func (rs ResponseFieldList) StructType() *types.Struct {
|
||||
vars := make([]*types.Var, 0)
|
||||
structTags := make([]string, 0)
|
||||
for _, filed := range rs {
|
||||
// クエリーのフィールドの子階層がFragmentの場合、このフィールドにそのFragmentの型を追加する
|
||||
if filed.IsFragmentSpread {
|
||||
typ := filed.ResponseFields.StructType().Underlying().(*types.Struct)
|
||||
for j := 0; j < typ.NumFields(); j++ {
|
||||
vars = append(vars, typ.Field(j))
|
||||
structTags = append(structTags, typ.Tag(j))
|
||||
}
|
||||
} else {
|
||||
vars = append(vars, types.NewVar(0, nil, templates.ToGo(filed.Name), filed.Type))
|
||||
structTags = append(structTags, strings.Join(filed.Tags, " "))
|
||||
}
|
||||
}
|
||||
|
||||
return types.NewStruct(vars, structTags)
|
||||
}
|
||||
|
||||
func (rs ResponseFieldList) IsFragment() bool {
|
||||
if len(rs) != 1 {
|
||||
return false
|
||||
}
|
||||
|
||||
return rs[0].IsInlineFragment || rs[0].IsFragmentSpread
|
||||
}
|
||||
|
||||
func (rs ResponseFieldList) IsBasicType() bool {
|
||||
return len(rs) == 0
|
||||
}
|
||||
|
||||
func (rs ResponseFieldList) IsStructType() bool {
|
||||
return len(rs) > 0 && !rs.IsFragment()
|
||||
}
|
||||
|
||||
type SourceGenerator struct {
|
||||
cfg *config.Config
|
||||
binder *config.Binder
|
||||
client config.PackageConfig
|
||||
}
|
||||
|
||||
func NewSourceGenerator(cfg *config.Config, client config.PackageConfig) *SourceGenerator {
|
||||
return &SourceGenerator{
|
||||
cfg: cfg,
|
||||
binder: cfg.NewBinder(),
|
||||
client: client,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *SourceGenerator) NewResponseFields(selectionSet ast.SelectionSet) ResponseFieldList {
|
||||
responseFields := make(ResponseFieldList, 0, len(selectionSet))
|
||||
for _, selection := range selectionSet {
|
||||
responseFields = append(responseFields, r.NewResponseField(selection))
|
||||
}
|
||||
|
||||
return responseFields
|
||||
}
|
||||
|
||||
func (r *SourceGenerator) NewResponseFieldsByDefinition(definition *ast.Definition) (ResponseFieldList, error) {
|
||||
fields := make(ResponseFieldList, 0, len(definition.Fields))
|
||||
for _, field := range definition.Fields {
|
||||
if field.Type.Name() == "__Schema" || field.Type.Name() == "__Type" {
|
||||
continue
|
||||
}
|
||||
typ, err := r.binder.FindTypeFromName(r.cfg.Models[field.Type.Name()].Model[0])
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("not found type: %w", err)
|
||||
}
|
||||
tags := []string{
|
||||
fmt.Sprintf(`json:"%s"`, field.Name),
|
||||
fmt.Sprintf(`graphql:"%s"`, field.Name),
|
||||
}
|
||||
|
||||
fields = append(fields, &ResponseField{
|
||||
Name: field.Name,
|
||||
Type: r.binder.CopyModifiersFromAst(field.Type, typ),
|
||||
Tags: tags,
|
||||
})
|
||||
}
|
||||
|
||||
return fields, nil
|
||||
}
|
||||
|
||||
func (r *SourceGenerator) NewResponseField(selection ast.Selection) *ResponseField {
|
||||
switch selection := selection.(type) {
|
||||
case *ast.Field:
|
||||
fieldsResponseFields := r.NewResponseFields(selection.SelectionSet)
|
||||
|
||||
var baseType types.Type
|
||||
switch {
|
||||
case fieldsResponseFields.IsBasicType():
|
||||
baseType = r.Type(selection.Definition.Type.Name())
|
||||
case fieldsResponseFields.IsFragment():
|
||||
// 子フィールドがFragmentの場合はこのFragmentがフィールドの型になる
|
||||
// if a child field is fragment, this field type became fragment.
|
||||
baseType = fieldsResponseFields[0].Type
|
||||
case fieldsResponseFields.IsStructType():
|
||||
baseType = fieldsResponseFields.StructType()
|
||||
default:
|
||||
// ここにきたらバグ
|
||||
// here is bug
|
||||
panic("not match type")
|
||||
}
|
||||
|
||||
// GraphQLの定義がオプショナルのはtypeのポインタ型が返り、配列の定義場合はポインタのスライスの型になって返ってきます
|
||||
// return pointer type then optional type or slice pointer then slice type of definition in GraphQL.
|
||||
typ := r.binder.CopyModifiersFromAst(selection.Definition.Type, baseType)
|
||||
|
||||
tags := []string{
|
||||
fmt.Sprintf(`json:"%s"`, selection.Alias),
|
||||
fmt.Sprintf(`graphql:"%s"`, selection.Alias),
|
||||
}
|
||||
|
||||
return &ResponseField{
|
||||
Name: selection.Alias,
|
||||
Type: typ,
|
||||
Tags: tags,
|
||||
ResponseFields: fieldsResponseFields,
|
||||
}
|
||||
|
||||
case *ast.FragmentSpread:
|
||||
// この構造体はテンプレート側で使われることはなく、ast.FieldでFragment判定するために使用する
|
||||
fieldsResponseFields := r.NewResponseFields(selection.Definition.SelectionSet)
|
||||
typ := types.NewNamed(
|
||||
types.NewTypeName(0, r.client.Pkg(), templates.ToGo(selection.Name), nil),
|
||||
fieldsResponseFields.StructType(),
|
||||
nil,
|
||||
)
|
||||
|
||||
return &ResponseField{
|
||||
Name: selection.Name,
|
||||
Type: typ,
|
||||
IsFragmentSpread: true,
|
||||
ResponseFields: fieldsResponseFields,
|
||||
}
|
||||
|
||||
case *ast.InlineFragment:
|
||||
// InlineFragmentは子要素をそのままstructとしてもつので、ここで、構造体の型を作成します
|
||||
fieldsResponseFields := r.NewResponseFields(selection.SelectionSet)
|
||||
|
||||
return &ResponseField{
|
||||
Name: selection.TypeCondition,
|
||||
Type: fieldsResponseFields.StructType(),
|
||||
IsInlineFragment: true,
|
||||
Tags: []string{fmt.Sprintf(`graphql:"... on %s"`, selection.TypeCondition)},
|
||||
ResponseFields: fieldsResponseFields,
|
||||
}
|
||||
}
|
||||
|
||||
panic("unexpected selection type")
|
||||
}
|
||||
|
||||
func (r *SourceGenerator) OperationArguments(variableDefinitions ast.VariableDefinitionList) []*Argument {
|
||||
argumentTypes := make([]*Argument, 0, len(variableDefinitions))
|
||||
for _, v := range variableDefinitions {
|
||||
argumentTypes = append(argumentTypes, &Argument{
|
||||
Variable: v.Variable,
|
||||
Type: r.binder.CopyModifiersFromAst(v.Type, r.Type(v.Type.Name())),
|
||||
})
|
||||
}
|
||||
|
||||
return argumentTypes
|
||||
}
|
||||
|
||||
// Typeの引数に渡すtypeNameは解析した結果からselectionなどから求めた型の名前を渡さなければいけない
|
||||
func (r *SourceGenerator) Type(typeName string) types.Type {
|
||||
goType, err := r.binder.FindTypeFromName(r.cfg.Models[typeName].Model[0])
|
||||
if err != nil {
|
||||
// 実装として正しいtypeNameを渡していれば必ず見つかるはずなのでpanic
|
||||
panic(fmt.Sprintf("%+v", err))
|
||||
}
|
||||
|
||||
return goType
|
||||
}
|
||||
27
vendor/github.com/Yamashou/gqlgenc/clientgen/template.go
generated
vendored
Normal file
27
vendor/github.com/Yamashou/gqlgenc/clientgen/template.go
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
package clientgen
|
||||
|
||||
import (
|
||||
"github.com/99designs/gqlgen/codegen/config"
|
||||
"github.com/99designs/gqlgen/codegen/templates"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
func RenderTemplate(cfg *config.Config, query *Query, mutation *Mutation, fragments []*Fragment, operations []*Operation, operationResponses []*OperationResponse, client config.PackageConfig) error {
|
||||
if err := templates.Render(templates.Options{
|
||||
PackageName: client.Package,
|
||||
Filename: client.Filename,
|
||||
Data: map[string]interface{}{
|
||||
"Query": query,
|
||||
"Mutation": mutation,
|
||||
"Fragment": fragments,
|
||||
"Operation": operations,
|
||||
"OperationResponse": operationResponses,
|
||||
},
|
||||
Packages: cfg.Packages,
|
||||
PackageDoc: "// Code generated by github.com/Yamashou/gqlgenc, DO NOT EDIT.\n",
|
||||
}); err != nil {
|
||||
return xerrors.Errorf("%s generating failed: %w", client.Filename, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
54
vendor/github.com/Yamashou/gqlgenc/clientgen/template.gotpl
generated
vendored
Normal file
54
vendor/github.com/Yamashou/gqlgenc/clientgen/template.gotpl
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
{{ reserveImport "bytes" }}
|
||||
{{ reserveImport "context" }}
|
||||
{{ reserveImport "encoding/json" }}
|
||||
{{ reserveImport "fmt" }}
|
||||
{{ reserveImport "io" }}
|
||||
{{ reserveImport "io/ioutil" }}
|
||||
{{ reserveImport "net/http" }}
|
||||
{{ reserveImport "net/url" }}
|
||||
{{ reserveImport "path" }}
|
||||
{{ reserveImport "time" }}
|
||||
|
||||
{{ reserveImport "golang.org/x/xerrors" }}
|
||||
|
||||
{{ reserveImport "github.com/Yamashou/gqlgenc/graphqljson" }}
|
||||
{{ reserveImport "github.com/Yamashou/gqlgenc/client" }}
|
||||
|
||||
type Client struct {
|
||||
Client *client.Client
|
||||
}
|
||||
|
||||
func NewClient(cli *http.Client, baseURL string, options ...client.HTTPRequestOption) *Client {
|
||||
return &Client{Client: client.NewClient(cli, baseURL, options...)}
|
||||
}
|
||||
|
||||
type {{ .Query.Name | go }} {{ .Query.Type | ref }}
|
||||
|
||||
type {{ .Mutation.Name | go }} {{ .Mutation.Type | ref }}
|
||||
|
||||
{{- range $name, $element := .Fragment }}
|
||||
type {{ .Name | go }} {{ .Type | ref }}
|
||||
{{- end }}
|
||||
|
||||
{{- range $name, $element := .OperationResponse }}
|
||||
type {{ .Name | go }} {{ .Type | ref }}
|
||||
{{- end }}
|
||||
|
||||
{{- range $model := .Operation}}
|
||||
const {{ $model.Name|go }}Query = `{{ $model.Operation }}`
|
||||
|
||||
func (c *Client) {{ $model.Name|go }} (ctx context.Context{{- range $arg := .Args }}, {{ $arg.Variable | goPrivate }} {{ $arg.Type | ref }} {{- end }}, httpRequestOptions ...client.HTTPRequestOption) (*{{ $model.ResponseStructName | go }}, error) {
|
||||
vars := map[string]interface{}{
|
||||
{{- range $args := .VariableDefinitions}}
|
||||
"{{ $args.Variable }}": {{ $args.Variable | goPrivate }},
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
var res {{ $model.ResponseStructName | go }}
|
||||
if err := c.Client.Post(ctx, {{ $model.Name|go }}Query, &res, vars, httpRequestOptions...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &res, nil
|
||||
}
|
||||
{{- end}}
|
||||
123
vendor/github.com/Yamashou/gqlgenc/config/config.go
generated
vendored
Normal file
123
vendor/github.com/Yamashou/gqlgenc/config/config.go
generated
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/99designs/gqlgen/codegen/config"
|
||||
"github.com/Yamashou/gqlgenc/client"
|
||||
"github.com/Yamashou/gqlgenc/introspection"
|
||||
"github.com/vektah/gqlparser/v2/ast"
|
||||
"github.com/vektah/gqlparser/v2/validator"
|
||||
"golang.org/x/xerrors"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Model config.PackageConfig `yaml:"model,omitempty"`
|
||||
Client config.PackageConfig `yaml:"client,omitempty"`
|
||||
Models config.TypeMap `yaml:"models,omitempty"`
|
||||
Endpoint EndPointConfig `yaml:"endpoint"`
|
||||
Query []string `yaml:"query"`
|
||||
|
||||
// gqlgen config struct
|
||||
GQLConfig *config.Config `yaml:"-"`
|
||||
}
|
||||
|
||||
type EndPointConfig struct {
|
||||
URL string `yaml:"url"`
|
||||
Headers map[string]string `yaml:"headers,omitempty"`
|
||||
}
|
||||
|
||||
func findCfg(fileName string) (string, error) {
|
||||
dir, err := os.Getwd()
|
||||
if err != nil {
|
||||
return "", xerrors.Errorf("unable to get working dir to findCfg: %w", err)
|
||||
}
|
||||
|
||||
cfg := findCfgInDir(dir, fileName)
|
||||
|
||||
if cfg == "" {
|
||||
return "", os.ErrNotExist
|
||||
}
|
||||
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func findCfgInDir(dir, fileName string) string {
|
||||
path := filepath.Join(dir, fileName)
|
||||
|
||||
return path
|
||||
}
|
||||
|
||||
func LoadConfig(filename string) (*Config, error) {
|
||||
var cfg Config
|
||||
file, err := findCfg(filename)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("unable to get file path: %w", err)
|
||||
}
|
||||
b, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("unable to read config: %w", err)
|
||||
}
|
||||
|
||||
confContent := []byte(os.ExpandEnv(string(b)))
|
||||
if err := yaml.UnmarshalStrict(confContent, &cfg); err != nil {
|
||||
return nil, xerrors.Errorf("unable to parse config: %w", err)
|
||||
}
|
||||
|
||||
cfg.GQLConfig = &config.Config{
|
||||
Model: cfg.Model,
|
||||
Models: cfg.Models,
|
||||
// TODO: gqlgen must be set exec but client not used
|
||||
Exec: config.PackageConfig{Filename: "generated.go"},
|
||||
Directives: map[string]config.DirectiveConfig{},
|
||||
}
|
||||
|
||||
if err := cfg.Client.Check(); err != nil {
|
||||
return nil, xerrors.Errorf("config.exec: %w", err)
|
||||
}
|
||||
|
||||
return &cfg, nil
|
||||
}
|
||||
|
||||
func (c *Config) LoadSchema(ctx context.Context) error {
|
||||
addHeader := func(req *http.Request) {
|
||||
for key, value := range c.Endpoint.Headers {
|
||||
req.Header.Set(key, value)
|
||||
}
|
||||
}
|
||||
gqlclient := client.NewClient(http.DefaultClient, c.Endpoint.URL, addHeader)
|
||||
schema, err := LoadRemoteSchema(ctx, gqlclient)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("load remote schema failed: %w", err)
|
||||
}
|
||||
if schema.Query == nil {
|
||||
schema.Query = &ast.Definition{
|
||||
Kind: ast.Object,
|
||||
Name: "Query",
|
||||
}
|
||||
schema.Types["Query"] = schema.Query
|
||||
}
|
||||
|
||||
c.GQLConfig.Schema = schema
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func LoadRemoteSchema(ctx context.Context, gqlclient *client.Client) (*ast.Schema, error) {
|
||||
var res introspection.Query
|
||||
if err := gqlclient.Post(ctx, introspection.Introspection, &res, nil); err != nil {
|
||||
return nil, xerrors.Errorf("introspection query failed: %w", err)
|
||||
}
|
||||
|
||||
schema, err := validator.ValidateSchemaDocument(introspection.ParseIntrospectionQuery(res))
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("validation error: %w", err)
|
||||
}
|
||||
|
||||
return schema, nil
|
||||
}
|
||||
40
vendor/github.com/Yamashou/gqlgenc/generator/generater.go
generated
vendored
Normal file
40
vendor/github.com/Yamashou/gqlgenc/generator/generater.go
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
package generator
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/99designs/gqlgen/api"
|
||||
"github.com/99designs/gqlgen/plugin"
|
||||
"github.com/99designs/gqlgen/plugin/modelgen"
|
||||
"github.com/Yamashou/gqlgenc/config"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
func Generate(ctx context.Context, cfg *config.Config, option ...api.Option) error {
|
||||
var plugins []plugin.Plugin
|
||||
if cfg.Model.IsDefined() {
|
||||
plugins = append(plugins, modelgen.New())
|
||||
}
|
||||
for _, o := range option {
|
||||
o(cfg.GQLConfig, &plugins)
|
||||
}
|
||||
|
||||
if err := cfg.LoadSchema(ctx); err != nil {
|
||||
return xerrors.Errorf("failed to load schema: %w\n", err)
|
||||
}
|
||||
|
||||
if err := cfg.GQLConfig.Init(); err != nil {
|
||||
return xerrors.Errorf("generating core failed: %w\n", err)
|
||||
}
|
||||
|
||||
for _, p := range plugins {
|
||||
if mut, ok := p.(plugin.ConfigMutator); ok {
|
||||
err := mut.MutateConfig(cfg.GQLConfig)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("%s failed: %w\n", p.Name(), err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
14
vendor/github.com/Yamashou/gqlgenc/go.mod
generated
vendored
Normal file
14
vendor/github.com/Yamashou/gqlgenc/go.mod
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
module github.com/Yamashou/gqlgenc
|
||||
|
||||
go 1.14
|
||||
|
||||
require (
|
||||
github.com/99designs/gqlgen v0.12.2
|
||||
github.com/agnivade/levenshtein v1.1.0 // indirect
|
||||
github.com/google/go-cmp v0.5.2
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/vektah/gqlparser/v2 v2.0.1
|
||||
golang.org/x/tools v0.0.0-20200827163409-021d7c6f1ec3 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1
|
||||
gopkg.in/yaml.v2 v2.3.0
|
||||
)
|
||||
122
vendor/github.com/Yamashou/gqlgenc/go.sum
generated
vendored
Normal file
122
vendor/github.com/Yamashou/gqlgenc/go.sum
generated
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
github.com/99designs/gqlgen v0.12.2 h1:aOdpsiCycFtCnAv8CAI1exnKrIDHMqtMzQoXeTziY4o=
|
||||
github.com/99designs/gqlgen v0.12.2/go.mod h1:7zdGo6ry9u1YBp/qlb2uxSU5Mt2jQKLcBETQiKk+Bxo=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/agnivade/levenshtein v1.0.1 h1:3oJU7J3FGFmyhn8KHjmVaZCN5hxTr7GxgRue+sxIXdQ=
|
||||
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
|
||||
github.com/agnivade/levenshtein v1.0.3 h1:M5ZnqLOoZR8ygVq0FfkXsNOKzMCk0xRiow0R5+5VkQ0=
|
||||
github.com/agnivade/levenshtein v1.0.3/go.mod h1:4SFRZbbXWLF4MU1T9Qg0pGgH3Pjs+t6ie5efyrwRJXs=
|
||||
github.com/agnivade/levenshtein v1.1.0 h1:n6qGwyHG61v3ABce1rPVZklEYRT8NFpCMrpZdBUbYGM=
|
||||
github.com/agnivade/levenshtein v1.1.0/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=
|
||||
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
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/dgryski/trifles v0.0.0-20190318185328-a8d75aae118c h1:TUuUh0Xgj97tLMNtWtNvI9mIV6isjEb9lBMNv+77IGM=
|
||||
github.com/dgryski/trifles v0.0.0-20190318185328-a8d75aae118c/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA=
|
||||
github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 h1:fRzb/w+pyskVMQ+UbP35JkH8yB7MYb4q/qhBarqZE6g=
|
||||
github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA=
|
||||
github.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
||||
github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||
github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007 h1:reVOUXwnhsYv/8UqjvhrMOu5CNT9UapHFLbQ2JcXsmg=
|
||||
github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047 h1:zCoDWFD5nrJJVjbXiDZcVhOBSzKn3o9LgRLLMRNuru8=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
|
||||
github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg=
|
||||
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
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/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/urfave/cli/v2 v2.1.1 h1:Qt8FeAtxE/vfdrLmR3rxR6JRE0RoVmbXu8+6kZtYU4k=
|
||||
github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
|
||||
github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e h1:+w0Zm/9gaWpEAyDlU1eKOuk5twTjAjuevXqcJJw8hrg=
|
||||
github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U=
|
||||
github.com/vektah/gqlparser v1.3.1 h1:8b0IcD3qZKWJQHSzynbDlrtP3IxVydZ2DZepCGofqfU=
|
||||
github.com/vektah/gqlparser v1.3.1/go.mod h1:bkVf0FX+Stjg/MHnm8mEyubuaArhNEqfQhF+OTiAL74=
|
||||
github.com/vektah/gqlparser/v2 v2.0.1 h1:xgl5abVnsd4hkN9rk65OJID9bfcLSMuTaTcZj777q1o=
|
||||
github.com/vektah/gqlparser/v2 v2.0.1/go.mod h1:SyUiHgLATUR8BiYURfTirrTcGpcE+4XkV2se04Px1Ms=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200114235610-7ae403b6b589 h1:rjUrONFu4kLchcZTfp3/96bR8bW8dIa8uz3cR5n0cgM=
|
||||
golang.org/x/tools v0.0.0-20200114235610-7ae403b6b589/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200827163409-021d7c6f1ec3 h1:OjYQxZBKJFs+sJbHkvSGIKNMkZXDJQ9JsMpebGhkafI=
|
||||
golang.org/x/tools v0.0.0-20200827163409-021d7c6f1ec3/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
sourcegraph.com/sourcegraph/appdash v0.0.0-20180110180208-2cc67fd64755/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
|
||||
sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67/go.mod h1:L5q+DGLGOQFpo1snNEkLOJT2d1YTW66rWNzatr3He1k=
|
||||
416
vendor/github.com/Yamashou/gqlgenc/graphqljson/graphql.go
generated
vendored
Normal file
416
vendor/github.com/Yamashou/gqlgenc/graphqljson/graphql.go
generated
vendored
Normal file
@@ -0,0 +1,416 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Dmitri Shuralyov
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
// Package jsonutil provides a function for decoding JSON
|
||||
// into a GraphQL query data structure.
|
||||
package graphqljson
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
// Reference: https://blog.gopheracademy.com/advent-2017/custom-json-unmarshaler-for-graphql-client/
|
||||
|
||||
// RawJSONError is a json formatted error from a GraphQL server.
|
||||
type RawJSONError struct {
|
||||
Response
|
||||
}
|
||||
|
||||
func (r RawJSONError) Error() string {
|
||||
return fmt.Sprintf("data: %s, error: %s, extensions: %v", r.Data, r.Errors, r.Extensions)
|
||||
}
|
||||
|
||||
// Response is a GraphQL layer response from a handler.
|
||||
type Response struct {
|
||||
Data json.RawMessage
|
||||
Errors Errors
|
||||
Extensions map[string]interface{}
|
||||
}
|
||||
|
||||
func Unmarshal(r io.Reader, data interface{}) error {
|
||||
resp := Response{}
|
||||
decoder := json.NewDecoder(r)
|
||||
if err := decoder.Decode(&resp); err != nil {
|
||||
var buf bytes.Buffer
|
||||
if _, e := io.Copy(&buf, decoder.Buffered()); e != nil {
|
||||
return xerrors.Errorf(": %w", err)
|
||||
}
|
||||
|
||||
return xerrors.Errorf("%s", buf.String())
|
||||
}
|
||||
|
||||
if len(resp.Errors) > 0 {
|
||||
return xerrors.Errorf("response error: %w", resp.Errors)
|
||||
}
|
||||
|
||||
if err := UnmarshalData(resp.Data, data); err != nil {
|
||||
return xerrors.Errorf("response mapping failed: %w", err)
|
||||
}
|
||||
|
||||
if resp.Errors != nil {
|
||||
return RawJSONError{resp}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmarshalGraphQL parses the JSON-encoded GraphQL response data and stores
|
||||
// the result in the GraphQL query data structure pointed to by v.
|
||||
//
|
||||
// The implementation is created on top of the JSON tokenizer available
|
||||
// in "encoding/json".Decoder.
|
||||
func UnmarshalData(data json.RawMessage, v interface{}) error {
|
||||
d := NewDecoder(bytes.NewBuffer(data))
|
||||
if err := d.Decode(v); err != nil {
|
||||
return xerrors.Errorf(": %w", err)
|
||||
}
|
||||
|
||||
// TODO: この処理が本当に必要かは今後検討
|
||||
tok, err := d.jsonDecoder.Token()
|
||||
switch err {
|
||||
case io.EOF:
|
||||
// Expect to get io.EOF. There shouldn't be any more
|
||||
// tokens left after we've decoded v successfully.
|
||||
return nil
|
||||
case nil:
|
||||
return xerrors.Errorf("invalid token '%v' after top-level value", tok)
|
||||
}
|
||||
|
||||
return xerrors.Errorf("invalid token '%v' after top-level value", tok)
|
||||
}
|
||||
|
||||
// decoder is a JSON decoder that performs custom unmarshaling behavior
|
||||
// for GraphQL query data structures. It's implemented on top of a JSON tokenizer.
|
||||
type Decoder struct {
|
||||
jsonDecoder *json.Decoder
|
||||
|
||||
// Stack of what part of input JSON we're in the middle of - objects, arrays.
|
||||
parseState []json.Delim
|
||||
|
||||
// Stacks of values where to unmarshal.
|
||||
// The top of each stack is the reflect.Value where to unmarshal next JSON value.
|
||||
//
|
||||
// The reason there's more than one stack is because we might be unmarshaling
|
||||
// a single JSON value into multiple GraphQL fragments or embedded structs, so
|
||||
// we keep track of them all.
|
||||
vs [][]reflect.Value
|
||||
}
|
||||
|
||||
func NewDecoder(r io.Reader) *Decoder {
|
||||
jsonDecoder := json.NewDecoder(r)
|
||||
jsonDecoder.UseNumber()
|
||||
|
||||
return &Decoder{
|
||||
jsonDecoder: jsonDecoder,
|
||||
}
|
||||
}
|
||||
|
||||
// Decode decodes a single JSON value from d.tokenizer into v.
|
||||
func (d *Decoder) Decode(v interface{}) error {
|
||||
rv := reflect.ValueOf(v)
|
||||
if rv.Kind() != reflect.Ptr {
|
||||
return xerrors.Errorf("cannot decode into non-pointer %T", v)
|
||||
}
|
||||
|
||||
d.vs = [][]reflect.Value{{rv.Elem()}}
|
||||
if err := d.decode(); err != nil {
|
||||
return xerrors.Errorf(": %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// decode decodes a single JSON value from d.tokenizer into d.vs.
|
||||
func (d *Decoder) decode() error {
|
||||
// The loop invariant is that the top of each d.vs stack
|
||||
// is where we try to unmarshal the next JSON value we see.
|
||||
for len(d.vs) > 0 {
|
||||
tok, err := d.jsonDecoder.Token()
|
||||
if err == io.EOF {
|
||||
return xerrors.New("unexpected end of JSON input")
|
||||
} else if err != nil {
|
||||
return xerrors.Errorf(": %w", err)
|
||||
}
|
||||
|
||||
switch {
|
||||
// Are we inside an object and seeing next key (rather than end of object)?
|
||||
case d.state() == '{' && tok != json.Delim('}'):
|
||||
key, ok := tok.(string)
|
||||
if !ok {
|
||||
return xerrors.New("unexpected non-key in JSON input")
|
||||
}
|
||||
|
||||
someFieldExist := false
|
||||
for i := range d.vs {
|
||||
v := d.vs[i][len(d.vs[i])-1]
|
||||
if v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
var f reflect.Value
|
||||
if v.Kind() == reflect.Struct {
|
||||
f = fieldByGraphQLName(v, key)
|
||||
if f.IsValid() {
|
||||
someFieldExist = true
|
||||
}
|
||||
}
|
||||
d.vs[i] = append(d.vs[i], f)
|
||||
}
|
||||
if !someFieldExist {
|
||||
return xerrors.Errorf("struct field for %q doesn't exist in any of %v places to unmarshal", key, len(d.vs))
|
||||
}
|
||||
|
||||
// We've just consumed the current token, which was the key.
|
||||
// Read the next token, which should be the value, and let the rest of code process it.
|
||||
tok, err = d.jsonDecoder.Token()
|
||||
if err == io.EOF {
|
||||
return xerrors.New("unexpected end of JSON input")
|
||||
} else if err != nil {
|
||||
return xerrors.Errorf(": %w", err)
|
||||
}
|
||||
|
||||
// Are we inside an array and seeing next value (rather than end of array)?
|
||||
case d.state() == '[' && tok != json.Delim(']'):
|
||||
someSliceExist := false
|
||||
for i := range d.vs {
|
||||
v := d.vs[i][len(d.vs[i])-1]
|
||||
if v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
var f reflect.Value
|
||||
if v.Kind() == reflect.Slice {
|
||||
v.Set(reflect.Append(v, reflect.Zero(v.Type().Elem()))) // v = append(v, T).
|
||||
f = v.Index(v.Len() - 1)
|
||||
someSliceExist = true
|
||||
}
|
||||
d.vs[i] = append(d.vs[i], f)
|
||||
}
|
||||
if !someSliceExist {
|
||||
return xerrors.Errorf("slice doesn't exist in any of %v places to unmarshal", len(d.vs))
|
||||
}
|
||||
}
|
||||
|
||||
switch tok := tok.(type) {
|
||||
case string, json.Number, bool, nil:
|
||||
// Value.
|
||||
|
||||
for i := range d.vs {
|
||||
v := d.vs[i][len(d.vs[i])-1]
|
||||
if !v.IsValid() {
|
||||
continue
|
||||
}
|
||||
err := unmarshalValue(tok, v)
|
||||
if err != nil {
|
||||
return xerrors.Errorf(": %w", err)
|
||||
}
|
||||
}
|
||||
d.popAllVs()
|
||||
|
||||
case json.Delim:
|
||||
switch tok {
|
||||
case '{':
|
||||
// Start of object.
|
||||
|
||||
d.pushState(tok)
|
||||
|
||||
frontier := make([]reflect.Value, len(d.vs)) // Places to look for GraphQL fragments/embedded structs.
|
||||
for i := range d.vs {
|
||||
v := d.vs[i][len(d.vs[i])-1]
|
||||
frontier[i] = v
|
||||
// TODO: Do this recursively or not? Add a test case if needed.
|
||||
if v.Kind() == reflect.Ptr && v.IsNil() {
|
||||
v.Set(reflect.New(v.Type().Elem())) // v = new(T).
|
||||
}
|
||||
}
|
||||
// Find GraphQL fragments/embedded structs recursively, adding to frontier
|
||||
// as new ones are discovered and exploring them further.
|
||||
for len(frontier) > 0 {
|
||||
v := frontier[0]
|
||||
frontier = frontier[1:]
|
||||
if v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
if v.Kind() != reflect.Struct {
|
||||
continue
|
||||
}
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
if isGraphQLFragment(v.Type().Field(i)) || v.Type().Field(i).Anonymous {
|
||||
// Add GraphQL fragment or embedded struct.
|
||||
d.vs = append(d.vs, []reflect.Value{v.Field(i)})
|
||||
frontier = append(frontier, v.Field(i))
|
||||
}
|
||||
}
|
||||
}
|
||||
case '[':
|
||||
// Start of array.
|
||||
|
||||
d.pushState(tok)
|
||||
|
||||
for i := range d.vs {
|
||||
v := d.vs[i][len(d.vs[i])-1]
|
||||
// TODO: Confirm this is needed, write a test case.
|
||||
// if v.Kind() == reflect.Ptr && v.IsNil() {
|
||||
// v.Set(reflect.New(v.Type().Elem())) // v = new(T).
|
||||
//}
|
||||
|
||||
// Reset slice to empty (in case it had non-zero initial value).
|
||||
if v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
if v.Kind() != reflect.Slice {
|
||||
continue
|
||||
}
|
||||
v.Set(reflect.MakeSlice(v.Type(), 0, 0)) // v = make(T, 0, 0).
|
||||
}
|
||||
case '}', ']':
|
||||
// End of object or array.
|
||||
d.popAllVs()
|
||||
d.popState()
|
||||
default:
|
||||
return xerrors.New("unexpected delimiter in JSON input")
|
||||
}
|
||||
default:
|
||||
return xerrors.New("unexpected token in JSON input")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// pushState pushes a new parse state s onto the stack.
|
||||
func (d *Decoder) pushState(s json.Delim) {
|
||||
d.parseState = append(d.parseState, s)
|
||||
}
|
||||
|
||||
// popState pops a parse state (already obtained) off the stack.
|
||||
// The stack must be non-empty.
|
||||
func (d *Decoder) popState() {
|
||||
d.parseState = d.parseState[:len(d.parseState)-1]
|
||||
}
|
||||
|
||||
// state reports the parse state on top of stack, or 0 if empty.
|
||||
func (d *Decoder) state() json.Delim {
|
||||
if len(d.parseState) == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
return d.parseState[len(d.parseState)-1]
|
||||
}
|
||||
|
||||
// popAllVs pops from all d.vs stacks, keeping only non-empty ones.
|
||||
func (d *Decoder) popAllVs() {
|
||||
var nonEmpty [][]reflect.Value
|
||||
for i := range d.vs {
|
||||
d.vs[i] = d.vs[i][:len(d.vs[i])-1]
|
||||
if len(d.vs[i]) > 0 {
|
||||
nonEmpty = append(nonEmpty, d.vs[i])
|
||||
}
|
||||
}
|
||||
d.vs = nonEmpty
|
||||
}
|
||||
|
||||
// fieldByGraphQLName returns an exported struct field of struct v
|
||||
// that matches GraphQL name, or invalid reflect.Value if none found.
|
||||
func fieldByGraphQLName(v reflect.Value, name string) reflect.Value {
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
if v.Type().Field(i).PkgPath != "" {
|
||||
// Skip unexported field.
|
||||
continue
|
||||
}
|
||||
if hasGraphQLName(v.Type().Field(i), name) {
|
||||
return v.Field(i)
|
||||
}
|
||||
}
|
||||
|
||||
return reflect.Value{}
|
||||
}
|
||||
|
||||
// hasGraphQLName reports whether struct field f has GraphQL name.
|
||||
func hasGraphQLName(f reflect.StructField, name string) bool {
|
||||
value, ok := f.Tag.Lookup("graphql")
|
||||
if !ok {
|
||||
// TODO: caseconv package is relatively slow. Optimize it, then consider using it here.
|
||||
// return caseconv.MixedCapsToLowerCamelCase(f.Name) == name
|
||||
return strings.EqualFold(f.Name, name)
|
||||
}
|
||||
value = strings.TrimSpace(value) // TODO: Parse better.
|
||||
if strings.HasPrefix(value, "...") {
|
||||
// GraphQL fragment. It doesn't have a name.
|
||||
return false
|
||||
}
|
||||
if i := strings.Index(value, "("); i != -1 {
|
||||
value = value[:i]
|
||||
}
|
||||
if i := strings.Index(value, ":"); i != -1 {
|
||||
value = value[:i]
|
||||
}
|
||||
|
||||
return strings.TrimSpace(value) == name
|
||||
}
|
||||
|
||||
// isGraphQLFragment reports whether struct field f is a GraphQL fragment.
|
||||
func isGraphQLFragment(f reflect.StructField) bool {
|
||||
value, ok := f.Tag.Lookup("graphql")
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
value = strings.TrimSpace(value) // TODO: Parse better.
|
||||
|
||||
return strings.HasPrefix(value, "...")
|
||||
}
|
||||
|
||||
// unmarshalValue unmarshals JSON value into v.
|
||||
// v must be addressable and not obtained by the use of unexported
|
||||
// struct fields, otherwise unmarshalValue will panic.
|
||||
func unmarshalValue(value json.Token, v reflect.Value) error {
|
||||
b, err := json.Marshal(value) // TODO: Short-circuit (if profiling says it's worth it).
|
||||
if err != nil {
|
||||
return xerrors.Errorf(": %w", err)
|
||||
}
|
||||
|
||||
return json.Unmarshal(b, v.Addr().Interface())
|
||||
}
|
||||
|
||||
// Errors represents the "Errors" array in a response from a GraphQL server.
|
||||
// If returned via error interface, the slice is expected to contain at least 1 element.
|
||||
//
|
||||
// Specification: https://facebook.github.io/graphql/#sec-Errors.
|
||||
type Errors []struct {
|
||||
Message string
|
||||
Locations []struct {
|
||||
Line int
|
||||
Column int
|
||||
}
|
||||
}
|
||||
|
||||
// Error implements error interface.
|
||||
func (e Errors) Error() string {
|
||||
return e[0].Message
|
||||
}
|
||||
289
vendor/github.com/Yamashou/gqlgenc/introspection/parse.go
generated
vendored
Normal file
289
vendor/github.com/Yamashou/gqlgenc/introspection/parse.go
generated
vendored
Normal file
@@ -0,0 +1,289 @@
|
||||
package introspection
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/vektah/gqlparser/v2/ast"
|
||||
)
|
||||
|
||||
func ParseIntrospectionQuery(query Query) *ast.SchemaDocument {
|
||||
var doc ast.SchemaDocument
|
||||
typeMap := query.Schema.Types.NameMap()
|
||||
|
||||
doc.Schema = append(doc.Schema, parseSchemaDefinition(query, typeMap))
|
||||
|
||||
for _, typeVale := range typeMap {
|
||||
doc.Definitions = append(doc.Definitions, parseTypeSystemDefinition(typeVale))
|
||||
}
|
||||
|
||||
for _, directiveValue := range query.Schema.Directives {
|
||||
doc.Directives = append(doc.Directives, parseDirectiveDefinition(directiveValue))
|
||||
}
|
||||
|
||||
return &doc
|
||||
}
|
||||
|
||||
func parseSchemaDefinition(query Query, typeMap map[string]*FullType) *ast.SchemaDefinition {
|
||||
def := ast.SchemaDefinition{}
|
||||
|
||||
def.OperationTypes = append(def.OperationTypes,
|
||||
parseOperationTypeDefinitionForQuery(typeMap[*query.Schema.QueryType.Name]),
|
||||
parseOperationTypeDefinitionForMutation(typeMap[*query.Schema.MutationType.Name]),
|
||||
)
|
||||
|
||||
return &def
|
||||
}
|
||||
|
||||
func parseOperationTypeDefinitionForQuery(fullType *FullType) *ast.OperationTypeDefinition {
|
||||
var op ast.OperationTypeDefinition
|
||||
op.Operation = ast.Query
|
||||
op.Type = *fullType.Name
|
||||
|
||||
return &op
|
||||
}
|
||||
|
||||
func parseOperationTypeDefinitionForMutation(fullType *FullType) *ast.OperationTypeDefinition {
|
||||
var op ast.OperationTypeDefinition
|
||||
op.Operation = ast.Mutation
|
||||
op.Type = *fullType.Name
|
||||
|
||||
return &op
|
||||
}
|
||||
|
||||
func parseDirectiveDefinition(directiveValue *DirectiveType) *ast.DirectiveDefinition {
|
||||
args := make(ast.ArgumentDefinitionList, 0, len(directiveValue.Args))
|
||||
for _, arg := range directiveValue.Args {
|
||||
argumentDefinition := buildInputValue(arg)
|
||||
args = append(args, argumentDefinition)
|
||||
}
|
||||
locations := make([]ast.DirectiveLocation, 0, len(directiveValue.Locations))
|
||||
for _, locationValue := range directiveValue.Locations {
|
||||
locations = append(locations, ast.DirectiveLocation(locationValue))
|
||||
}
|
||||
|
||||
return &ast.DirectiveDefinition{
|
||||
Description: pointerString(directiveValue.Description),
|
||||
Name: directiveValue.Name,
|
||||
Arguments: args,
|
||||
Locations: locations,
|
||||
}
|
||||
}
|
||||
|
||||
func parseObjectFields(typeVale *FullType) ast.FieldList {
|
||||
fieldList := make(ast.FieldList, 0, len(typeVale.Fields))
|
||||
for _, field := range typeVale.Fields {
|
||||
typ := getType(&field.Type)
|
||||
args := make(ast.ArgumentDefinitionList, 0, len(field.Args))
|
||||
for _, arg := range field.Args {
|
||||
argumentDefinition := buildInputValue(arg)
|
||||
args = append(args, argumentDefinition)
|
||||
}
|
||||
|
||||
fieldDefinition := &ast.FieldDefinition{
|
||||
Description: pointerString(field.Description),
|
||||
Name: field.Name,
|
||||
Arguments: args,
|
||||
Type: typ,
|
||||
}
|
||||
fieldList = append(fieldList, fieldDefinition)
|
||||
}
|
||||
|
||||
return fieldList
|
||||
}
|
||||
|
||||
func parseInputObjectFields(typeVale *FullType) ast.FieldList {
|
||||
fieldList := make(ast.FieldList, 0, len(typeVale.InputFields))
|
||||
for _, field := range typeVale.InputFields {
|
||||
typ := getType(&field.Type)
|
||||
fieldDefinition := &ast.FieldDefinition{
|
||||
Description: pointerString(field.Description),
|
||||
Name: field.Name,
|
||||
Type: typ,
|
||||
}
|
||||
fieldList = append(fieldList, fieldDefinition)
|
||||
}
|
||||
|
||||
return fieldList
|
||||
}
|
||||
|
||||
func parseObjectTypeDefinition(typeVale *FullType) *ast.Definition {
|
||||
fieldList := parseObjectFields(typeVale)
|
||||
interfaces := make([]string, 0, len(typeVale.Interfaces))
|
||||
for _, intf := range typeVale.Interfaces {
|
||||
interfaces = append(interfaces, pointerString(intf.Name))
|
||||
}
|
||||
|
||||
enums := make(ast.EnumValueList, 0, len(typeVale.EnumValues))
|
||||
for _, enum := range typeVale.EnumValues {
|
||||
enumValue := &ast.EnumValueDefinition{
|
||||
Description: pointerString(enum.Description),
|
||||
Name: enum.Name,
|
||||
}
|
||||
enums = append(enums, enumValue)
|
||||
}
|
||||
|
||||
return &ast.Definition{
|
||||
Kind: ast.Object,
|
||||
Description: pointerString(typeVale.Description),
|
||||
Name: pointerString(typeVale.Name),
|
||||
Interfaces: interfaces,
|
||||
Fields: fieldList,
|
||||
EnumValues: enums,
|
||||
Position: nil,
|
||||
BuiltIn: true,
|
||||
}
|
||||
}
|
||||
|
||||
func parseInterfaceTypeDefinition(typeVale *FullType) *ast.Definition {
|
||||
fieldList := parseObjectFields(typeVale)
|
||||
interfaces := make([]string, 0, len(typeVale.Interfaces))
|
||||
for _, intf := range typeVale.Interfaces {
|
||||
interfaces = append(interfaces, pointerString(intf.Name))
|
||||
}
|
||||
|
||||
return &ast.Definition{
|
||||
Kind: ast.Interface,
|
||||
Description: pointerString(typeVale.Description),
|
||||
Name: pointerString(typeVale.Name),
|
||||
Interfaces: interfaces,
|
||||
Fields: fieldList,
|
||||
Position: nil,
|
||||
BuiltIn: true,
|
||||
}
|
||||
}
|
||||
|
||||
func parseInputObjectTypeDefinition(typeVale *FullType) *ast.Definition {
|
||||
fieldList := parseInputObjectFields(typeVale)
|
||||
interfaces := make([]string, 0, len(typeVale.Interfaces))
|
||||
for _, intf := range typeVale.Interfaces {
|
||||
interfaces = append(interfaces, pointerString(intf.Name))
|
||||
}
|
||||
|
||||
return &ast.Definition{
|
||||
Kind: ast.InputObject,
|
||||
Description: pointerString(typeVale.Description),
|
||||
Name: pointerString(typeVale.Name),
|
||||
Interfaces: interfaces,
|
||||
Fields: fieldList,
|
||||
Position: nil,
|
||||
BuiltIn: true,
|
||||
}
|
||||
}
|
||||
|
||||
func parseUnionTypeDefinition(typeVale *FullType) *ast.Definition {
|
||||
unions := make([]string, 0, len(typeVale.PossibleTypes))
|
||||
for _, unionValue := range typeVale.PossibleTypes {
|
||||
unions = append(unions, *unionValue.Name)
|
||||
}
|
||||
|
||||
return &ast.Definition{
|
||||
Kind: ast.Union,
|
||||
Description: pointerString(typeVale.Description),
|
||||
Name: pointerString(typeVale.Name),
|
||||
Types: unions,
|
||||
Position: nil,
|
||||
BuiltIn: true,
|
||||
}
|
||||
}
|
||||
|
||||
func parseEnumTypeDefinition(typeVale *FullType) *ast.Definition {
|
||||
enums := make(ast.EnumValueList, 0, len(typeVale.EnumValues))
|
||||
for _, enum := range typeVale.EnumValues {
|
||||
enumValue := &ast.EnumValueDefinition{
|
||||
Description: pointerString(enum.Description),
|
||||
Name: enum.Name,
|
||||
}
|
||||
enums = append(enums, enumValue)
|
||||
}
|
||||
|
||||
return &ast.Definition{
|
||||
Kind: ast.Enum,
|
||||
Description: pointerString(typeVale.Description),
|
||||
Name: pointerString(typeVale.Name),
|
||||
EnumValues: enums,
|
||||
Position: nil,
|
||||
BuiltIn: true,
|
||||
}
|
||||
}
|
||||
|
||||
func parseScalarTypeExtension(typeVale *FullType) *ast.Definition {
|
||||
return &ast.Definition{
|
||||
Kind: ast.Scalar,
|
||||
Description: pointerString(typeVale.Description),
|
||||
Name: pointerString(typeVale.Name),
|
||||
Position: nil,
|
||||
BuiltIn: true,
|
||||
}
|
||||
}
|
||||
|
||||
func parseTypeSystemDefinition(typeVale *FullType) *ast.Definition {
|
||||
switch typeVale.Kind {
|
||||
case TypeKindScalar:
|
||||
return parseScalarTypeExtension(typeVale)
|
||||
case TypeKindInterface:
|
||||
return parseInterfaceTypeDefinition(typeVale)
|
||||
case TypeKindEnum:
|
||||
return parseEnumTypeDefinition(typeVale)
|
||||
case TypeKindUnion:
|
||||
return parseUnionTypeDefinition(typeVale)
|
||||
case TypeKindObject:
|
||||
return parseObjectTypeDefinition(typeVale)
|
||||
case TypeKindInputObject:
|
||||
return parseInputObjectTypeDefinition(typeVale)
|
||||
case TypeKindList, TypeKindNonNull:
|
||||
panic(fmt.Sprintf("not match Kind: %s", typeVale.Kind))
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("not match Kind: %s", typeVale.Kind))
|
||||
}
|
||||
|
||||
func pointerString(s *string) string {
|
||||
if s == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return *s
|
||||
}
|
||||
|
||||
func buildInputValue(input *InputValue) *ast.ArgumentDefinition {
|
||||
typ := getType(&input.Type)
|
||||
|
||||
var defaultValue *ast.Value
|
||||
if input.DefaultValue != nil {
|
||||
defaultValue = &ast.Value{
|
||||
Raw: pointerString(input.DefaultValue),
|
||||
Kind: ast.Variable,
|
||||
}
|
||||
}
|
||||
|
||||
return &ast.ArgumentDefinition{
|
||||
Description: pointerString(input.Description),
|
||||
Name: input.Name,
|
||||
DefaultValue: defaultValue,
|
||||
Type: typ,
|
||||
}
|
||||
}
|
||||
|
||||
func getType(typeRef *TypeRef) *ast.Type {
|
||||
if typeRef.Kind == TypeKindList {
|
||||
itemRef := typeRef.OfType
|
||||
if itemRef == nil {
|
||||
panic("Decorated type deeper than introspection query.")
|
||||
}
|
||||
|
||||
return ast.ListType(getType(itemRef), nil)
|
||||
}
|
||||
|
||||
if typeRef.Kind == TypeKindNonNull {
|
||||
nullableRef := typeRef.OfType
|
||||
if nullableRef == nil {
|
||||
panic("Decorated type deeper than introspection query.")
|
||||
}
|
||||
nullableType := getType(nullableRef)
|
||||
nullableType.NonNull = true
|
||||
|
||||
return nullableType
|
||||
}
|
||||
|
||||
return ast.NamedType(pointerString(typeRef.Name), nil)
|
||||
}
|
||||
93
vendor/github.com/Yamashou/gqlgenc/introspection/query.go
generated
vendored
Normal file
93
vendor/github.com/Yamashou/gqlgenc/introspection/query.go
generated
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
package introspection
|
||||
|
||||
const Introspection = `query Query {
|
||||
__schema {
|
||||
queryType { name }
|
||||
mutationType { name }
|
||||
subscriptionType { name }
|
||||
types {
|
||||
...FullType
|
||||
}
|
||||
directives {
|
||||
name
|
||||
description
|
||||
locations
|
||||
args {
|
||||
...InputValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fragment FullType on __Type {
|
||||
kind
|
||||
name
|
||||
description
|
||||
fields(includeDeprecated: true) {
|
||||
name
|
||||
description
|
||||
args {
|
||||
...InputValue
|
||||
}
|
||||
type {
|
||||
...TypeRef
|
||||
}
|
||||
isDeprecated
|
||||
deprecationReason
|
||||
}
|
||||
inputFields {
|
||||
...InputValue
|
||||
}
|
||||
interfaces {
|
||||
...TypeRef
|
||||
}
|
||||
enumValues(includeDeprecated: true) {
|
||||
name
|
||||
description
|
||||
isDeprecated
|
||||
deprecationReason
|
||||
}
|
||||
possibleTypes {
|
||||
...TypeRef
|
||||
}
|
||||
}
|
||||
|
||||
fragment InputValue on __InputValue {
|
||||
name
|
||||
description
|
||||
type { ...TypeRef }
|
||||
defaultValue
|
||||
}
|
||||
|
||||
fragment TypeRef on __Type {
|
||||
kind
|
||||
name
|
||||
ofType {
|
||||
kind
|
||||
name
|
||||
ofType {
|
||||
kind
|
||||
name
|
||||
ofType {
|
||||
kind
|
||||
name
|
||||
ofType {
|
||||
kind
|
||||
name
|
||||
ofType {
|
||||
kind
|
||||
name
|
||||
ofType {
|
||||
kind
|
||||
name
|
||||
ofType {
|
||||
kind
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
80
vendor/github.com/Yamashou/gqlgenc/introspection/type.go
generated
vendored
Normal file
80
vendor/github.com/Yamashou/gqlgenc/introspection/type.go
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
package introspection
|
||||
|
||||
type TypeKind string
|
||||
|
||||
const (
|
||||
TypeKindScalar TypeKind = "SCALAR"
|
||||
TypeKindObject TypeKind = "OBJECT"
|
||||
TypeKindInterface TypeKind = "INTERFACE"
|
||||
TypeKindUnion TypeKind = "UNION"
|
||||
TypeKindEnum TypeKind = "ENUM"
|
||||
TypeKindInputObject TypeKind = "INPUT_OBJECT"
|
||||
TypeKindList TypeKind = "LIST"
|
||||
TypeKindNonNull TypeKind = "NON_NULL"
|
||||
)
|
||||
|
||||
type FullTypes []*FullType
|
||||
|
||||
func (fs FullTypes) NameMap() map[string]*FullType {
|
||||
typeMap := make(map[string]*FullType)
|
||||
for _, typ := range fs {
|
||||
typeMap[*typ.Name] = typ
|
||||
}
|
||||
|
||||
return typeMap
|
||||
}
|
||||
|
||||
type FullType struct {
|
||||
Kind TypeKind
|
||||
Name *string
|
||||
Description *string
|
||||
Fields []*FieldValue
|
||||
InputFields []*InputValue
|
||||
Interfaces []*TypeRef
|
||||
EnumValues []*struct {
|
||||
Name string
|
||||
Description *string
|
||||
IsDeprecated bool
|
||||
DeprecationReason *string
|
||||
}
|
||||
PossibleTypes []*TypeRef
|
||||
}
|
||||
|
||||
type FieldValue struct {
|
||||
Name string
|
||||
Description *string
|
||||
Args []*InputValue
|
||||
Type TypeRef
|
||||
IsDeprecated bool
|
||||
DeprecationReason *string
|
||||
}
|
||||
|
||||
type InputValue struct {
|
||||
Name string
|
||||
Description *string
|
||||
Type TypeRef
|
||||
DefaultValue *string
|
||||
}
|
||||
|
||||
type TypeRef struct {
|
||||
Kind TypeKind
|
||||
Name *string
|
||||
OfType *TypeRef
|
||||
}
|
||||
|
||||
type Query struct {
|
||||
Schema struct {
|
||||
QueryType struct{ Name *string }
|
||||
MutationType *struct{ Name *string }
|
||||
SubscriptionType *struct{ Name *string }
|
||||
Types FullTypes
|
||||
Directives []*DirectiveType
|
||||
} `graphql:"__schema"`
|
||||
}
|
||||
|
||||
type DirectiveType struct {
|
||||
Name string
|
||||
Description *string
|
||||
Locations []string
|
||||
Args []*InputValue
|
||||
}
|
||||
27
vendor/github.com/Yamashou/gqlgenc/main.go
generated
vendored
Normal file
27
vendor/github.com/Yamashou/gqlgenc/main.go
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/99designs/gqlgen/api"
|
||||
"github.com/Yamashou/gqlgenc/clientgen"
|
||||
"github.com/Yamashou/gqlgenc/config"
|
||||
"github.com/Yamashou/gqlgenc/generator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx := context.Background()
|
||||
cfg, err := config.LoadConfig(".gqlgenc.yml")
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%+v", err.Error())
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
clientPlugin := clientgen.New(cfg.Query, cfg.Client)
|
||||
if err := generator.Generate(ctx, cfg, api.AddPlugin(clientPlugin)); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%+v", err.Error())
|
||||
os.Exit(4)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user