mirror of
https://github.com/stashapp/stash.git
synced 2025-12-15 21:03:22 +01:00
Upgrade to go 1.19 and update dependencies (#3069)
* Update to go 1.19 * Update dependencies * Update cross-compile script * Add missing targets to cross-compile-all * Update cache action to remove warning
This commit is contained in:
parent
f25881a3bf
commit
bba7c23957
939 changed files with 101336 additions and 43819 deletions
8
.github/workflows/build.yml
vendored
8
.github/workflows/build.yml
vendored
|
|
@ -12,7 +12,7 @@ concurrency:
|
|||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
COMPILER_IMAGE: stashapp/compiler:6
|
||||
COMPILER_IMAGE: stashapp/compiler:7
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
|
@ -27,7 +27,7 @@ jobs:
|
|||
run: docker pull $COMPILER_IMAGE
|
||||
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: cache-node_modules
|
||||
with:
|
||||
|
|
@ -35,7 +35,7 @@ jobs:
|
|||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('ui/v2.5/yarn.lock') }}
|
||||
|
||||
- name: Cache UI build
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
id: cache-ui
|
||||
env:
|
||||
cache-name: cache-ui
|
||||
|
|
@ -44,7 +44,7 @@ jobs:
|
|||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('ui/v2.5/yarn.lock', 'ui/v2.5/public/**', 'ui/v2.5/src/**', 'graphql/**/*.graphql') }}
|
||||
|
||||
- name: Cache go build
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
# increment the number suffix to bump the cache
|
||||
cache-name: cache-go-cache-1
|
||||
|
|
|
|||
2
.github/workflows/golangci-lint.yml
vendored
2
.github/workflows/golangci-lint.yml
vendored
|
|
@ -9,7 +9,7 @@ on:
|
|||
pull_request:
|
||||
|
||||
env:
|
||||
COMPILER_IMAGE: stashapp/compiler:6
|
||||
COMPILER_IMAGE: stashapp/compiler:7
|
||||
|
||||
jobs:
|
||||
golangci:
|
||||
|
|
|
|||
3
Makefile
3
Makefile
|
|
@ -135,7 +135,8 @@ cross-compile-linux-arm32v6: build-release-static
|
|||
|
||||
cross-compile-all:
|
||||
make cross-compile-windows
|
||||
make cross-compile-macos
|
||||
make cross-compile-macos-intel
|
||||
make cross-compile-macos-applesilicon
|
||||
make cross-compile-linux
|
||||
make cross-compile-linux-arm64v8
|
||||
make cross-compile-linux-arm32v7
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ ARG STASH_VERSION
|
|||
RUN BUILD_DATE=$(date +"%Y-%m-%d %H:%M:%S") make ui
|
||||
|
||||
# Build Backend
|
||||
FROM golang:1.17-alpine as backend
|
||||
FROM golang:1.19-alpine as backend
|
||||
RUN apk add --no-cache make alpine-sdk
|
||||
WORKDIR /stash
|
||||
COPY ./go* ./*.go Makefile gqlgen.yml .gqlgenc.yml /stash/
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM golang:1.17
|
||||
FROM golang:1.19
|
||||
|
||||
LABEL maintainer="https://discord.gg/2TsNFKt"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
user=stashapp
|
||||
repo=compiler
|
||||
version=6
|
||||
version=7
|
||||
|
||||
latest:
|
||||
docker build -t ${user}/${repo}:latest .
|
||||
|
|
|
|||
114
go.mod
114
go.mod
|
|
@ -1,111 +1,115 @@
|
|||
module github.com/stashapp/stash
|
||||
|
||||
require (
|
||||
github.com/99designs/gqlgen v0.17.2
|
||||
github.com/Yamashou/gqlgenc v0.0.6
|
||||
github.com/anacrolix/dms v1.2.2
|
||||
github.com/antchfx/htmlquery v1.2.5-0.20211125074323-810ee8082758
|
||||
github.com/chromedp/cdproto v0.0.0-20210622022015-fe1827b46b84
|
||||
github.com/chromedp/chromedp v0.7.3
|
||||
github.com/corona10/goimagehash v1.0.3
|
||||
github.com/disintegration/imaging v1.6.0
|
||||
github.com/99designs/gqlgen v0.17.20
|
||||
github.com/Yamashou/gqlgenc v0.11.2
|
||||
github.com/anacrolix/dms v1.5.0
|
||||
github.com/antchfx/htmlquery v1.2.5
|
||||
github.com/chromedp/cdproto v0.0.0-20221029224954-108014bf7279
|
||||
github.com/chromedp/chromedp v0.8.6
|
||||
github.com/corona10/goimagehash v1.1.0
|
||||
github.com/disintegration/imaging v1.6.2
|
||||
github.com/fvbommel/sortorder v1.0.2
|
||||
github.com/go-chi/chi v4.0.2+incompatible
|
||||
github.com/golang-jwt/jwt/v4 v4.0.0
|
||||
github.com/golang-migrate/migrate/v4 v4.15.0-beta.1
|
||||
github.com/go-chi/chi v4.1.2+incompatible
|
||||
github.com/golang-jwt/jwt/v4 v4.4.2
|
||||
github.com/golang-migrate/migrate/v4 v4.15.2
|
||||
github.com/gorilla/securecookie v1.1.1
|
||||
github.com/gorilla/sessions v1.2.0
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a
|
||||
github.com/jmoiron/sqlx v1.3.1
|
||||
github.com/gorilla/sessions v1.2.1
|
||||
github.com/gorilla/websocket v1.5.0
|
||||
github.com/jinzhu/copier v0.3.5
|
||||
github.com/jmoiron/sqlx v1.3.5
|
||||
github.com/json-iterator/go v1.1.12
|
||||
github.com/mattn/go-sqlite3 v1.14.7
|
||||
github.com/mattn/go-sqlite3 v1.14.16
|
||||
github.com/natefinch/pie v0.0.0-20170715172608-9a0d72014007
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8
|
||||
github.com/remeh/sizedwaitgroup v1.0.0
|
||||
github.com/robertkrimen/otto v0.0.0-20200922221731-ef014fd054ac
|
||||
github.com/rs/cors v1.6.0
|
||||
github.com/shurcooL/graphql v0.0.0-20181231061246-d48a9a75455f
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/spf13/afero v1.8.2 // indirect
|
||||
github.com/robertkrimen/otto v0.0.0-20221025135307-511d75fba9f8
|
||||
github.com/rs/cors v1.8.2
|
||||
github.com/shurcooL/graphql v0.0.0-20220606043923-3cf50f8a0a29
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
github.com/spf13/afero v1.9.2 // indirect
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/spf13/viper v1.10.1
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/tidwall/gjson v1.9.3
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
github.com/spf13/viper v1.13.0
|
||||
github.com/stretchr/testify v1.8.1
|
||||
github.com/tidwall/gjson v1.14.3
|
||||
github.com/tidwall/pretty v1.2.1 // indirect
|
||||
github.com/vektra/mockery/v2 v2.10.0
|
||||
golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064
|
||||
golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b
|
||||
golang.org/x/sys v0.0.0-20220808155132-1c4a2a72c664
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
|
||||
golang.org/x/text v0.3.7
|
||||
golang.org/x/crypto v0.1.0
|
||||
golang.org/x/image v0.1.0
|
||||
golang.org/x/net v0.1.0
|
||||
golang.org/x/sys v0.1.0
|
||||
golang.org/x/term v0.1.0
|
||||
golang.org/x/text v0.4.0
|
||||
golang.org/x/tools v0.1.12 // indirect
|
||||
gopkg.in/sourcemap.v1 v1.0.5 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/asticode/go-astisub v0.20.0
|
||||
github.com/asticode/go-astisub v0.21.0
|
||||
github.com/doug-martin/goqu/v9 v9.18.0
|
||||
github.com/go-chi/httplog v0.2.1
|
||||
github.com/go-chi/httplog v0.2.5
|
||||
github.com/go-toast/toast v0.0.0-20190211030409-01e6764cf0a4
|
||||
github.com/hashicorp/golang-lru v0.5.4
|
||||
github.com/kermieisinthehouse/gosx-notifier v0.1.1
|
||||
github.com/kermieisinthehouse/systray v1.2.4
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0
|
||||
github.com/spf13/cast v1.4.1
|
||||
github.com/vearutop/statigz v1.1.6
|
||||
github.com/spf13/cast v1.5.0
|
||||
github.com/vearutop/statigz v1.1.8
|
||||
github.com/vektah/dataloaden v0.3.0
|
||||
github.com/vektah/gqlparser/v2 v2.4.1
|
||||
github.com/vektah/gqlparser/v2 v2.5.1
|
||||
gopkg.in/guregu/null.v4 v4.0.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/agnivade/levenshtein v1.1.1 // indirect
|
||||
github.com/antchfx/xpath v1.2.0 // indirect
|
||||
github.com/asticode/go-astikit v0.20.0 // indirect
|
||||
github.com/asticode/go-astits v1.8.0 // indirect
|
||||
github.com/anacrolix/log v0.13.1 // indirect
|
||||
github.com/antchfx/xpath v1.2.1 // indirect
|
||||
github.com/asticode/go-astikit v0.35.0 // indirect
|
||||
github.com/asticode/go-astits v1.11.0 // indirect
|
||||
github.com/chromedp/sysutil v1.0.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/fsnotify/fsnotify v1.5.1 // indirect
|
||||
github.com/go-chi/chi/v5 v5.0.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/go-chi/chi/v5 v5.0.7 // indirect
|
||||
github.com/gobwas/httphead v0.1.0 // indirect
|
||||
github.com/gobwas/pool v0.2.1 // indirect
|
||||
github.com/gobwas/ws v1.1.0-rc.5 // indirect
|
||||
github.com/gobwas/ws v1.1.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/magiconair/properties v1.8.6 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/matryer/moq v0.2.6 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.4.3 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
|
||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
|
||||
github.com/pelletier/go-toml v1.9.4 // indirect
|
||||
github.com/pelletier/go-toml v1.9.5 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/rs/zerolog v1.26.1 // indirect
|
||||
github.com/rs/zerolog v1.28.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/spf13/cobra v1.4.0 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/stretchr/objx v0.2.0 // indirect
|
||||
github.com/subosito/gotenv v1.2.0 // indirect
|
||||
github.com/stretchr/objx v0.5.0 // indirect
|
||||
github.com/subosito/gotenv v1.4.1 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/urfave/cli/v2 v2.4.0 // indirect
|
||||
go.uber.org/atomic v1.7.0 // indirect
|
||||
github.com/urfave/cli/v2 v2.8.1 // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||
go.uber.org/atomic v1.10.0 // indirect
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
||||
gopkg.in/ini.v1 v1.66.4 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
replace git.apache.org/thrift.git => github.com/apache/thrift v0.0.0-20180902110319-2566ecd5d999
|
||||
|
||||
go 1.17
|
||||
go 1.19
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"compress/flate"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
|
|
@ -61,8 +62,7 @@ func Start() error {
|
|||
r.Use(httplog.RequestLogger(httpLogger))
|
||||
}
|
||||
r.Use(SecurityHeadersMiddleware)
|
||||
r.Use(middleware.DefaultCompress)
|
||||
r.Use(middleware.StripSlashes)
|
||||
r.Use(middleware.Compress(flate.DefaultCompression))
|
||||
r.Use(cors.AllowAll().Handler)
|
||||
r.Use(BaseURLMiddleware)
|
||||
|
||||
|
|
|
|||
|
|
@ -14,15 +14,15 @@ const APIKeySubject = "APIKey"
|
|||
|
||||
type APIKeyClaims struct {
|
||||
UserID string `json:"uid"`
|
||||
jwt.StandardClaims
|
||||
jwt.RegisteredClaims
|
||||
}
|
||||
|
||||
func GenerateAPIKey(userID string) (string, error) {
|
||||
claims := &APIKeyClaims{
|
||||
UserID: userID,
|
||||
StandardClaims: jwt.StandardClaims{
|
||||
RegisteredClaims: jwt.RegisteredClaims{
|
||||
Subject: APIKeySubject,
|
||||
IssuedAt: time.Now().Unix(),
|
||||
IssuedAt: jwt.NewNumericDate(time.Now()),
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
COMPILER_CONTAINER="stashapp/compiler:6"
|
||||
COMPILER_CONTAINER="stashapp/compiler:7"
|
||||
|
||||
BUILD_DATE=`go run -mod=vendor scripts/getDate.go`
|
||||
GITHASH=`git rev-parse --short HEAD`
|
||||
|
|
|
|||
2
vendor/github.com/99designs/gqlgen/.gitignore
generated
vendored
2
vendor/github.com/99designs/gqlgen/.gitignore
generated
vendored
|
|
@ -14,3 +14,5 @@
|
|||
.idea/
|
||||
*.test
|
||||
*.out
|
||||
gqlgen
|
||||
*.exe
|
||||
|
|
|
|||
2097
vendor/github.com/99designs/gqlgen/CHANGELOG.md
generated
vendored
2097
vendor/github.com/99designs/gqlgen/CHANGELOG.md
generated
vendored
File diff suppressed because it is too large
Load diff
11
vendor/github.com/99designs/gqlgen/README.md
generated
vendored
11
vendor/github.com/99designs/gqlgen/README.md
generated
vendored
|
|
@ -142,9 +142,20 @@ first model in this list is used as the default type and it will always be used
|
|||
|
||||
There isn't any way around this, gqlgen has no way to know what you want in a given context.
|
||||
|
||||
### Why do my interfaces have getters? Can I disable these?
|
||||
These were added in v0.17.14 to allow accessing common interface fields without casting to a concrete type.
|
||||
However, certain fields, like Relay-style Connections, cannot be implemented with simple getters.
|
||||
|
||||
If you'd prefer to not have getters generated in your interfaces, you can add the following in your `gqlgen.yml`:
|
||||
```yaml
|
||||
# gqlgen.yml
|
||||
omit_getters: true
|
||||
```
|
||||
|
||||
## Other Resources
|
||||
|
||||
- [Christopher Biscardi @ Gophercon UK 2018](https://youtu.be/FdURVezcdcw)
|
||||
- [Introducing gqlgen: a GraphQL Server Generator for Go](https://99designs.com.au/blog/engineering/gqlgen-a-graphql-server-generator-for-go/)
|
||||
- [Dive into GraphQL by Iván Corrales Solera](https://medium.com/@ivan.corrales.solera/dive-into-graphql-9bfedf22e1a)
|
||||
- [Sample Project built on gqlgen with Postgres by Oleg Shalygin](https://github.com/oshalygin/gqlgen-pg-todo-example)
|
||||
- [Hackernews GraphQL Server with gqlgen by Shayegan Hooshyari](https://www.howtographql.com/graphql-go/0-introduction/)
|
||||
|
|
|
|||
16
vendor/github.com/99designs/gqlgen/api/generate.go
generated
vendored
16
vendor/github.com/99designs/gqlgen/api/generate.go
generated
vendored
|
|
@ -2,6 +2,7 @@ package api
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"syscall"
|
||||
|
||||
"github.com/99designs/gqlgen/codegen"
|
||||
|
|
@ -24,7 +25,20 @@ func Generate(cfg *config.Config, option ...Option) error {
|
|||
}
|
||||
plugins = append(plugins, resolvergen.New())
|
||||
if cfg.Federation.IsDefined() {
|
||||
plugins = append([]plugin.Plugin{federation.New()}, plugins...)
|
||||
if cfg.Federation.Version == 0 { // default to using the user's choice of version, but if unset, try to sort out which federation version to use
|
||||
urlRegex := regexp.MustCompile(`(?s)@link.*\(.*url:.*?"(.*?)"[^)]+\)`) // regex to grab the url of a link directive, should it exist
|
||||
|
||||
// check the sources, and if one is marked as federation v2, we mark the entirety to be generated using that format
|
||||
for _, v := range cfg.Sources {
|
||||
cfg.Federation.Version = 1
|
||||
urlString := urlRegex.FindStringSubmatch(v.Input)
|
||||
if urlString != nil && urlString[1] == "https://specs.apollo.dev/federation/v2.0" {
|
||||
cfg.Federation.Version = 2
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
plugins = append([]plugin.Plugin{federation.New(cfg.Federation.Version)}, plugins...)
|
||||
}
|
||||
|
||||
for _, o := range option {
|
||||
|
|
|
|||
12
vendor/github.com/99designs/gqlgen/codegen/args.go
generated
vendored
12
vendor/github.com/99designs/gqlgen/codegen/args.go
generated
vendored
|
|
@ -73,11 +73,15 @@ func (b *builder) buildArg(obj *Object, arg *ast.ArgumentDefinition) (*FieldArgu
|
|||
return &newArg, nil
|
||||
}
|
||||
|
||||
func (b *builder) bindArgs(field *Field, params *types.Tuple) ([]*FieldArgument, error) {
|
||||
var newArgs []*FieldArgument
|
||||
|
||||
func (b *builder) bindArgs(field *Field, sig *types.Signature, params *types.Tuple) ([]*FieldArgument, error) {
|
||||
n := params.Len()
|
||||
newArgs := make([]*FieldArgument, 0, len(field.Args))
|
||||
// Accept variadic methods (i.e. have optional parameters).
|
||||
if params.Len() > len(field.Args) && sig.Variadic() {
|
||||
n = len(field.Args)
|
||||
}
|
||||
nextArg:
|
||||
for j := 0; j < params.Len(); j++ {
|
||||
for j := 0; j < n; j++ {
|
||||
param := params.At(j)
|
||||
for _, oldArg := range field.Args {
|
||||
if strings.EqualFold(oldArg.Name, param.Name()) {
|
||||
|
|
|
|||
1
vendor/github.com/99designs/gqlgen/codegen/config/binder.go
generated
vendored
1
vendor/github.com/99designs/gqlgen/codegen/config/binder.go
generated
vendored
|
|
@ -216,7 +216,6 @@ func (t *TypeReference) IsPtr() bool {
|
|||
}
|
||||
|
||||
// fix for https://github.com/golang/go/issues/31103 may make it possible to remove this (may still be useful)
|
||||
//
|
||||
func (t *TypeReference) IsPtrToPtr() bool {
|
||||
if p, isPtr := t.GO.(*types.Pointer); isPtr {
|
||||
_, isPtr := p.Elem().(*types.Pointer)
|
||||
|
|
|
|||
60
vendor/github.com/99designs/gqlgen/codegen/config/config.go
generated
vendored
60
vendor/github.com/99designs/gqlgen/codegen/config/config.go
generated
vendored
|
|
@ -1,8 +1,8 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
|
|
@ -12,25 +12,28 @@ import (
|
|||
"github.com/99designs/gqlgen/internal/code"
|
||||
"github.com/vektah/gqlparser/v2"
|
||||
"github.com/vektah/gqlparser/v2/ast"
|
||||
"gopkg.in/yaml.v2"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
SchemaFilename StringList `yaml:"schema,omitempty"`
|
||||
Exec ExecConfig `yaml:"exec"`
|
||||
Model PackageConfig `yaml:"model,omitempty"`
|
||||
Federation PackageConfig `yaml:"federation,omitempty"`
|
||||
Resolver ResolverConfig `yaml:"resolver,omitempty"`
|
||||
AutoBind []string `yaml:"autobind"`
|
||||
Models TypeMap `yaml:"models,omitempty"`
|
||||
StructTag string `yaml:"struct_tag,omitempty"`
|
||||
Directives map[string]DirectiveConfig `yaml:"directives,omitempty"`
|
||||
OmitSliceElementPointers bool `yaml:"omit_slice_element_pointers,omitempty"`
|
||||
SkipValidation bool `yaml:"skip_validation,omitempty"`
|
||||
SkipModTidy bool `yaml:"skip_mod_tidy,omitempty"`
|
||||
Sources []*ast.Source `yaml:"-"`
|
||||
Packages *code.Packages `yaml:"-"`
|
||||
Schema *ast.Schema `yaml:"-"`
|
||||
SchemaFilename StringList `yaml:"schema,omitempty"`
|
||||
Exec ExecConfig `yaml:"exec"`
|
||||
Model PackageConfig `yaml:"model,omitempty"`
|
||||
Federation PackageConfig `yaml:"federation,omitempty"`
|
||||
Resolver ResolverConfig `yaml:"resolver,omitempty"`
|
||||
AutoBind []string `yaml:"autobind"`
|
||||
Models TypeMap `yaml:"models,omitempty"`
|
||||
StructTag string `yaml:"struct_tag,omitempty"`
|
||||
Directives map[string]DirectiveConfig `yaml:"directives,omitempty"`
|
||||
OmitSliceElementPointers bool `yaml:"omit_slice_element_pointers,omitempty"`
|
||||
OmitGetters bool `yaml:"omit_getters,omitempty"`
|
||||
StructFieldsAlwaysPointers bool `yaml:"struct_fields_always_pointers,omitempty"`
|
||||
ResolversAlwaysReturnPointers bool `yaml:"resolvers_always_return_pointers,omitempty"`
|
||||
SkipValidation bool `yaml:"skip_validation,omitempty"`
|
||||
SkipModTidy bool `yaml:"skip_mod_tidy,omitempty"`
|
||||
Sources []*ast.Source `yaml:"-"`
|
||||
Packages *code.Packages `yaml:"-"`
|
||||
Schema *ast.Schema `yaml:"-"`
|
||||
|
||||
// Deprecated: use Federation instead. Will be removed next release
|
||||
Federated bool `yaml:"federated,omitempty"`
|
||||
|
|
@ -41,11 +44,13 @@ var cfgFilenames = []string{".gqlgen.yml", "gqlgen.yml", "gqlgen.yaml"}
|
|||
// DefaultConfig creates a copy of the default config
|
||||
func DefaultConfig() *Config {
|
||||
return &Config{
|
||||
SchemaFilename: StringList{"schema.graphql"},
|
||||
Model: PackageConfig{Filename: "models_gen.go"},
|
||||
Exec: ExecConfig{Filename: "generated.go"},
|
||||
Directives: map[string]DirectiveConfig{},
|
||||
Models: TypeMap{},
|
||||
SchemaFilename: StringList{"schema.graphql"},
|
||||
Model: PackageConfig{Filename: "models_gen.go"},
|
||||
Exec: ExecConfig{Filename: "generated.go"},
|
||||
Directives: map[string]DirectiveConfig{},
|
||||
Models: TypeMap{},
|
||||
StructFieldsAlwaysPointers: true,
|
||||
ResolversAlwaysReturnPointers: true,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -57,7 +62,7 @@ func LoadDefaultConfig() (*Config, error) {
|
|||
filename = filepath.ToSlash(filename)
|
||||
var err error
|
||||
var schemaRaw []byte
|
||||
schemaRaw, err = ioutil.ReadFile(filename)
|
||||
schemaRaw, err = os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to open schema: %w", err)
|
||||
}
|
||||
|
|
@ -94,12 +99,15 @@ var path2regex = strings.NewReplacer(
|
|||
func LoadConfig(filename string) (*Config, error) {
|
||||
config := DefaultConfig()
|
||||
|
||||
b, err := ioutil.ReadFile(filename)
|
||||
b, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to read config: %w", err)
|
||||
}
|
||||
|
||||
if err := yaml.UnmarshalStrict(b, config); err != nil {
|
||||
dec := yaml.NewDecoder(bytes.NewReader(b))
|
||||
dec.KnownFields(true)
|
||||
|
||||
if err := dec.Decode(config); err != nil {
|
||||
return nil, fmt.Errorf("unable to parse config: %w", err)
|
||||
}
|
||||
|
||||
|
|
@ -173,7 +181,7 @@ func CompleteConfig(config *Config) error {
|
|||
filename = filepath.ToSlash(filename)
|
||||
var err error
|
||||
var schemaRaw []byte
|
||||
schemaRaw, err = ioutil.ReadFile(filename)
|
||||
schemaRaw, err = os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to open schema: %w", err)
|
||||
}
|
||||
|
|
|
|||
1
vendor/github.com/99designs/gqlgen/codegen/config/package.go
generated
vendored
1
vendor/github.com/99designs/gqlgen/codegen/config/package.go
generated
vendored
|
|
@ -12,6 +12,7 @@ import (
|
|||
type PackageConfig struct {
|
||||
Filename string `yaml:"filename,omitempty"`
|
||||
Package string `yaml:"package,omitempty"`
|
||||
Version int `yaml:"version,omitempty"`
|
||||
}
|
||||
|
||||
func (c *PackageConfig) ImportPath() string {
|
||||
|
|
|
|||
48
vendor/github.com/99designs/gqlgen/codegen/data.go
generated
vendored
48
vendor/github.com/99designs/gqlgen/codegen/data.go
generated
vendored
|
|
@ -2,7 +2,10 @@ package codegen
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/vektah/gqlparser/v2/ast"
|
||||
|
||||
|
|
@ -30,6 +33,26 @@ type Data struct {
|
|||
QueryRoot *Object
|
||||
MutationRoot *Object
|
||||
SubscriptionRoot *Object
|
||||
AugmentedSources []AugmentedSource
|
||||
}
|
||||
|
||||
func (d *Data) HasEmbeddableSources() bool {
|
||||
hasEmbeddableSources := false
|
||||
for _, s := range d.AugmentedSources {
|
||||
if s.Embeddable {
|
||||
hasEmbeddableSources = true
|
||||
}
|
||||
}
|
||||
return hasEmbeddableSources
|
||||
}
|
||||
|
||||
// AugmentedSource contains extra information about graphql schema files which is not known directly from the Config.Sources data
|
||||
type AugmentedSource struct {
|
||||
// path relative to Config.Exec.Filename
|
||||
RelativePath string
|
||||
Embeddable bool
|
||||
BuiltIn bool
|
||||
Source string
|
||||
}
|
||||
|
||||
type builder struct {
|
||||
|
|
@ -147,6 +170,31 @@ func BuildData(cfg *config.Config) (*Data, error) {
|
|||
// otherwise show a generic error message
|
||||
return nil, fmt.Errorf("invalid types were encountered while traversing the go source code, this probably means the invalid code generated isnt correct. add try adding -v to debug")
|
||||
}
|
||||
aSources := []AugmentedSource{}
|
||||
for _, s := range cfg.Sources {
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get working directory: %w", err)
|
||||
}
|
||||
outputDir := cfg.Exec.Dir()
|
||||
sourcePath := filepath.Join(wd, s.Name)
|
||||
relative, err := filepath.Rel(outputDir, sourcePath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to compute path of %s relative to %s: %w", sourcePath, outputDir, err)
|
||||
}
|
||||
relative = filepath.ToSlash(relative)
|
||||
embeddable := true
|
||||
if strings.HasPrefix(relative, "..") || s.BuiltIn {
|
||||
embeddable = false
|
||||
}
|
||||
aSources = append(aSources, AugmentedSource{
|
||||
RelativePath: relative,
|
||||
Embeddable: embeddable,
|
||||
BuiltIn: s.BuiltIn,
|
||||
Source: s.Input,
|
||||
})
|
||||
}
|
||||
s.AugmentedSources = aSources
|
||||
|
||||
return &s, nil
|
||||
}
|
||||
|
|
|
|||
10
vendor/github.com/99designs/gqlgen/codegen/directives.gotpl
generated
vendored
10
vendor/github.com/99designs/gqlgen/codegen/directives.gotpl
generated
vendored
|
|
@ -70,7 +70,7 @@ func (ec *executionContext) _mutationMiddleware(ctx context.Context, obj *ast.Op
|
|||
{{ end }}
|
||||
|
||||
{{ if .Directives.LocationDirectives "SUBSCRIPTION" }}
|
||||
func (ec *executionContext) _subscriptionMiddleware(ctx context.Context, obj *ast.OperationDefinition, next func(ctx context.Context) (interface{}, error)) func() graphql.Marshaler {
|
||||
func (ec *executionContext) _subscriptionMiddleware(ctx context.Context, obj *ast.OperationDefinition, next func(ctx context.Context) (interface{}, error)) func(ctx context.Context) graphql.Marshaler {
|
||||
for _, d := range obj.Directives {
|
||||
switch d.Name {
|
||||
{{- range $directive := .Directives.LocationDirectives "SUBSCRIPTION" }}
|
||||
|
|
@ -80,7 +80,7 @@ func (ec *executionContext) _subscriptionMiddleware(ctx context.Context, obj *as
|
|||
args, err := ec.{{ $directive.ArgsFunc }}(ctx,rawArgs)
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return func() graphql.Marshaler {
|
||||
return func(ctx context.Context) graphql.Marshaler {
|
||||
return graphql.Null
|
||||
}
|
||||
}
|
||||
|
|
@ -98,15 +98,15 @@ func (ec *executionContext) _subscriptionMiddleware(ctx context.Context, obj *as
|
|||
tmp, err := next(ctx)
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return func() graphql.Marshaler {
|
||||
return func(ctx context.Context) graphql.Marshaler {
|
||||
return graphql.Null
|
||||
}
|
||||
}
|
||||
if data, ok := tmp.(func() graphql.Marshaler); ok {
|
||||
if data, ok := tmp.(func(ctx context.Context) graphql.Marshaler); ok {
|
||||
return data
|
||||
}
|
||||
ec.Errorf(ctx, `unexpected type %T from directive, should be graphql.Marshaler`, tmp)
|
||||
return func() graphql.Marshaler {
|
||||
return func(ctx context.Context) graphql.Marshaler {
|
||||
return graphql.Null
|
||||
}
|
||||
}
|
||||
|
|
|
|||
36
vendor/github.com/99designs/gqlgen/codegen/field.go
generated
vendored
36
vendor/github.com/99designs/gqlgen/codegen/field.go
generated
vendored
|
|
@ -12,6 +12,8 @@ import (
|
|||
"github.com/99designs/gqlgen/codegen/config"
|
||||
"github.com/99designs/gqlgen/codegen/templates"
|
||||
"github.com/vektah/gqlparser/v2/ast"
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
type Field struct {
|
||||
|
|
@ -71,7 +73,7 @@ func (b *builder) buildField(obj *Object, field *ast.FieldDefinition) (*Field, e
|
|||
log.Println(err.Error())
|
||||
}
|
||||
|
||||
if f.IsResolver && !f.TypeReference.IsPtr() && f.TypeReference.IsStruct() {
|
||||
if f.IsResolver && b.Config.ResolversAlwaysReturnPointers && !f.TypeReference.IsPtr() && f.TypeReference.IsStruct() {
|
||||
f.TypeReference = b.Binder.PointerTo(f.TypeReference)
|
||||
}
|
||||
|
||||
|
|
@ -179,8 +181,8 @@ func (b *builder) bindField(obj *Object, f *Field) (errret error) {
|
|||
params = types.NewTuple(vars...)
|
||||
}
|
||||
|
||||
// Try to match target function's arguments with GraphQL field arguments
|
||||
newArgs, err := b.bindArgs(f, params)
|
||||
// Try to match target function's arguments with GraphQL field arguments.
|
||||
newArgs, err := b.bindArgs(f, sig, params)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s:%d: %w", pos.Filename, pos.Line, err)
|
||||
}
|
||||
|
|
@ -469,10 +471,11 @@ func (f *Field) GoNameUnexported() string {
|
|||
}
|
||||
|
||||
func (f *Field) ShortInvocation() string {
|
||||
caser := cases.Title(language.English, cases.NoLower)
|
||||
if f.Object.Kind == ast.InputObject {
|
||||
return fmt.Sprintf("%s().%s(ctx, &it, data)", strings.Title(f.Object.Definition.Name), f.GoFieldName)
|
||||
return fmt.Sprintf("%s().%s(ctx, &it, data)", caser.String(f.Object.Definition.Name), f.GoFieldName)
|
||||
}
|
||||
return fmt.Sprintf("%s().%s(%s)", strings.Title(f.Object.Definition.Name), f.GoFieldName, f.CallArgs())
|
||||
return fmt.Sprintf("%s().%s(%s)", caser.String(f.Object.Definition.Name), f.GoFieldName, f.CallArgs())
|
||||
}
|
||||
|
||||
func (f *Field) ArgsFunc() string {
|
||||
|
|
@ -483,6 +486,14 @@ func (f *Field) ArgsFunc() string {
|
|||
return "field_" + f.Object.Definition.Name + "_" + f.Name + "_args"
|
||||
}
|
||||
|
||||
func (f *Field) FieldContextFunc() string {
|
||||
return "fieldContext_" + f.Object.Definition.Name + "_" + f.Name
|
||||
}
|
||||
|
||||
func (f *Field) ChildFieldContextFunc(name string) string {
|
||||
return "fieldContext_" + f.TypeReference.Definition.Name + "_" + name
|
||||
}
|
||||
|
||||
func (f *Field) ResolverType() string {
|
||||
if !f.IsResolver {
|
||||
return ""
|
||||
|
|
@ -549,7 +560,20 @@ func (f *Field) CallArgs() string {
|
|||
}
|
||||
|
||||
for _, arg := range f.Args {
|
||||
args = append(args, "args["+strconv.Quote(arg.Name)+"].("+templates.CurrentImports.LookupType(arg.TypeReference.GO)+")")
|
||||
tmp := "fc.Args[" + strconv.Quote(arg.Name) + "].(" + templates.CurrentImports.LookupType(arg.TypeReference.GO) + ")"
|
||||
|
||||
if iface, ok := arg.TypeReference.GO.(*types.Interface); ok && iface.Empty() {
|
||||
tmp = fmt.Sprintf(`
|
||||
func () interface{} {
|
||||
if fc.Args["%s"] == nil {
|
||||
return nil
|
||||
}
|
||||
return fc.Args["%s"].(interface{})
|
||||
}()`, arg.Name, arg.Name,
|
||||
)
|
||||
}
|
||||
|
||||
args = append(args, tmp)
|
||||
}
|
||||
|
||||
return strings.Join(args, ", ")
|
||||
|
|
|
|||
87
vendor/github.com/99designs/gqlgen/codegen/field.gotpl
generated
vendored
87
vendor/github.com/99designs/gqlgen/codegen/field.gotpl
generated
vendored
|
|
@ -1,34 +1,21 @@
|
|||
{{- range $object := .Objects }}{{- range $field := $object.Fields }}
|
||||
|
||||
func (ec *executionContext) _{{$object.Name}}_{{$field.Name}}(ctx context.Context, field graphql.CollectedField{{ if not $object.Root }}, obj {{$object.Reference | ref}}{{end}}) (ret {{ if $object.Stream }}func(){{ end }}graphql.Marshaler) {
|
||||
func (ec *executionContext) _{{$object.Name}}_{{$field.Name}}(ctx context.Context, field graphql.CollectedField{{ if not $object.Root }}, obj {{$object.Reference | ref}}{{end}}) (ret {{ if $object.Stream }}func(ctx context.Context){{ end }}graphql.Marshaler) {
|
||||
{{- $null := "graphql.Null" }}
|
||||
{{- if $object.Stream }}
|
||||
{{- $null = "nil" }}
|
||||
{{- end }}
|
||||
fc, err := ec.{{ $field.FieldContextFunc }}(ctx, field)
|
||||
if err != nil {
|
||||
return {{ $null }}
|
||||
}
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
defer func () {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = {{ $null }}
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: {{$object.Name|quote}},
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: {{or $field.IsMethod $field.IsResolver}},
|
||||
IsResolver: {{ $field.IsResolver }},
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
{{- if $field.Args }}
|
||||
rawArgs := field.ArgumentMap(ec.Variables)
|
||||
args, err := ec.{{ $field.ArgsFunc }}(ctx,rawArgs)
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return {{ $null }}
|
||||
}
|
||||
fc.Args = args
|
||||
{{- end }}
|
||||
{{- if $.AllDirectives.LocationDirectives "FIELD" }}
|
||||
resTmp := ec._fieldMiddleware(ctx, {{if $object.Root}}nil{{else}}obj{{end}}, func(rctx context.Context) (interface{}, error) {
|
||||
{{ template "field" $field }}
|
||||
|
|
@ -51,18 +38,22 @@ func (ec *executionContext) _{{$object.Name}}_{{$field.Name}}(ctx context.Contex
|
|||
return {{ $null }}
|
||||
}
|
||||
{{- if $object.Stream }}
|
||||
return func() graphql.Marshaler {
|
||||
res, ok := <-resTmp.(<-chan {{$field.TypeReference.GO | ref}})
|
||||
if !ok {
|
||||
return func(ctx context.Context) graphql.Marshaler {
|
||||
select {
|
||||
case res, ok := <-resTmp.(<-chan {{$field.TypeReference.GO | ref}}):
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return graphql.WriterFunc(func(w io.Writer) {
|
||||
w.Write([]byte{'{'})
|
||||
graphql.MarshalString(field.Alias).MarshalGQL(w)
|
||||
w.Write([]byte{':'})
|
||||
ec.{{ $field.TypeReference.MarshalFunc }}(ctx, field.Selections, res).MarshalGQL(w)
|
||||
w.Write([]byte{'}'})
|
||||
})
|
||||
case <-ctx.Done():
|
||||
return nil
|
||||
}
|
||||
return graphql.WriterFunc(func(w io.Writer) {
|
||||
w.Write([]byte{'{'})
|
||||
graphql.MarshalString(field.Alias).MarshalGQL(w)
|
||||
w.Write([]byte{':'})
|
||||
ec.{{ $field.TypeReference.MarshalFunc }}(ctx, field.Selections, res).MarshalGQL(w)
|
||||
w.Write([]byte{'}'})
|
||||
})
|
||||
}
|
||||
{{- else }}
|
||||
res := resTmp.({{$field.TypeReference.GO | ref}})
|
||||
|
|
@ -71,6 +62,44 @@ func (ec *executionContext) _{{$object.Name}}_{{$field.Name}}(ctx context.Contex
|
|||
{{- end }}
|
||||
}
|
||||
|
||||
func (ec *executionContext) {{ $field.FieldContextFunc }}(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: {{quote $field.Object.Name}},
|
||||
Field: field,
|
||||
IsMethod: {{or $field.IsMethod $field.IsResolver}},
|
||||
IsResolver: {{ $field.IsResolver }},
|
||||
Child: func (ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
{{- if not $field.TypeReference.Definition.Fields }}
|
||||
return nil, errors.New("field of type {{ $field.TypeReference.Definition.Name }} does not have child fields")
|
||||
{{- else if ne $field.TypeReference.Definition.Kind "OBJECT" }}
|
||||
return nil, errors.New("FieldContext.Child cannot be called on type {{ $field.TypeReference.Definition.Kind }}")
|
||||
{{- else }}
|
||||
switch field.Name {
|
||||
{{- range $f := $field.TypeReference.Definition.Fields }}
|
||||
case "{{ $f.Name }}":
|
||||
return ec.{{ $field.ChildFieldContextFunc $f.Name }}(ctx, field)
|
||||
{{- end }}
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type {{ $field.TypeReference.Definition.Name }}", field.Name)
|
||||
{{- end }}
|
||||
},
|
||||
}
|
||||
{{- if $field.Args }}
|
||||
defer func () {
|
||||
if r := recover(); r != nil {
|
||||
err = ec.Recover(ctx, r)
|
||||
ec.Error(ctx, err)
|
||||
}
|
||||
}()
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
if fc.Args, err = ec.{{ $field.ArgsFunc }}(ctx, field.ArgumentMap(ec.Variables)); err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return
|
||||
}
|
||||
{{- end }}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
{{- end }}{{- end}}
|
||||
|
||||
{{ define "field" }}
|
||||
|
|
|
|||
11
vendor/github.com/99designs/gqlgen/codegen/generate.go
generated
vendored
11
vendor/github.com/99designs/gqlgen/codegen/generate.go
generated
vendored
|
|
@ -1,9 +1,10 @@
|
|||
package codegen
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
|
@ -13,6 +14,9 @@ import (
|
|||
"github.com/vektah/gqlparser/v2/ast"
|
||||
)
|
||||
|
||||
//go:embed *.gotpl
|
||||
var codegenTemplates embed.FS
|
||||
|
||||
func GenerateCode(data *Data) error {
|
||||
if !data.Config.Exec.IsDefined() {
|
||||
return fmt.Errorf("missing exec config")
|
||||
|
|
@ -36,6 +40,7 @@ func generateSingleFile(data *Data) error {
|
|||
RegionTags: true,
|
||||
GeneratedHeader: true,
|
||||
Packages: data.Config.Packages,
|
||||
TemplateFS: codegenTemplates,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -82,6 +87,7 @@ func generatePerSchema(data *Data) error {
|
|||
RegionTags: true,
|
||||
GeneratedHeader: true,
|
||||
Packages: data.Config.Packages,
|
||||
TemplateFS: codegenTemplates,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -131,7 +137,7 @@ func generateRootFile(data *Data) error {
|
|||
_, thisFile, _, _ := runtime.Caller(0)
|
||||
rootDir := filepath.Dir(thisFile)
|
||||
templatePath := filepath.Join(rootDir, "root_.gotpl")
|
||||
templateBytes, err := ioutil.ReadFile(templatePath)
|
||||
templateBytes, err := os.ReadFile(templatePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -145,6 +151,7 @@ func generateRootFile(data *Data) error {
|
|||
RegionTags: false,
|
||||
GeneratedHeader: true,
|
||||
Packages: data.Config.Packages,
|
||||
TemplateFS: codegenTemplates,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
29
vendor/github.com/99designs/gqlgen/codegen/generated!.gotpl
generated
vendored
29
vendor/github.com/99designs/gqlgen/codegen/generated!.gotpl
generated
vendored
|
|
@ -7,6 +7,7 @@
|
|||
{{ reserveImport "sync/atomic" }}
|
||||
{{ reserveImport "errors" }}
|
||||
{{ reserveImport "bytes" }}
|
||||
{{ reserveImport "embed" }}
|
||||
|
||||
{{ reserveImport "github.com/vektah/gqlparser/v2" "gqlparser" }}
|
||||
{{ reserveImport "github.com/vektah/gqlparser/v2/ast" }}
|
||||
|
|
@ -135,6 +136,13 @@
|
|||
func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler {
|
||||
rc := graphql.GetOperationContext(ctx)
|
||||
ec := executionContext{rc, e}
|
||||
inputUnmarshalMap := graphql.BuildUnmarshalerMap(
|
||||
{{- range $input := .Inputs -}}
|
||||
{{ if not $input.HasUnmarshal }}
|
||||
ec.unmarshalInput{{ $input.Name }},
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
)
|
||||
first := true
|
||||
|
||||
switch rc.Operation.Operation {
|
||||
|
|
@ -142,6 +150,7 @@
|
|||
return func(ctx context.Context) *graphql.Response {
|
||||
if !first { return nil }
|
||||
first = false
|
||||
ctx = graphql.WithUnmarshalerMap(ctx, inputUnmarshalMap)
|
||||
{{ if .Directives.LocationDirectives "QUERY" -}}
|
||||
data := ec._queryMiddleware(ctx, rc.Operation, func(ctx context.Context) (interface{}, error){
|
||||
return ec._{{.QueryRoot.Name}}(ctx, rc.Operation.SelectionSet), nil
|
||||
|
|
@ -162,6 +171,7 @@
|
|||
return func(ctx context.Context) *graphql.Response {
|
||||
if !first { return nil }
|
||||
first = false
|
||||
ctx = graphql.WithUnmarshalerMap(ctx, inputUnmarshalMap)
|
||||
{{ if .Directives.LocationDirectives "MUTATION" -}}
|
||||
data := ec._mutationMiddleware(ctx, rc.Operation, func(ctx context.Context) (interface{}, error){
|
||||
return ec._{{.MutationRoot.Name}}(ctx, rc.Operation.SelectionSet), nil
|
||||
|
|
@ -190,7 +200,7 @@
|
|||
var buf bytes.Buffer
|
||||
return func(ctx context.Context) *graphql.Response {
|
||||
buf.Reset()
|
||||
data := next()
|
||||
data := next(ctx)
|
||||
|
||||
if data == nil {
|
||||
return nil
|
||||
|
|
@ -226,9 +236,22 @@
|
|||
return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil
|
||||
}
|
||||
|
||||
{{if .HasEmbeddableSources }}
|
||||
//go:embed{{- range $source := .AugmentedSources }}{{if $source.Embeddable}} {{$source.RelativePath|quote}}{{end}}{{- end }}
|
||||
var sourcesFS embed.FS
|
||||
|
||||
func sourceData(filename string) string {
|
||||
data, err := sourcesFS.ReadFile(filename)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("codegen problem: %s not available", filename))
|
||||
}
|
||||
return string(data)
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
var sources = []*ast.Source{
|
||||
{{- range $source := .Config.Sources }}
|
||||
{Name: {{$source.Name|quote}}, Input: {{$source.Input|rawQuote}}, BuiltIn: {{$source.BuiltIn}}},
|
||||
{{- range $source := .AugmentedSources }}
|
||||
{Name: {{$source.RelativePath|quote}}, Input: {{if (not $source.Embeddable)}}{{$source.Source|rawQuote}}{{else}}sourceData({{$source.RelativePath|quote}}){{end}}, BuiltIn: {{$source.BuiltIn}}},
|
||||
{{- end }}
|
||||
}
|
||||
var parsedSchema = gqlparser.MustLoadSchema(sources...)
|
||||
|
|
|
|||
7
vendor/github.com/99designs/gqlgen/codegen/input.gotpl
generated
vendored
7
vendor/github.com/99designs/gqlgen/codegen/input.gotpl
generated
vendored
|
|
@ -14,7 +14,12 @@
|
|||
{{- end}}
|
||||
{{- end }}
|
||||
|
||||
for k, v := range asMap {
|
||||
fieldsInOrder := [...]string{ {{ range .Fields }}{{ quote .Name }},{{ end }} }
|
||||
for _, k := range fieldsInOrder {
|
||||
v, ok := asMap[k]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
switch k {
|
||||
{{- range $field := .Fields }}
|
||||
case {{$field.Name|quote}}:
|
||||
|
|
|
|||
6
vendor/github.com/99designs/gqlgen/codegen/object.go
generated
vendored
6
vendor/github.com/99designs/gqlgen/codegen/object.go
generated
vendored
|
|
@ -9,6 +9,8 @@ import (
|
|||
|
||||
"github.com/99designs/gqlgen/codegen/config"
|
||||
"github.com/vektah/gqlparser/v2/ast"
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
type GoFieldType int
|
||||
|
|
@ -38,7 +40,7 @@ func (b *builder) buildObject(typ *ast.Definition) (*Object, error) {
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: %w", typ.Name, err)
|
||||
}
|
||||
|
||||
caser := cases.Title(language.English, cases.NoLower)
|
||||
obj := &Object{
|
||||
Definition: typ,
|
||||
Root: b.Schema.Query == typ || b.Schema.Mutation == typ || b.Schema.Subscription == typ,
|
||||
|
|
@ -46,7 +48,7 @@ func (b *builder) buildObject(typ *ast.Definition) (*Object, error) {
|
|||
Stream: typ == b.Schema.Subscription,
|
||||
Directives: dirs,
|
||||
ResolverInterface: types.NewNamed(
|
||||
types.NewTypeName(0, b.Config.Exec.Pkg(), strings.Title(typ.Name)+"Resolver", nil),
|
||||
types.NewTypeName(0, b.Config.Exec.Pkg(), caser.String(typ.Name)+"Resolver", nil),
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
|
|
|
|||
11
vendor/github.com/99designs/gqlgen/codegen/object.gotpl
generated
vendored
11
vendor/github.com/99designs/gqlgen/codegen/object.gotpl
generated
vendored
|
|
@ -3,7 +3,7 @@
|
|||
var {{ $object.Name|lcFirst}}Implementors = {{$object.Implementors}}
|
||||
|
||||
{{- if .Stream }}
|
||||
func (ec *executionContext) _{{$object.Name}}(ctx context.Context, sel ast.SelectionSet) func() graphql.Marshaler {
|
||||
func (ec *executionContext) _{{$object.Name}}(ctx context.Context, sel ast.SelectionSet) func(ctx context.Context) graphql.Marshaler {
|
||||
fields := graphql.CollectFields(ec.OperationContext, sel, {{$object.Name|lcFirst}}Implementors)
|
||||
ctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{
|
||||
Object: {{$object.Name|quote}},
|
||||
|
|
@ -80,13 +80,12 @@ func (ec *executionContext) _{{$object.Name}}(ctx context.Context, sel ast.Selec
|
|||
{{end}}
|
||||
})
|
||||
{{- else }}
|
||||
innerFunc := func(ctx context.Context) (res graphql.Marshaler) {
|
||||
return ec._{{$object.Name}}_{{$field.Name}}(ctx, field{{if not $object.Root}}, obj{{end}})
|
||||
}
|
||||
{{if $object.Root}}
|
||||
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, innerFunc)
|
||||
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
|
||||
return ec._{{$object.Name}}_{{$field.Name}}(ctx, field)
|
||||
})
|
||||
{{else}}
|
||||
out.Values[i] = innerFunc(ctx)
|
||||
out.Values[i] = ec._{{$object.Name}}_{{$field.Name}}(ctx, field, obj)
|
||||
{{end}}
|
||||
|
||||
{{- if $field.TypeReference.GQL.NonNull }}
|
||||
|
|
|
|||
35
vendor/github.com/99designs/gqlgen/codegen/root_.gotpl
generated
vendored
35
vendor/github.com/99designs/gqlgen/codegen/root_.gotpl
generated
vendored
|
|
@ -7,6 +7,7 @@
|
|||
{{ reserveImport "sync/atomic" }}
|
||||
{{ reserveImport "errors" }}
|
||||
{{ reserveImport "bytes" }}
|
||||
{{ reserveImport "embed" }}
|
||||
|
||||
{{ reserveImport "github.com/vektah/gqlparser/v2" "gqlparser" }}
|
||||
{{ reserveImport "github.com/vektah/gqlparser/v2/ast" }}
|
||||
|
|
@ -34,6 +35,11 @@ type ResolverRoot interface {
|
|||
{{ucFirst $object.Name}}() {{ucFirst $object.Name}}Resolver
|
||||
{{ end }}
|
||||
{{- end }}
|
||||
{{- range $object := .Inputs -}}
|
||||
{{ if $object.HasResolvers -}}
|
||||
{{ucFirst $object.Name}}() {{ucFirst $object.Name}}Resolver
|
||||
{{ end }}
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
type DirectiveRoot struct {
|
||||
|
|
@ -102,6 +108,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
|||
func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler {
|
||||
rc := graphql.GetOperationContext(ctx)
|
||||
ec := executionContext{rc, e}
|
||||
inputUnmarshalMap := graphql.BuildUnmarshalerMap(
|
||||
{{- range $input := .Inputs -}}
|
||||
{{ if not $input.HasUnmarshal }}
|
||||
ec.unmarshalInput{{ $input.Name }},
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
)
|
||||
first := true
|
||||
|
||||
switch rc.Operation.Operation {
|
||||
|
|
@ -109,6 +122,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler {
|
|||
return func(ctx context.Context) *graphql.Response {
|
||||
if !first { return nil }
|
||||
first = false
|
||||
ctx = graphql.WithUnmarshalerMap(ctx, inputUnmarshalMap)
|
||||
{{ if .Directives.LocationDirectives "QUERY" -}}
|
||||
data := ec._queryMiddleware(ctx, rc.Operation, func(ctx context.Context) (interface{}, error){
|
||||
return ec._{{.QueryRoot.Name}}(ctx, rc.Operation.SelectionSet), nil
|
||||
|
|
@ -129,6 +143,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler {
|
|||
return func(ctx context.Context) *graphql.Response {
|
||||
if !first { return nil }
|
||||
first = false
|
||||
ctx = graphql.WithUnmarshalerMap(ctx, inputUnmarshalMap)
|
||||
{{ if .Directives.LocationDirectives "MUTATION" -}}
|
||||
data := ec._mutationMiddleware(ctx, rc.Operation, func(ctx context.Context) (interface{}, error){
|
||||
return ec._{{.MutationRoot.Name}}(ctx, rc.Operation.SelectionSet), nil
|
||||
|
|
@ -157,7 +172,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler {
|
|||
var buf bytes.Buffer
|
||||
return func(ctx context.Context) *graphql.Response {
|
||||
buf.Reset()
|
||||
data := next()
|
||||
data := next(ctx)
|
||||
|
||||
if data == nil {
|
||||
return nil
|
||||
|
|
@ -193,9 +208,23 @@ func (ec *executionContext) introspectType(name string) (*introspection.Type, er
|
|||
return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil
|
||||
}
|
||||
|
||||
|
||||
{{if .HasEmbeddableSources }}
|
||||
//go:embed{{- range $source := .AugmentedSources }}{{if $source.Embeddable}} {{$source.RelativePath|quote}}{{end}}{{- end }}
|
||||
var sourcesFS embed.FS
|
||||
|
||||
func sourceData(filename string) string {
|
||||
data, err := sourcesFS.ReadFile(filename)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("codegen problem: %s not available", filename))
|
||||
}
|
||||
return string(data)
|
||||
}
|
||||
{{- end}}
|
||||
|
||||
var sources = []*ast.Source{
|
||||
{{- range $source := .Config.Sources }}
|
||||
{Name: {{$source.Name|quote}}, Input: {{$source.Input|rawQuote}}, BuiltIn: {{$source.BuiltIn}}},
|
||||
{{- range $source := .AugmentedSources }}
|
||||
{Name: {{$source.RelativePath|quote}}, Input: {{if (not $source.Embeddable)}}{{$source.Source|rawQuote}}{{else}}sourceData({{$source.RelativePath|quote}}){{end}}, BuiltIn: {{$source.BuiltIn}}},
|
||||
{{- end }}
|
||||
}
|
||||
var parsedSchema = gqlparser.MustLoadSchema(sources...)
|
||||
|
|
|
|||
315
vendor/github.com/99designs/gqlgen/codegen/templates/templates.go
generated
vendored
315
vendor/github.com/99designs/gqlgen/codegen/templates/templates.go
generated
vendored
|
|
@ -4,14 +4,16 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"go/types"
|
||||
"io/ioutil"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"text/template"
|
||||
"unicode"
|
||||
|
||||
|
|
@ -36,6 +38,11 @@ type Options struct {
|
|||
// the plugin processor will look for .gotpl files
|
||||
// in the same directory of where you wrote the plugin.
|
||||
Template string
|
||||
|
||||
// Use the go:embed API to collect all the template files you want to pass into Render
|
||||
// this is an alternative to passing the Template option
|
||||
TemplateFS fs.FS
|
||||
|
||||
// Filename is the name of the file that will be
|
||||
// written to the system disk once the template is rendered.
|
||||
Filename string
|
||||
|
|
@ -53,6 +60,12 @@ type Options struct {
|
|||
Packages *code.Packages
|
||||
}
|
||||
|
||||
var (
|
||||
modelNamesMu sync.Mutex
|
||||
modelNames = make(map[string]string, 0)
|
||||
goNameRe = regexp.MustCompile("[^a-zA-Z0-9_]")
|
||||
)
|
||||
|
||||
// Render renders a gql plugin template from the given Options. Render is an
|
||||
// abstraction of the text/template package that makes it easier to write gqlgen
|
||||
// plugins. If Options.Template is empty, the Render function will look for `.gotpl`
|
||||
|
|
@ -63,55 +76,27 @@ func Render(cfg Options) error {
|
|||
}
|
||||
CurrentImports = &Imports{packages: cfg.Packages, destDir: filepath.Dir(cfg.Filename)}
|
||||
|
||||
// load path relative to calling source file
|
||||
_, callerFile, _, _ := runtime.Caller(1)
|
||||
rootDir := filepath.Dir(callerFile)
|
||||
|
||||
funcs := Funcs()
|
||||
for n, f := range cfg.Funcs {
|
||||
funcs[n] = f
|
||||
}
|
||||
|
||||
t := template.New("").Funcs(funcs)
|
||||
t, err := parseTemplates(cfg, t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var roots []string
|
||||
if cfg.Template != "" {
|
||||
var err error
|
||||
t, err = t.New("template.gotpl").Parse(cfg.Template)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error with provided template: %w", err)
|
||||
roots := make([]string, 0, len(t.Templates()))
|
||||
for _, template := range t.Templates() {
|
||||
// templates that end with _.gotpl are special files we don't want to include
|
||||
if strings.HasSuffix(template.Name(), "_.gotpl") ||
|
||||
// filter out templates added with {{ template xxx }} syntax inside the template file
|
||||
!strings.HasSuffix(template.Name(), ".gotpl") {
|
||||
continue
|
||||
}
|
||||
roots = append(roots, "template.gotpl")
|
||||
} else {
|
||||
// load all the templates in the directory
|
||||
err := filepath.Walk(rootDir, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
name := filepath.ToSlash(strings.TrimPrefix(path, rootDir+string(os.PathSeparator)))
|
||||
if !strings.HasSuffix(info.Name(), ".gotpl") {
|
||||
return nil
|
||||
}
|
||||
// omit any templates with "_" at the end of their name, which are meant for specific contexts only
|
||||
if strings.HasSuffix(info.Name(), "_.gotpl") {
|
||||
return nil
|
||||
}
|
||||
b, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
t, err = t.New(name).Parse(string(b))
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: %w", cfg.Filename, err)
|
||||
}
|
||||
|
||||
roots = append(roots, name)
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("locating templates: %w", err)
|
||||
}
|
||||
roots = append(roots, template.Name())
|
||||
}
|
||||
|
||||
// then execute all the important looking ones in order, adding them to the same file
|
||||
|
|
@ -125,6 +110,7 @@ func Render(cfg Options) error {
|
|||
}
|
||||
return roots[i] < roots[j]
|
||||
})
|
||||
|
||||
var buf bytes.Buffer
|
||||
for _, root := range roots {
|
||||
if cfg.RegionTags {
|
||||
|
|
@ -156,7 +142,7 @@ func Render(cfg Options) error {
|
|||
result.WriteString("import (\n")
|
||||
result.WriteString(CurrentImports.String())
|
||||
result.WriteString(")\n")
|
||||
_, err := buf.WriteTo(&result)
|
||||
_, err = buf.WriteTo(&result)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -171,6 +157,34 @@ func Render(cfg Options) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func parseTemplates(cfg Options, t *template.Template) (*template.Template, error) {
|
||||
if cfg.Template != "" {
|
||||
var err error
|
||||
t, err = t.New("template.gotpl").Parse(cfg.Template)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error with provided template: %w", err)
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
|
||||
var fileSystem fs.FS
|
||||
if cfg.TemplateFS != nil {
|
||||
fileSystem = cfg.TemplateFS
|
||||
} else {
|
||||
// load path relative to calling source file
|
||||
_, callerFile, _, _ := runtime.Caller(1)
|
||||
rootDir := filepath.Dir(callerFile)
|
||||
fileSystem = os.DirFS(rootDir)
|
||||
}
|
||||
|
||||
t, err := t.ParseFS(fileSystem, "*.gotpl")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("locating templates: %w", err)
|
||||
}
|
||||
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func center(width int, pad string, s string) string {
|
||||
if len(s)+2 > width {
|
||||
return s
|
||||
|
|
@ -182,20 +196,22 @@ func center(width int, pad string, s string) string {
|
|||
|
||||
func Funcs() template.FuncMap {
|
||||
return template.FuncMap{
|
||||
"ucFirst": UcFirst,
|
||||
"lcFirst": LcFirst,
|
||||
"quote": strconv.Quote,
|
||||
"rawQuote": rawQuote,
|
||||
"dump": Dump,
|
||||
"ref": ref,
|
||||
"ts": TypeIdentifier,
|
||||
"call": Call,
|
||||
"prefixLines": prefixLines,
|
||||
"notNil": notNil,
|
||||
"reserveImport": CurrentImports.Reserve,
|
||||
"lookupImport": CurrentImports.Lookup,
|
||||
"go": ToGo,
|
||||
"goPrivate": ToGoPrivate,
|
||||
"ucFirst": UcFirst,
|
||||
"lcFirst": LcFirst,
|
||||
"quote": strconv.Quote,
|
||||
"rawQuote": rawQuote,
|
||||
"dump": Dump,
|
||||
"ref": ref,
|
||||
"ts": TypeIdentifier,
|
||||
"call": Call,
|
||||
"prefixLines": prefixLines,
|
||||
"notNil": notNil,
|
||||
"reserveImport": CurrentImports.Reserve,
|
||||
"lookupImport": CurrentImports.Lookup,
|
||||
"go": ToGo,
|
||||
"goPrivate": ToGoPrivate,
|
||||
"goModelName": ToGoModelName,
|
||||
"goPrivateModelName": ToGoPrivateModelName,
|
||||
"add": func(a, b int) int {
|
||||
return a + b
|
||||
},
|
||||
|
|
@ -285,25 +301,154 @@ func Call(p *types.Func) string {
|
|||
return pkg + p.Name()
|
||||
}
|
||||
|
||||
func resetModelNames() {
|
||||
modelNamesMu.Lock()
|
||||
defer modelNamesMu.Unlock()
|
||||
modelNames = make(map[string]string, 0)
|
||||
}
|
||||
|
||||
func buildGoModelNameKey(parts []string) string {
|
||||
const sep = ":"
|
||||
return strings.Join(parts, sep)
|
||||
}
|
||||
|
||||
func goModelName(primaryToGoFunc func(string) string, parts []string) string {
|
||||
modelNamesMu.Lock()
|
||||
defer modelNamesMu.Unlock()
|
||||
|
||||
var (
|
||||
goNameKey string
|
||||
partLen int
|
||||
|
||||
nameExists = func(n string) bool {
|
||||
for _, v := range modelNames {
|
||||
if n == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
applyToGoFunc = func(parts []string) string {
|
||||
var out string
|
||||
switch len(parts) {
|
||||
case 0:
|
||||
return ""
|
||||
case 1:
|
||||
return primaryToGoFunc(parts[0])
|
||||
default:
|
||||
out = primaryToGoFunc(parts[0])
|
||||
}
|
||||
for _, p := range parts[1:] {
|
||||
out = fmt.Sprintf("%s%s", out, ToGo(p))
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
applyValidGoName = func(parts []string) string {
|
||||
var out string
|
||||
for _, p := range parts {
|
||||
out = fmt.Sprintf("%s%s", out, replaceInvalidCharacters(p))
|
||||
}
|
||||
return out
|
||||
}
|
||||
)
|
||||
|
||||
// build key for this entity
|
||||
goNameKey = buildGoModelNameKey(parts)
|
||||
|
||||
// determine if we've seen this entity before, and reuse if so
|
||||
if goName, ok := modelNames[goNameKey]; ok {
|
||||
return goName
|
||||
}
|
||||
|
||||
// attempt first pass
|
||||
if goName := applyToGoFunc(parts); !nameExists(goName) {
|
||||
modelNames[goNameKey] = goName
|
||||
return goName
|
||||
}
|
||||
|
||||
// determine number of parts
|
||||
partLen = len(parts)
|
||||
|
||||
// if there is only 1 part, append incrementing number until no conflict
|
||||
if partLen == 1 {
|
||||
base := applyToGoFunc(parts)
|
||||
for i := 0; ; i++ {
|
||||
tmp := fmt.Sprintf("%s%d", base, i)
|
||||
if !nameExists(tmp) {
|
||||
modelNames[goNameKey] = tmp
|
||||
return tmp
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// best effort "pretty" name
|
||||
for i := partLen - 1; i >= 1; i-- {
|
||||
tmp := fmt.Sprintf("%s%s", applyToGoFunc(parts[0:i]), applyValidGoName(parts[i:]))
|
||||
if !nameExists(tmp) {
|
||||
modelNames[goNameKey] = tmp
|
||||
return tmp
|
||||
}
|
||||
}
|
||||
|
||||
// finally, fallback to just adding an incrementing number
|
||||
base := applyToGoFunc(parts)
|
||||
for i := 0; ; i++ {
|
||||
tmp := fmt.Sprintf("%s%d", base, i)
|
||||
if !nameExists(tmp) {
|
||||
modelNames[goNameKey] = tmp
|
||||
return tmp
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ToGoModelName(parts ...string) string {
|
||||
return goModelName(ToGo, parts)
|
||||
}
|
||||
|
||||
func ToGoPrivateModelName(parts ...string) string {
|
||||
return goModelName(ToGoPrivate, parts)
|
||||
}
|
||||
|
||||
func replaceInvalidCharacters(in string) string {
|
||||
return goNameRe.ReplaceAllLiteralString(in, "_")
|
||||
}
|
||||
|
||||
func wordWalkerFunc(private bool, nameRunes *[]rune) func(*wordInfo) {
|
||||
return func(info *wordInfo) {
|
||||
word := info.Word
|
||||
|
||||
switch {
|
||||
case private && info.WordOffset == 0:
|
||||
if strings.ToUpper(word) == word || strings.ToLower(word) == word {
|
||||
// ID → id, CAMEL → camel
|
||||
word = strings.ToLower(info.Word)
|
||||
} else {
|
||||
// ITicket → iTicket
|
||||
word = LcFirst(info.Word)
|
||||
}
|
||||
|
||||
case info.MatchCommonInitial:
|
||||
word = strings.ToUpper(word)
|
||||
|
||||
case !info.HasCommonInitial && (strings.ToUpper(word) == word || strings.ToLower(word) == word):
|
||||
// FOO or foo → Foo
|
||||
// FOo → FOo
|
||||
word = UcFirst(strings.ToLower(word))
|
||||
}
|
||||
|
||||
*nameRunes = append(*nameRunes, []rune(word)...)
|
||||
}
|
||||
}
|
||||
|
||||
func ToGo(name string) string {
|
||||
if name == "_" {
|
||||
return "_"
|
||||
}
|
||||
runes := make([]rune, 0, len(name))
|
||||
|
||||
wordWalker(name, func(info *wordInfo) {
|
||||
word := info.Word
|
||||
if info.MatchCommonInitial {
|
||||
word = strings.ToUpper(word)
|
||||
} else if !info.HasCommonInitial {
|
||||
if strings.ToUpper(word) == word || strings.ToLower(word) == word {
|
||||
// FOO or foo → Foo
|
||||
// FOo → FOo
|
||||
word = UcFirst(strings.ToLower(word))
|
||||
}
|
||||
}
|
||||
runes = append(runes, []rune(word)...)
|
||||
})
|
||||
wordWalker(name, wordWalkerFunc(false, &runes))
|
||||
|
||||
return string(runes)
|
||||
}
|
||||
|
|
@ -314,31 +459,13 @@ func ToGoPrivate(name string) string {
|
|||
}
|
||||
runes := make([]rune, 0, len(name))
|
||||
|
||||
first := true
|
||||
wordWalker(name, func(info *wordInfo) {
|
||||
word := info.Word
|
||||
switch {
|
||||
case first:
|
||||
if strings.ToUpper(word) == word || strings.ToLower(word) == word {
|
||||
// ID → id, CAMEL → camel
|
||||
word = strings.ToLower(info.Word)
|
||||
} else {
|
||||
// ITicket → iTicket
|
||||
word = LcFirst(info.Word)
|
||||
}
|
||||
first = false
|
||||
case info.MatchCommonInitial:
|
||||
word = strings.ToUpper(word)
|
||||
case !info.HasCommonInitial:
|
||||
word = UcFirst(strings.ToLower(word))
|
||||
}
|
||||
runes = append(runes, []rune(word)...)
|
||||
})
|
||||
wordWalker(name, wordWalkerFunc(true, &runes))
|
||||
|
||||
return sanitizeKeywords(string(runes))
|
||||
}
|
||||
|
||||
type wordInfo struct {
|
||||
WordOffset int
|
||||
Word string
|
||||
MatchCommonInitial bool
|
||||
HasCommonInitial bool
|
||||
|
|
@ -348,7 +475,7 @@ type wordInfo struct {
|
|||
// https://github.com/golang/lint/blob/06c8688daad7faa9da5a0c2f163a3d14aac986ca/lint.go#L679
|
||||
func wordWalker(str string, f func(*wordInfo)) {
|
||||
runes := []rune(strings.TrimFunc(str, isDelimiter))
|
||||
w, i := 0, 0 // index of start of word, scan
|
||||
w, i, wo := 0, 0, 0 // index of start of word, scan, word offset
|
||||
hasCommonInitial := false
|
||||
for i+1 <= len(runes) {
|
||||
eow := false // whether we hit the end of a word
|
||||
|
|
@ -396,12 +523,14 @@ func wordWalker(str string, f func(*wordInfo)) {
|
|||
}
|
||||
|
||||
f(&wordInfo{
|
||||
WordOffset: wo,
|
||||
Word: word,
|
||||
MatchCommonInitial: matchCommonInitial,
|
||||
HasCommonInitial: hasCommonInitial,
|
||||
})
|
||||
hasCommonInitial = false
|
||||
w = i
|
||||
wo++
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -576,7 +705,7 @@ func resolveName(name string, skip int) string {
|
|||
func render(filename string, tpldata interface{}) (*bytes.Buffer, error) {
|
||||
t := template.New("").Funcs(Funcs())
|
||||
|
||||
b, err := ioutil.ReadFile(filename)
|
||||
b, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -602,7 +731,7 @@ func write(filename string, b []byte, packages *code.Packages) error {
|
|||
formatted = b
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(filename, formatted, 0o644)
|
||||
err = os.WriteFile(filename, formatted, 0o644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to write %s: %w", filename, err)
|
||||
}
|
||||
|
|
|
|||
1
vendor/github.com/99designs/gqlgen/codegen/templates/test.gotpl
generated
vendored
Normal file
1
vendor/github.com/99designs/gqlgen/codegen/templates/test.gotpl
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
this is my test package
|
||||
1
vendor/github.com/99designs/gqlgen/codegen/templates/test_.gotpl
generated
vendored
Normal file
1
vendor/github.com/99designs/gqlgen/codegen/templates/test_.gotpl
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
this will not be included
|
||||
4
vendor/github.com/99designs/gqlgen/codegen/type.gotpl
generated
vendored
4
vendor/github.com/99designs/gqlgen/codegen/type.gotpl
generated
vendored
|
|
@ -151,7 +151,7 @@
|
|||
if v == nil {
|
||||
{{- if $type.GQL.NonNull }}
|
||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
ec.Errorf(ctx, "the requested element is null which the schema does not allow")
|
||||
}
|
||||
{{- end }}
|
||||
return graphql.Null
|
||||
|
|
@ -174,7 +174,7 @@
|
|||
{{- if $type.GQL.NonNull }}
|
||||
if res == graphql.Null {
|
||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
ec.Errorf(ctx, "the requested element is null which the schema does not allow")
|
||||
}
|
||||
}
|
||||
{{- end }}
|
||||
|
|
|
|||
19
vendor/github.com/99designs/gqlgen/graphql/context_field.go
generated
vendored
19
vendor/github.com/99designs/gqlgen/graphql/context_field.go
generated
vendored
|
|
@ -30,6 +30,25 @@ type FieldContext struct {
|
|||
IsMethod bool
|
||||
// IsResolver indicates if the field has a user-specified resolver
|
||||
IsResolver bool
|
||||
// Child allows getting a child FieldContext by its field collection description.
|
||||
// Note that, the returned child FieldContext represents the context as it was
|
||||
// before the execution of the field resolver. For example:
|
||||
//
|
||||
// srv.AroundFields(func(ctx context.Context, next graphql.Resolver) (interface{}, error) {
|
||||
// fc := graphql.GetFieldContext(ctx)
|
||||
// op := graphql.GetOperationContext(ctx)
|
||||
// collected := graphql.CollectFields(opCtx, fc.Field.Selections, []string{"User"})
|
||||
//
|
||||
// child, err := fc.Child(ctx, collected[0])
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// fmt.Println("child context %q with args: %v", child.Field.Name, child.Args)
|
||||
//
|
||||
// return next(ctx)
|
||||
// })
|
||||
//
|
||||
Child func(context.Context, CollectedField) (*FieldContext, error)
|
||||
}
|
||||
|
||||
type FieldStats struct {
|
||||
|
|
|
|||
2
vendor/github.com/99designs/gqlgen/graphql/context_operation.go
generated
vendored
2
vendor/github.com/99designs/gqlgen/graphql/context_operation.go
generated
vendored
|
|
@ -3,6 +3,7 @@ package graphql
|
|||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/vektah/gqlparser/v2/ast"
|
||||
)
|
||||
|
|
@ -15,6 +16,7 @@ type OperationContext struct {
|
|||
Variables map[string]interface{}
|
||||
OperationName string
|
||||
Doc *ast.QueryDocument
|
||||
Headers http.Header
|
||||
|
||||
Operation *ast.OperationDefinition
|
||||
DisableIntrospection bool
|
||||
|
|
|
|||
19
vendor/github.com/99designs/gqlgen/graphql/errcode/codes.go
generated
vendored
19
vendor/github.com/99designs/gqlgen/graphql/errcode/codes.go
generated
vendored
|
|
@ -23,18 +23,27 @@ var codeType = map[string]ErrorKind{
|
|||
ParseFailed: KindProtocol,
|
||||
}
|
||||
|
||||
// RegisterErrorType should be called by extensions that want to customize the http status codes for errors they return
|
||||
// RegisterErrorType should be called by extensions that want to customize the http status codes for
|
||||
// errors they return
|
||||
func RegisterErrorType(code string, kind ErrorKind) {
|
||||
codeType[code] = kind
|
||||
}
|
||||
|
||||
// Set the error code on a given graphql error extension
|
||||
func Set(err *gqlerror.Error, value string) {
|
||||
if err.Extensions == nil {
|
||||
err.Extensions = map[string]interface{}{}
|
||||
func Set(err error, value string) {
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
gqlErr, ok := err.(*gqlerror.Error)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
err.Extensions["code"] = value
|
||||
if gqlErr.Extensions == nil {
|
||||
gqlErr.Extensions = map[string]interface{}{}
|
||||
}
|
||||
|
||||
gqlErr.Extensions["code"] = value
|
||||
}
|
||||
|
||||
// get the kind of the first non User error, defaults to User if no errors have a custom extension
|
||||
|
|
|
|||
3
vendor/github.com/99designs/gqlgen/graphql/error.go
generated
vendored
3
vendor/github.com/99designs/gqlgen/graphql/error.go
generated
vendored
|
|
@ -26,7 +26,8 @@ func ErrorOnPath(ctx context.Context, err error) error {
|
|||
if gqlErr.Path == nil {
|
||||
gqlErr.Path = GetPath(ctx)
|
||||
}
|
||||
return gqlErr
|
||||
// Return the original error to avoid losing any attached annotation
|
||||
return err
|
||||
}
|
||||
return gqlerror.WrapPath(GetPath(ctx), err)
|
||||
}
|
||||
|
|
|
|||
5
vendor/github.com/99designs/gqlgen/graphql/executable_schema.go
generated
vendored
5
vendor/github.com/99designs/gqlgen/graphql/executable_schema.go
generated
vendored
|
|
@ -118,6 +118,11 @@ func getOrCreateAndAppendField(c *[]CollectedField, name string, alias string, o
|
|||
return &(*c)[i]
|
||||
}
|
||||
}
|
||||
for _, ifc := range cf.ObjectDefinition.Interfaces {
|
||||
if ifc == objectDefinition.Name {
|
||||
return &(*c)[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
57
vendor/github.com/99designs/gqlgen/graphql/executor/executor.go
generated
vendored
57
vendor/github.com/99designs/gqlgen/graphql/executor/executor.go
generated
vendored
|
|
@ -37,7 +37,10 @@ func New(es graphql.ExecutableSchema) *Executor {
|
|||
return e
|
||||
}
|
||||
|
||||
func (e *Executor) CreateOperationContext(ctx context.Context, params *graphql.RawParams) (*graphql.OperationContext, gqlerror.List) {
|
||||
func (e *Executor) CreateOperationContext(
|
||||
ctx context.Context,
|
||||
params *graphql.RawParams,
|
||||
) (*graphql.OperationContext, gqlerror.List) {
|
||||
rc := &graphql.OperationContext{
|
||||
DisableIntrospection: true,
|
||||
RecoverFunc: e.recoverFunc,
|
||||
|
|
@ -58,6 +61,7 @@ func (e *Executor) CreateOperationContext(ctx context.Context, params *graphql.R
|
|||
|
||||
rc.RawQuery = params.Query
|
||||
rc.OperationName = params.OperationName
|
||||
rc.Headers = params.Headers
|
||||
|
||||
var listErr gqlerror.List
|
||||
rc.Doc, listErr = e.parseQuery(ctx, &rc.Stats, params.Query)
|
||||
|
|
@ -67,15 +71,21 @@ func (e *Executor) CreateOperationContext(ctx context.Context, params *graphql.R
|
|||
|
||||
rc.Operation = rc.Doc.Operations.ForName(params.OperationName)
|
||||
if rc.Operation == nil {
|
||||
return rc, gqlerror.List{gqlerror.Errorf("operation %s not found", params.OperationName)}
|
||||
}
|
||||
|
||||
var err *gqlerror.Error
|
||||
rc.Variables, err = validator.VariableValues(e.es.Schema(), rc.Operation, params.Variables)
|
||||
if err != nil {
|
||||
err := gqlerror.Errorf("operation %s not found", params.OperationName)
|
||||
errcode.Set(err, errcode.ValidationFailed)
|
||||
return rc, gqlerror.List{err}
|
||||
}
|
||||
|
||||
var err error
|
||||
rc.Variables, err = validator.VariableValues(e.es.Schema(), rc.Operation, params.Variables)
|
||||
|
||||
if err != nil {
|
||||
gqlErr, ok := err.(*gqlerror.Error)
|
||||
if ok {
|
||||
errcode.Set(gqlErr, errcode.ValidationFailed)
|
||||
return rc, gqlerror.List{gqlErr}
|
||||
}
|
||||
}
|
||||
rc.Stats.Validation.End = graphql.Now()
|
||||
|
||||
for _, p := range e.ext.operationContextMutators {
|
||||
|
|
@ -87,7 +97,10 @@ func (e *Executor) CreateOperationContext(ctx context.Context, params *graphql.R
|
|||
return rc, nil
|
||||
}
|
||||
|
||||
func (e *Executor) DispatchOperation(ctx context.Context, rc *graphql.OperationContext) (graphql.ResponseHandler, context.Context) {
|
||||
func (e *Executor) DispatchOperation(
|
||||
ctx context.Context,
|
||||
rc *graphql.OperationContext,
|
||||
) (graphql.ResponseHandler, context.Context) {
|
||||
ctx = graphql.WithOperationContext(ctx, rc)
|
||||
|
||||
var innerCtx context.Context
|
||||
|
|
@ -130,7 +143,7 @@ func (e *Executor) DispatchError(ctx context.Context, list gqlerror.List) *graph
|
|||
|
||||
resp := e.ext.responseMiddleware(ctx, func(ctx context.Context) *graphql.Response {
|
||||
resp := &graphql.Response{
|
||||
Errors: list,
|
||||
Errors: graphql.GetErrors(ctx),
|
||||
}
|
||||
resp.Extensions = graphql.GetExtensions(ctx)
|
||||
return resp
|
||||
|
|
@ -139,7 +152,7 @@ func (e *Executor) DispatchError(ctx context.Context, list gqlerror.List) *graph
|
|||
return resp
|
||||
}
|
||||
|
||||
func (e *Executor) PresentRecoveredError(ctx context.Context, err interface{}) *gqlerror.Error {
|
||||
func (e *Executor) PresentRecoveredError(ctx context.Context, err interface{}) error {
|
||||
return e.errorPresenter(ctx, e.recoverFunc(ctx, err))
|
||||
}
|
||||
|
||||
|
|
@ -157,9 +170,14 @@ func (e *Executor) SetRecoverFunc(f graphql.RecoverFunc) {
|
|||
|
||||
// parseQuery decodes the incoming query and validates it, pulling from cache if present.
|
||||
//
|
||||
// NOTE: This should NOT look at variables, they will change per request. It should only parse and validate
|
||||
// NOTE: This should NOT look at variables, they will change per request. It should only parse and
|
||||
// validate
|
||||
// the raw query string.
|
||||
func (e *Executor) parseQuery(ctx context.Context, stats *graphql.Stats, query string) (*ast.QueryDocument, gqlerror.List) {
|
||||
func (e *Executor) parseQuery(
|
||||
ctx context.Context,
|
||||
stats *graphql.Stats,
|
||||
query string,
|
||||
) (*ast.QueryDocument, gqlerror.List) {
|
||||
stats.Parsing.Start = graphql.Now()
|
||||
|
||||
if doc, ok := e.queryCache.Get(ctx, query); ok {
|
||||
|
|
@ -172,12 +190,23 @@ func (e *Executor) parseQuery(ctx context.Context, stats *graphql.Stats, query s
|
|||
|
||||
doc, err := parser.ParseQuery(&ast.Source{Input: query})
|
||||
if err != nil {
|
||||
errcode.Set(err, errcode.ParseFailed)
|
||||
return nil, gqlerror.List{err}
|
||||
gqlErr, ok := err.(*gqlerror.Error)
|
||||
if ok {
|
||||
errcode.Set(gqlErr, errcode.ParseFailed)
|
||||
return nil, gqlerror.List{gqlErr}
|
||||
}
|
||||
}
|
||||
stats.Parsing.End = graphql.Now()
|
||||
|
||||
stats.Validation.Start = graphql.Now()
|
||||
|
||||
if len(doc.Operations) == 0 {
|
||||
err = gqlerror.Errorf("no operation provided")
|
||||
gqlErr, _ := err.(*gqlerror.Error)
|
||||
errcode.Set(err, errcode.ValidationFailed)
|
||||
return nil, gqlerror.List{gqlErr}
|
||||
}
|
||||
|
||||
listErr := validator.Validate(e.es.Schema(), doc)
|
||||
if len(listErr) != 0 {
|
||||
for _, e := range listErr {
|
||||
|
|
|
|||
17
vendor/github.com/99designs/gqlgen/graphql/handler.go
generated
vendored
17
vendor/github.com/99designs/gqlgen/graphql/handler.go
generated
vendored
|
|
@ -27,6 +27,7 @@ type (
|
|||
OperationName string `json:"operationName"`
|
||||
Variables map[string]interface{} `json:"variables"`
|
||||
Extensions map[string]interface{} `json:"extensions"`
|
||||
Headers http.Header `json:"headers"`
|
||||
|
||||
ReadTime TraceTiming `json:"-"`
|
||||
}
|
||||
|
|
@ -41,14 +42,14 @@ type (
|
|||
// Its important to understand the lifecycle of a graphql request and the terminology we use in gqlgen
|
||||
// before working with these
|
||||
//
|
||||
// +--- REQUEST POST /graphql --------------------------------------------+
|
||||
// | +- OPERATION query OpName { viewer { name } } -----------------------+ |
|
||||
// | | RESPONSE { "data": { "viewer": { "name": "bob" } } } | |
|
||||
// | +- OPERATION subscription OpName2 { chat { message } } --------------+ |
|
||||
// | | RESPONSE { "data": { "chat": { "message": "hello" } } } | |
|
||||
// | | RESPONSE { "data": { "chat": { "message": "byee" } } } | |
|
||||
// | +--------------------------------------------------------------------+ |
|
||||
// +------------------------------------------------------------------------+
|
||||
// +--- REQUEST POST /graphql --------------------------------------------+
|
||||
// | +- OPERATION query OpName { viewer { name } } -----------------------+ |
|
||||
// | | RESPONSE { "data": { "viewer": { "name": "bob" } } } | |
|
||||
// | +- OPERATION subscription OpName2 { chat { message } } --------------+ |
|
||||
// | | RESPONSE { "data": { "chat": { "message": "hello" } } } | |
|
||||
// | | RESPONSE { "data": { "chat": { "message": "byee" } } } | |
|
||||
// | +--------------------------------------------------------------------+ |
|
||||
// +------------------------------------------------------------------------+
|
||||
HandlerExtension interface {
|
||||
// ExtensionName should be a CamelCase string version of the extension which may be shown in stats and logging.
|
||||
ExtensionName() string
|
||||
|
|
|
|||
3
vendor/github.com/99designs/gqlgen/graphql/handler/server.go
generated
vendored
3
vendor/github.com/99designs/gqlgen/graphql/handler/server.go
generated
vendored
|
|
@ -102,7 +102,8 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
err := s.exec.PresentRecoveredError(r.Context(), err)
|
||||
resp := &graphql.Response{Errors: []*gqlerror.Error{err}}
|
||||
gqlErr, _ := err.(*gqlerror.Error)
|
||||
resp := &graphql.Response{Errors: []*gqlerror.Error{gqlErr}}
|
||||
b, _ := json.Marshal(resp)
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
w.Write(b)
|
||||
|
|
|
|||
196
vendor/github.com/99designs/gqlgen/graphql/handler/transport/http_form.go
generated
vendored
196
vendor/github.com/99designs/gqlgen/graphql/handler/transport/http_form.go
generated
vendored
|
|
@ -3,11 +3,9 @@ package transport
|
|||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"mime"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/99designs/gqlgen/graphql"
|
||||
)
|
||||
|
|
@ -64,133 +62,145 @@ func (f MultipartForm) Do(w http.ResponseWriter, r *http.Request, exec graphql.G
|
|||
return
|
||||
}
|
||||
r.Body = http.MaxBytesReader(w, r.Body, f.maxUploadSize())
|
||||
if err = r.ParseMultipartForm(f.maxMemory()); err != nil {
|
||||
defer r.Body.Close()
|
||||
|
||||
mr, err := r.MultipartReader()
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
if strings.Contains(err.Error(), "request body too large") {
|
||||
writeJsonError(w, "failed to parse multipart form, request body too large")
|
||||
return
|
||||
}
|
||||
writeJsonError(w, "failed to parse multipart form")
|
||||
return
|
||||
}
|
||||
defer r.Body.Close()
|
||||
|
||||
part, err := mr.NextPart()
|
||||
if err != nil || part.FormName() != "operations" {
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
writeJsonError(w, "first part must be operations")
|
||||
return
|
||||
}
|
||||
|
||||
var params graphql.RawParams
|
||||
|
||||
if err = jsonDecode(strings.NewReader(r.Form.Get("operations")), ¶ms); err != nil {
|
||||
if err = jsonDecode(part, ¶ms); err != nil {
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
writeJsonError(w, "operations form field could not be decoded")
|
||||
return
|
||||
}
|
||||
|
||||
part, err = mr.NextPart()
|
||||
if err != nil || part.FormName() != "map" {
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
writeJsonError(w, "second part must be map")
|
||||
return
|
||||
}
|
||||
|
||||
uploadsMap := map[string][]string{}
|
||||
if err = json.Unmarshal([]byte(r.Form.Get("map")), &uploadsMap); err != nil {
|
||||
if err = json.NewDecoder(part).Decode(&uploadsMap); err != nil {
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
writeJsonError(w, "map form field could not be decoded")
|
||||
return
|
||||
}
|
||||
|
||||
var upload graphql.Upload
|
||||
for key, paths := range uploadsMap {
|
||||
for {
|
||||
part, err = mr.NextPart()
|
||||
if err == io.EOF {
|
||||
break
|
||||
} else if err != nil {
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
writeJsonErrorf(w, "failed to parse part")
|
||||
return
|
||||
}
|
||||
|
||||
key := part.FormName()
|
||||
filename := part.FileName()
|
||||
contentType := part.Header.Get("Content-Type")
|
||||
|
||||
paths := uploadsMap[key]
|
||||
if len(paths) == 0 {
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
writeJsonErrorf(w, "invalid empty operations paths list for key %s", key)
|
||||
return
|
||||
}
|
||||
file, header, err := r.FormFile(key)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
writeJsonErrorf(w, "failed to get key %s from form", key)
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
delete(uploadsMap, key)
|
||||
|
||||
if len(paths) == 1 {
|
||||
upload = graphql.Upload{
|
||||
File: file,
|
||||
Size: header.Size,
|
||||
Filename: header.Filename,
|
||||
ContentType: header.Header.Get("Content-Type"),
|
||||
}
|
||||
|
||||
if err := params.AddUpload(upload, key, paths[0]); err != nil {
|
||||
var upload graphql.Upload
|
||||
if r.ContentLength < f.maxMemory() {
|
||||
fileBytes, err := io.ReadAll(part)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
writeJsonGraphqlError(w, err)
|
||||
writeJsonErrorf(w, "failed to read file for key %s", key)
|
||||
return
|
||||
}
|
||||
for _, path := range paths {
|
||||
upload = graphql.Upload{
|
||||
File: &bytesReader{s: &fileBytes, i: 0},
|
||||
Size: int64(len(fileBytes)),
|
||||
Filename: filename,
|
||||
ContentType: contentType,
|
||||
}
|
||||
|
||||
if err := params.AddUpload(upload, key, path); err != nil {
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
writeJsonGraphqlError(w, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if r.ContentLength < f.maxMemory() {
|
||||
fileBytes, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
writeJsonErrorf(w, "failed to read file for key %s", key)
|
||||
return
|
||||
}
|
||||
for _, path := range paths {
|
||||
upload = graphql.Upload{
|
||||
File: &bytesReader{s: &fileBytes, i: 0, prevRune: -1},
|
||||
Size: header.Size,
|
||||
Filename: header.Filename,
|
||||
ContentType: header.Header.Get("Content-Type"),
|
||||
}
|
||||
|
||||
if err := params.AddUpload(upload, key, path); err != nil {
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
writeJsonGraphqlError(w, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tmpFile, err := ioutil.TempFile(os.TempDir(), "gqlgen-")
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
writeJsonErrorf(w, "failed to create temp file for key %s", key)
|
||||
return
|
||||
}
|
||||
tmpName := tmpFile.Name()
|
||||
defer func() {
|
||||
_ = os.Remove(tmpName)
|
||||
}()
|
||||
_, err = io.Copy(tmpFile, file)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
if err := tmpFile.Close(); err != nil {
|
||||
writeJsonErrorf(w, "failed to copy to temp file and close temp file for key %s", key)
|
||||
return
|
||||
}
|
||||
writeJsonErrorf(w, "failed to copy to temp file for key %s", key)
|
||||
return
|
||||
}
|
||||
tmpFile, err := os.CreateTemp(os.TempDir(), "gqlgen-")
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
writeJsonErrorf(w, "failed to create temp file for key %s", key)
|
||||
return
|
||||
}
|
||||
tmpName := tmpFile.Name()
|
||||
defer func() {
|
||||
_ = os.Remove(tmpName)
|
||||
}()
|
||||
fileSize, err := io.Copy(tmpFile, part)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
if err := tmpFile.Close(); err != nil {
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
writeJsonErrorf(w, "failed to close temp file for key %s", key)
|
||||
writeJsonErrorf(w, "failed to copy to temp file and close temp file for key %s", key)
|
||||
return
|
||||
}
|
||||
for _, path := range paths {
|
||||
pathTmpFile, err := os.Open(tmpName)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
writeJsonErrorf(w, "failed to open temp file for key %s", key)
|
||||
return
|
||||
}
|
||||
defer pathTmpFile.Close()
|
||||
upload = graphql.Upload{
|
||||
File: pathTmpFile,
|
||||
Size: header.Size,
|
||||
Filename: header.Filename,
|
||||
ContentType: header.Header.Get("Content-Type"),
|
||||
}
|
||||
writeJsonErrorf(w, "failed to copy to temp file for key %s", key)
|
||||
return
|
||||
}
|
||||
if err := tmpFile.Close(); err != nil {
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
writeJsonErrorf(w, "failed to close temp file for key %s", key)
|
||||
return
|
||||
}
|
||||
for _, path := range paths {
|
||||
pathTmpFile, err := os.Open(tmpName)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
writeJsonErrorf(w, "failed to open temp file for key %s", key)
|
||||
return
|
||||
}
|
||||
defer pathTmpFile.Close()
|
||||
upload = graphql.Upload{
|
||||
File: pathTmpFile,
|
||||
Size: fileSize,
|
||||
Filename: filename,
|
||||
ContentType: contentType,
|
||||
}
|
||||
|
||||
if err := params.AddUpload(upload, key, path); err != nil {
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
writeJsonGraphqlError(w, err)
|
||||
return
|
||||
}
|
||||
if err := params.AddUpload(upload, key, path); err != nil {
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
writeJsonGraphqlError(w, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for key := range uploadsMap {
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
writeJsonErrorf(w, "failed to get key %s from form", key)
|
||||
return
|
||||
}
|
||||
|
||||
params.Headers = r.Header
|
||||
|
||||
params.ReadTime = graphql.TraceTiming{
|
||||
Start: start,
|
||||
End: graphql.Now(),
|
||||
|
|
|
|||
24
vendor/github.com/99designs/gqlgen/graphql/handler/transport/http_get.go
generated
vendored
24
vendor/github.com/99designs/gqlgen/graphql/handler/transport/http_get.go
generated
vendored
|
|
@ -4,6 +4,7 @@ import (
|
|||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/99designs/gqlgen/graphql"
|
||||
|
|
@ -27,15 +28,22 @@ func (h GET) Supports(r *http.Request) bool {
|
|||
}
|
||||
|
||||
func (h GET) Do(w http.ResponseWriter, r *http.Request, exec graphql.GraphExecutor) {
|
||||
query, err := url.ParseQuery(r.URL.RawQuery)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
writeJsonError(w, err.Error())
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
raw := &graphql.RawParams{
|
||||
Query: r.URL.Query().Get("query"),
|
||||
OperationName: r.URL.Query().Get("operationName"),
|
||||
Query: query.Get("query"),
|
||||
OperationName: query.Get("operationName"),
|
||||
Headers: r.Header,
|
||||
}
|
||||
raw.ReadTime.Start = graphql.Now()
|
||||
|
||||
if variables := r.URL.Query().Get("variables"); variables != "" {
|
||||
if variables := query.Get("variables"); variables != "" {
|
||||
if err := jsonDecode(strings.NewReader(variables), &raw.Variables); err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
writeJsonError(w, "variables could not be decoded")
|
||||
|
|
@ -43,7 +51,7 @@ func (h GET) Do(w http.ResponseWriter, r *http.Request, exec graphql.GraphExecut
|
|||
}
|
||||
}
|
||||
|
||||
if extensions := r.URL.Query().Get("extensions"); extensions != "" {
|
||||
if extensions := query.Get("extensions"); extensions != "" {
|
||||
if err := jsonDecode(strings.NewReader(extensions), &raw.Extensions); err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
writeJsonError(w, "extensions could not be decoded")
|
||||
|
|
@ -53,10 +61,10 @@ func (h GET) Do(w http.ResponseWriter, r *http.Request, exec graphql.GraphExecut
|
|||
|
||||
raw.ReadTime.End = graphql.Now()
|
||||
|
||||
rc, err := exec.CreateOperationContext(r.Context(), raw)
|
||||
if err != nil {
|
||||
w.WriteHeader(statusFor(err))
|
||||
resp := exec.DispatchError(graphql.WithOperationContext(r.Context(), rc), err)
|
||||
rc, gqlError := exec.CreateOperationContext(r.Context(), raw)
|
||||
if gqlError != nil {
|
||||
w.WriteHeader(statusFor(gqlError))
|
||||
resp := exec.DispatchError(graphql.WithOperationContext(r.Context(), rc), gqlError)
|
||||
writeJson(w, resp)
|
||||
return
|
||||
}
|
||||
|
|
|
|||
3
vendor/github.com/99designs/gqlgen/graphql/handler/transport/http_post.go
generated
vendored
3
vendor/github.com/99designs/gqlgen/graphql/handler/transport/http_post.go
generated
vendored
|
|
@ -36,6 +36,9 @@ func (h POST) Do(w http.ResponseWriter, r *http.Request, exec graphql.GraphExecu
|
|||
writeJsonErrorf(w, "json body could not be decoded: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
params.Headers = r.Header
|
||||
|
||||
params.ReadTime = graphql.TraceTiming{
|
||||
Start: start,
|
||||
End: graphql.Now(),
|
||||
|
|
|
|||
15
vendor/github.com/99designs/gqlgen/graphql/handler/transport/options.go
generated
vendored
15
vendor/github.com/99designs/gqlgen/graphql/handler/transport/options.go
generated
vendored
|
|
@ -2,12 +2,16 @@ package transport
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/99designs/gqlgen/graphql"
|
||||
)
|
||||
|
||||
// Options responds to http OPTIONS and HEAD requests
|
||||
type Options struct{}
|
||||
type Options struct {
|
||||
// AllowedMethods is a list of allowed HTTP methods.
|
||||
AllowedMethods []string
|
||||
}
|
||||
|
||||
var _ graphql.Transport = Options{}
|
||||
|
||||
|
|
@ -18,9 +22,16 @@ func (o Options) Supports(r *http.Request) bool {
|
|||
func (o Options) Do(w http.ResponseWriter, r *http.Request, exec graphql.GraphExecutor) {
|
||||
switch r.Method {
|
||||
case http.MethodOptions:
|
||||
w.Header().Set("Allow", "OPTIONS, GET, POST")
|
||||
w.Header().Set("Allow", o.allowedMethods())
|
||||
w.WriteHeader(http.StatusOK)
|
||||
case http.MethodHead:
|
||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||
}
|
||||
}
|
||||
|
||||
func (o Options) allowedMethods() string {
|
||||
if len(o.AllowedMethods) == 0 {
|
||||
return "OPTIONS, GET, POST"
|
||||
}
|
||||
return strings.Join(o.AllowedMethods, ", ")
|
||||
}
|
||||
|
|
|
|||
28
vendor/github.com/99designs/gqlgen/graphql/handler/transport/reader.go
generated
vendored
28
vendor/github.com/99designs/gqlgen/graphql/handler/transport/reader.go
generated
vendored
|
|
@ -6,9 +6,8 @@ import (
|
|||
)
|
||||
|
||||
type bytesReader struct {
|
||||
s *[]byte
|
||||
i int64 // current reading index
|
||||
prevRune int // index of previous rune; or < 0
|
||||
s *[]byte
|
||||
i int64 // current reading index
|
||||
}
|
||||
|
||||
func (r *bytesReader) Read(b []byte) (n int, err error) {
|
||||
|
|
@ -18,8 +17,29 @@ func (r *bytesReader) Read(b []byte) (n int, err error) {
|
|||
if r.i >= int64(len(*r.s)) {
|
||||
return 0, io.EOF
|
||||
}
|
||||
r.prevRune = -1
|
||||
n = copy(b, (*r.s)[r.i:])
|
||||
r.i += int64(n)
|
||||
return
|
||||
}
|
||||
|
||||
func (r *bytesReader) Seek(offset int64, whence int) (int64, error) {
|
||||
if r.s == nil {
|
||||
return 0, errors.New("byte slice pointer is nil")
|
||||
}
|
||||
var abs int64
|
||||
switch whence {
|
||||
case io.SeekStart:
|
||||
abs = offset
|
||||
case io.SeekCurrent:
|
||||
abs = r.i + offset
|
||||
case io.SeekEnd:
|
||||
abs = int64(len(*r.s)) + offset
|
||||
default:
|
||||
return 0, errors.New("invalid whence")
|
||||
}
|
||||
if abs < 0 {
|
||||
return 0, errors.New("negative position")
|
||||
}
|
||||
r.i = abs
|
||||
return abs, nil
|
||||
}
|
||||
|
|
|
|||
36
vendor/github.com/99designs/gqlgen/graphql/handler/transport/websocket.go
generated
vendored
36
vendor/github.com/99designs/gqlgen/graphql/handler/transport/websocket.go
generated
vendored
|
|
@ -49,7 +49,24 @@ type (
|
|||
|
||||
var errReadTimeout = errors.New("read timeout")
|
||||
|
||||
var _ graphql.Transport = Websocket{}
|
||||
type WebsocketError struct {
|
||||
Err error
|
||||
|
||||
// IsReadError flags whether the error occurred on read or write to the websocket
|
||||
IsReadError bool
|
||||
}
|
||||
|
||||
func (e WebsocketError) Error() string {
|
||||
if e.IsReadError {
|
||||
return fmt.Sprintf("websocket read: %v", e.Err)
|
||||
}
|
||||
return fmt.Sprintf("websocket write: %v", e.Err)
|
||||
}
|
||||
|
||||
var (
|
||||
_ graphql.Transport = Websocket{}
|
||||
_ error = WebsocketError{}
|
||||
)
|
||||
|
||||
func (t Websocket) Supports(r *http.Request) bool {
|
||||
return r.Header.Get("Upgrade") != ""
|
||||
|
|
@ -94,9 +111,12 @@ func (t Websocket) Do(w http.ResponseWriter, r *http.Request, exec graphql.Graph
|
|||
conn.run()
|
||||
}
|
||||
|
||||
func (c *wsConnection) handlePossibleError(err error) {
|
||||
func (c *wsConnection) handlePossibleError(err error, isReadError bool) {
|
||||
if c.ErrorFunc != nil && err != nil {
|
||||
c.ErrorFunc(c.ctx, err)
|
||||
c.ErrorFunc(c.ctx, WebsocketError{
|
||||
Err: err,
|
||||
IsReadError: isReadError,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -181,7 +201,7 @@ func (c *wsConnection) init() bool {
|
|||
|
||||
func (c *wsConnection) write(msg *message) {
|
||||
c.mu.Lock()
|
||||
c.handlePossibleError(c.me.Send(msg))
|
||||
c.handlePossibleError(c.me.Send(msg), false)
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
|
|
@ -227,7 +247,7 @@ func (c *wsConnection) run() {
|
|||
if err != nil {
|
||||
// If the connection got closed by us, don't report the error
|
||||
if !errors.Is(err, net.ErrClosed) {
|
||||
c.handlePossibleError(err)
|
||||
c.handlePossibleError(err, true)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
@ -358,12 +378,8 @@ func (c *wsConnection) subscribe(start time.Time, msg *message) {
|
|||
|
||||
c.sendResponse(msg.id, response)
|
||||
}
|
||||
c.complete(msg.id)
|
||||
|
||||
c.mu.Lock()
|
||||
delete(c.active, msg.id)
|
||||
c.mu.Unlock()
|
||||
cancel()
|
||||
// complete and context cancel comes from the defer
|
||||
}()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import (
|
|||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
// https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md
|
||||
// https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md
|
||||
const (
|
||||
graphqltransportwsSubprotocol = "graphql-transport-ws"
|
||||
|
||||
|
|
|
|||
2
vendor/github.com/99designs/gqlgen/graphql/handler/transport/websocket_graphqlws.go
generated
vendored
2
vendor/github.com/99designs/gqlgen/graphql/handler/transport/websocket_graphqlws.go
generated
vendored
|
|
@ -7,7 +7,7 @@ import (
|
|||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
// https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md
|
||||
// https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md
|
||||
const (
|
||||
graphqlwsSubprotocol = "graphql-ws"
|
||||
|
||||
|
|
|
|||
55
vendor/github.com/99designs/gqlgen/graphql/input.go
generated
vendored
Normal file
55
vendor/github.com/99designs/gqlgen/graphql/input.go
generated
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
package graphql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
const unmarshalInputCtx key = "unmarshal_input_context"
|
||||
|
||||
// BuildUnmarshalerMap returns a map of unmarshal functions of the ExecutableContext
|
||||
// to use with the WithUnmarshalerMap function.
|
||||
func BuildUnmarshalerMap(unmarshaler ...interface{}) map[reflect.Type]reflect.Value {
|
||||
maps := make(map[reflect.Type]reflect.Value)
|
||||
for _, v := range unmarshaler {
|
||||
ft := reflect.TypeOf(v)
|
||||
if ft.Kind() == reflect.Func {
|
||||
maps[ft.Out(0)] = reflect.ValueOf(v)
|
||||
}
|
||||
}
|
||||
|
||||
return maps
|
||||
}
|
||||
|
||||
// WithUnmarshalerMap returns a new context with a map from input types to their unmarshaler functions.
|
||||
func WithUnmarshalerMap(ctx context.Context, maps map[reflect.Type]reflect.Value) context.Context {
|
||||
return context.WithValue(ctx, unmarshalInputCtx, maps)
|
||||
}
|
||||
|
||||
// UnmarshalInputFromContext allows unmarshaling input object from a context.
|
||||
func UnmarshalInputFromContext(ctx context.Context, raw, v interface{}) error {
|
||||
m, ok := ctx.Value(unmarshalInputCtx).(map[reflect.Type]reflect.Value)
|
||||
if m == nil || !ok {
|
||||
return errors.New("graphql: the input context is empty")
|
||||
}
|
||||
|
||||
rv := reflect.ValueOf(v)
|
||||
if rv.Kind() != reflect.Ptr || rv.IsNil() {
|
||||
return errors.New("graphql: input must be a non-nil pointer")
|
||||
}
|
||||
if fn, ok := m[rv.Elem().Type()]; ok {
|
||||
res := fn.Call([]reflect.Value{
|
||||
reflect.ValueOf(ctx),
|
||||
reflect.ValueOf(raw),
|
||||
})
|
||||
if err := res[1].Interface(); err != nil {
|
||||
return err.(error)
|
||||
}
|
||||
|
||||
rv.Elem().Set(res[0])
|
||||
return nil
|
||||
}
|
||||
|
||||
return errors.New("graphql: no unmarshal function found")
|
||||
}
|
||||
90
vendor/github.com/99designs/gqlgen/graphql/playground/playground.go
generated
vendored
90
vendor/github.com/99designs/gqlgen/graphql/playground/playground.go
generated
vendored
|
|
@ -3,22 +3,26 @@ package playground
|
|||
import (
|
||||
"html/template"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
var page = template.Must(template.New("graphiql").Parse(`<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{{.title}}</title>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/graphiql@{{.version}}/graphiql.min.css"
|
||||
integrity="{{.cssSRI}}"
|
||||
crossorigin="anonymous"
|
||||
/>
|
||||
</head>
|
||||
<body style="margin: 0;">
|
||||
<div id="graphiql" style="height: 100vh;"></div>
|
||||
<meta charset="utf-8">
|
||||
<title>{{.title}}</title>
|
||||
<style>
|
||||
body {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#graphiql {
|
||||
height: 100vh;
|
||||
}
|
||||
</style>
|
||||
<script
|
||||
src="https://cdn.jsdelivr.net/npm/react@17.0.2/umd/react.production.min.js"
|
||||
integrity="{{.reactSRI}}"
|
||||
|
|
@ -29,6 +33,16 @@ var page = template.Must(template.New("graphiql").Parse(`<!DOCTYPE html>
|
|||
integrity="{{.reactDOMSRI}}"
|
||||
crossorigin="anonymous"
|
||||
></script>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/graphiql@{{.version}}/graphiql.min.css"
|
||||
integrity="{{.cssSRI}}"
|
||||
crossorigin="anonymous"
|
||||
/>
|
||||
</head>
|
||||
<body>
|
||||
<div id="graphiql">Loading...</div>
|
||||
|
||||
<script
|
||||
src="https://cdn.jsdelivr.net/npm/graphiql@{{.version}}/graphiql.min.js"
|
||||
integrity="{{.jsSRI}}"
|
||||
|
|
@ -36,15 +50,20 @@ var page = template.Must(template.New("graphiql").Parse(`<!DOCTYPE html>
|
|||
></script>
|
||||
|
||||
<script>
|
||||
const url = location.protocol + '//' + location.host + '{{.endpoint}}';
|
||||
{{- if .endpointIsAbsolute}}
|
||||
const url = {{.endpoint}};
|
||||
const subscriptionUrl = {{.subscriptionEndpoint}};
|
||||
{{- else}}
|
||||
const url = location.protocol + '//' + location.host + {{.endpoint}};
|
||||
const wsProto = location.protocol == 'https:' ? 'wss:' : 'ws:';
|
||||
const subscriptionUrl = wsProto + '//' + location.host + '{{.endpoint}}';
|
||||
const subscriptionUrl = wsProto + '//' + location.host + {{.endpoint}};
|
||||
{{- end}}
|
||||
|
||||
const fetcher = GraphiQL.createFetcher({ url, subscriptionUrl });
|
||||
ReactDOM.render(
|
||||
React.createElement(GraphiQL, {
|
||||
fetcher: fetcher,
|
||||
headerEditorEnabled: true,
|
||||
isHeadersEditorEnabled: true,
|
||||
shouldPersistHeaders: true
|
||||
}),
|
||||
document.getElementById('graphiql'),
|
||||
|
|
@ -54,20 +73,47 @@ var page = template.Must(template.New("graphiql").Parse(`<!DOCTYPE html>
|
|||
</html>
|
||||
`))
|
||||
|
||||
// Handler responsible for setting up the playground
|
||||
func Handler(title string, endpoint string) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Add("Content-Type", "text/html")
|
||||
err := page.Execute(w, map[string]string{
|
||||
"title": title,
|
||||
"endpoint": endpoint,
|
||||
"version": "1.5.16",
|
||||
"cssSRI": "sha256-HADQowUuFum02+Ckkv5Yu5ygRoLllHZqg0TFZXY7NHI=",
|
||||
"jsSRI": "sha256-uHp12yvpXC4PC9+6JmITxKuLYwjlW9crq9ywPE5Rxco=",
|
||||
"reactSRI": "sha256-Ipu/TQ50iCCVZBUsZyNJfxrDk0E2yhaEIz0vqI+kFG8=",
|
||||
"reactDOMSRI": "sha256-nbMykgB6tsOFJ7OdVmPpdqMFVk4ZsqWocT6issAPUF0=",
|
||||
w.Header().Add("Content-Type", "text/html; charset=UTF-8")
|
||||
err := page.Execute(w, map[string]interface{}{
|
||||
"title": title,
|
||||
"endpoint": endpoint,
|
||||
"endpointIsAbsolute": endpointHasScheme(endpoint),
|
||||
"subscriptionEndpoint": getSubscriptionEndpoint(endpoint),
|
||||
"version": "2.0.7",
|
||||
"cssSRI": "sha256-gQryfbGYeYFxnJYnfPStPYFt0+uv8RP8Dm++eh00G9c=",
|
||||
"jsSRI": "sha256-qQ6pw7LwTLC+GfzN+cJsYXfVWRKH9O5o7+5H96gTJhQ=",
|
||||
"reactSRI": "sha256-Ipu/TQ50iCCVZBUsZyNJfxrDk0E2yhaEIz0vqI+kFG8=",
|
||||
"reactDOMSRI": "sha256-nbMykgB6tsOFJ7OdVmPpdqMFVk4ZsqWocT6issAPUF0=",
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// endpointHasScheme checks if the endpoint has a scheme.
|
||||
func endpointHasScheme(endpoint string) bool {
|
||||
u, err := url.Parse(endpoint)
|
||||
return err == nil && u.Scheme != ""
|
||||
}
|
||||
|
||||
// getSubscriptionEndpoint returns the subscription endpoint for the given
|
||||
// endpoint if it is parsable as a URL, or an empty string.
|
||||
func getSubscriptionEndpoint(endpoint string) string {
|
||||
u, err := url.Parse(endpoint)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
switch u.Scheme {
|
||||
case "https":
|
||||
u.Scheme = "wss"
|
||||
default:
|
||||
u.Scheme = "ws"
|
||||
}
|
||||
|
||||
return u.String()
|
||||
}
|
||||
|
|
|
|||
2
vendor/github.com/99designs/gqlgen/graphql/upload.go
generated
vendored
2
vendor/github.com/99designs/gqlgen/graphql/upload.go
generated
vendored
|
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
type Upload struct {
|
||||
File io.Reader
|
||||
File io.ReadSeeker
|
||||
Filename string
|
||||
Size int64
|
||||
ContentType string
|
||||
|
|
|
|||
2
vendor/github.com/99designs/gqlgen/graphql/version.go
generated
vendored
2
vendor/github.com/99designs/gqlgen/graphql/version.go
generated
vendored
|
|
@ -1,3 +1,3 @@
|
|||
package graphql
|
||||
|
||||
const Version = "v0.17.2"
|
||||
const Version = "v0.17.20"
|
||||
|
|
|
|||
7
vendor/github.com/99designs/gqlgen/init-templates/gqlgen.yml.gotmpl
generated
vendored
7
vendor/github.com/99designs/gqlgen/init-templates/gqlgen.yml.gotmpl
generated
vendored
|
|
@ -29,6 +29,13 @@ resolver:
|
|||
# Optional: turn on to use []Thing instead of []*Thing
|
||||
# omit_slice_element_pointers: false
|
||||
|
||||
# Optional: turn off to make struct-type struct fields not use pointers
|
||||
# e.g. type Thing struct { FieldA OtherThing } instead of { FieldA *OtherThing }
|
||||
# struct_fields_always_pointers: true
|
||||
|
||||
# Optional: turn off to make resolvers return values instead of pointers for structs
|
||||
# resolvers_always_return_pointers: true
|
||||
|
||||
# Optional: set to speed up generation time by not performing a final validation pass.
|
||||
# skip_validation: true
|
||||
|
||||
|
|
|
|||
31
vendor/github.com/99designs/gqlgen/internal/code/imports.go
generated
vendored
31
vendor/github.com/99designs/gqlgen/internal/code/imports.go
generated
vendored
|
|
@ -1,10 +1,12 @@
|
|||
package code
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
|
@ -26,7 +28,7 @@ func NameForDir(dir string) string {
|
|||
if err != nil {
|
||||
return SanitizePackageName(filepath.Base(dir))
|
||||
}
|
||||
files, err := ioutil.ReadDir(dir)
|
||||
files, err := os.ReadDir(dir)
|
||||
if err != nil {
|
||||
return SanitizePackageName(filepath.Base(dir))
|
||||
}
|
||||
|
|
@ -73,8 +75,8 @@ func goModuleRoot(dir string) (string, bool) {
|
|||
break
|
||||
}
|
||||
|
||||
if content, err := ioutil.ReadFile(filepath.Join(modDir, "go.mod")); err == nil {
|
||||
moduleName := string(modregex.FindSubmatch(content)[1])
|
||||
if content, err := os.ReadFile(filepath.Join(modDir, "go.mod")); err == nil {
|
||||
moduleName := extractModuleName(content)
|
||||
result = goModuleSearchResult{
|
||||
path: moduleName,
|
||||
goModPath: modDir,
|
||||
|
|
@ -126,6 +128,27 @@ func goModuleRoot(dir string) (string, bool) {
|
|||
return res.path, true
|
||||
}
|
||||
|
||||
func extractModuleName(content []byte) string {
|
||||
for {
|
||||
advance, tkn, err := bufio.ScanLines(content, false)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("error parsing mod file: %w", err))
|
||||
}
|
||||
if advance == 0 {
|
||||
break
|
||||
}
|
||||
s := strings.Trim(string(tkn), " \t")
|
||||
if len(s) != 0 && !strings.HasPrefix(s, "//") {
|
||||
break
|
||||
}
|
||||
if advance <= len(content) {
|
||||
content = content[advance:]
|
||||
}
|
||||
}
|
||||
moduleName := string(modregex.FindSubmatch(content)[1])
|
||||
return moduleName
|
||||
}
|
||||
|
||||
// ImportPathForDir takes a path and returns a golang import path for the package
|
||||
func ImportPathForDir(dir string) (res string) {
|
||||
dir, err := filepath.Abs(dir)
|
||||
|
|
|
|||
35
vendor/github.com/99designs/gqlgen/internal/rewrite/rewriter.go
generated
vendored
35
vendor/github.com/99designs/gqlgen/internal/rewrite/rewriter.go
generated
vendored
|
|
@ -5,7 +5,7 @@ import (
|
|||
"fmt"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
|
@ -56,7 +56,7 @@ func (r *Rewriter) getSource(start, end token.Pos) string {
|
|||
|
||||
func (r *Rewriter) getFile(filename string) string {
|
||||
if _, ok := r.files[filename]; !ok {
|
||||
b, err := ioutil.ReadFile(filename)
|
||||
b, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("unable to load file, already exists: %w", err))
|
||||
}
|
||||
|
|
@ -68,6 +68,37 @@ func (r *Rewriter) getFile(filename string) string {
|
|||
return r.files[filename]
|
||||
}
|
||||
|
||||
func (r *Rewriter) GetMethodComment(structname string, methodname string) string {
|
||||
for _, f := range r.pkg.Syntax {
|
||||
for _, d := range f.Decls {
|
||||
d, isFunc := d.(*ast.FuncDecl)
|
||||
if !isFunc {
|
||||
continue
|
||||
}
|
||||
if d.Name.Name != methodname {
|
||||
continue
|
||||
}
|
||||
if d.Recv == nil || len(d.Recv.List) == 0 {
|
||||
continue
|
||||
}
|
||||
recv := d.Recv.List[0].Type
|
||||
if star, isStar := recv.(*ast.StarExpr); isStar {
|
||||
recv = star.X
|
||||
}
|
||||
ident, ok := recv.(*ast.Ident)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if ident.Name != structname {
|
||||
continue
|
||||
}
|
||||
return d.Doc.Text()
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
func (r *Rewriter) GetMethodBody(structname string, methodname string) string {
|
||||
for _, f := range r.pkg.Syntax {
|
||||
for _, d := range f.Decls {
|
||||
|
|
|
|||
6
vendor/github.com/99designs/gqlgen/main.go
generated
vendored
6
vendor/github.com/99designs/gqlgen/main.go
generated
vendored
|
|
@ -6,8 +6,8 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
|
@ -43,7 +43,7 @@ func initFile(filename, contents string) error {
|
|||
if err := os.MkdirAll(filepath.Dir(filename), 0o755); err != nil {
|
||||
return fmt.Errorf("unable to create directory for file '%s': %w\n", filename, err)
|
||||
}
|
||||
if err := ioutil.WriteFile(filename, []byte(contents), 0o644); err != nil {
|
||||
if err := os.WriteFile(filename, []byte(contents), 0o644); err != nil {
|
||||
return fmt.Errorf("unable to write file '%s': %w\n", filename, err)
|
||||
}
|
||||
|
||||
|
|
@ -171,7 +171,7 @@ func main() {
|
|||
if context.Bool("verbose") {
|
||||
log.SetFlags(0)
|
||||
} else {
|
||||
log.SetOutput(ioutil.Discard)
|
||||
log.SetOutput(io.Discard)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
78
vendor/github.com/99designs/gqlgen/plugin/federation/federation.go
generated
vendored
78
vendor/github.com/99designs/gqlgen/plugin/federation/federation.go
generated
vendored
|
|
@ -1,6 +1,7 @@
|
|||
package federation
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
|
@ -14,14 +15,22 @@ import (
|
|||
"github.com/99designs/gqlgen/plugin/federation/fieldset"
|
||||
)
|
||||
|
||||
//go:embed federation.gotpl
|
||||
var federationTemplate string
|
||||
|
||||
type federation struct {
|
||||
Entities []*Entity
|
||||
Version int
|
||||
}
|
||||
|
||||
// New returns a federation plugin that injects
|
||||
// federated directives and types into the schema
|
||||
func New() plugin.Plugin {
|
||||
return &federation{}
|
||||
func New(version int) plugin.Plugin {
|
||||
if version == 0 {
|
||||
version = 1
|
||||
}
|
||||
|
||||
return &federation{Version: version}
|
||||
}
|
||||
|
||||
// Name returns the plugin name
|
||||
|
|
@ -51,6 +60,7 @@ func (f *federation) MutateConfig(cfg *config.Config) error {
|
|||
Model: config.StringList{"github.com/99designs/gqlgen/graphql.Map"},
|
||||
},
|
||||
}
|
||||
|
||||
for typeName, entry := range builtins {
|
||||
if cfg.Models.Exists(typeName) {
|
||||
return fmt.Errorf("%v already exists which must be reserved when Federation is enabled", typeName)
|
||||
|
|
@ -63,22 +73,46 @@ func (f *federation) MutateConfig(cfg *config.Config) error {
|
|||
cfg.Directives["key"] = config.DirectiveConfig{SkipRuntime: true}
|
||||
cfg.Directives["extends"] = config.DirectiveConfig{SkipRuntime: true}
|
||||
|
||||
// Federation 2 specific directives
|
||||
if f.Version == 2 {
|
||||
cfg.Directives["shareable"] = config.DirectiveConfig{SkipRuntime: true}
|
||||
cfg.Directives["link"] = config.DirectiveConfig{SkipRuntime: true}
|
||||
cfg.Directives["tag"] = config.DirectiveConfig{SkipRuntime: true}
|
||||
cfg.Directives["override"] = config.DirectiveConfig{SkipRuntime: true}
|
||||
cfg.Directives["inaccessible"] = config.DirectiveConfig{SkipRuntime: true}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *federation) InjectSourceEarly() *ast.Source {
|
||||
return &ast.Source{
|
||||
Name: "federation/directives.graphql",
|
||||
Input: `
|
||||
scalar _Any
|
||||
scalar _FieldSet
|
||||
input := `
|
||||
scalar _Any
|
||||
scalar _FieldSet
|
||||
|
||||
directive @external on FIELD_DEFINITION
|
||||
directive @requires(fields: _FieldSet!) on FIELD_DEFINITION
|
||||
directive @provides(fields: _FieldSet!) on FIELD_DEFINITION
|
||||
directive @key(fields: _FieldSet!) repeatable on OBJECT | INTERFACE
|
||||
directive @extends on OBJECT | INTERFACE
|
||||
`,
|
||||
directive @external on FIELD_DEFINITION
|
||||
directive @requires(fields: _FieldSet!) on FIELD_DEFINITION
|
||||
directive @provides(fields: _FieldSet!) on FIELD_DEFINITION
|
||||
directive @extends on OBJECT | INTERFACE
|
||||
`
|
||||
// add version-specific changes on key directive, as well as adding the new directives for federation 2
|
||||
if f.Version == 1 {
|
||||
input += `
|
||||
directive @key(fields: _FieldSet!) repeatable on OBJECT | INTERFACE
|
||||
`
|
||||
} else if f.Version == 2 {
|
||||
input += `
|
||||
directive @key(fields: _FieldSet!, resolvable: Boolean = true) repeatable on OBJECT | INTERFACE
|
||||
directive @link(import: [String!], url: String!) repeatable on SCHEMA
|
||||
directive @shareable on OBJECT | FIELD_DEFINITION
|
||||
directive @tag(name: String!) repeatable on FIELD_DEFINITION | INTERFACE | OBJECT | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION
|
||||
directive @override(from: String!) on FIELD_DEFINITION
|
||||
directive @inaccessible on SCALAR | OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION | INTERFACE | UNION | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION
|
||||
`
|
||||
}
|
||||
return &ast.Source{
|
||||
Name: "federation/directives.graphql",
|
||||
Input: input,
|
||||
BuiltIn: true,
|
||||
}
|
||||
}
|
||||
|
|
@ -244,6 +278,7 @@ func (f *federation) GenerateCode(data *codegen.Data) error {
|
|||
Data: f,
|
||||
GeneratedHeader: true,
|
||||
Packages: data.Config.Packages,
|
||||
Template: federationTemplate,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -290,10 +325,21 @@ func (f *federation) setEntities(schema *ast.Schema) {
|
|||
// }
|
||||
if !e.allFieldsAreExternal() {
|
||||
for _, dir := range keys {
|
||||
if len(dir.Arguments) != 1 || dir.Arguments[0].Name != "fields" {
|
||||
panic("Exactly one `fields` argument needed for @key declaration.")
|
||||
if len(dir.Arguments) > 2 {
|
||||
panic("More than two arguments provided for @key declaration.")
|
||||
}
|
||||
arg := dir.Arguments[0]
|
||||
var arg *ast.Argument
|
||||
|
||||
// since keys are able to now have multiple arguments, we need to check both possible for a possible @key(fields="" fields="")
|
||||
for _, a := range dir.Arguments {
|
||||
if a.Name == "fields" {
|
||||
if arg != nil {
|
||||
panic("More than one `fields` provided for @key declaration.")
|
||||
}
|
||||
arg = a
|
||||
}
|
||||
}
|
||||
|
||||
keyFieldSet := fieldset.New(arg.Value.Raw, nil)
|
||||
|
||||
keyFields := make([]*KeyField, len(keyFieldSet))
|
||||
|
|
|
|||
12
vendor/github.com/99designs/gqlgen/plugin/federation/fieldset/fieldset.go
generated
vendored
12
vendor/github.com/99designs/gqlgen/plugin/federation/fieldset/fieldset.go
generated
vendored
|
|
@ -11,15 +11,12 @@ import (
|
|||
|
||||
// Set represents a FieldSet that is used in federation directives @key and @requires.
|
||||
// Would be happier to reuse FieldSet parsing from gqlparser, but this suits for now.
|
||||
//
|
||||
type Set []Field
|
||||
|
||||
// Field represents a single field in a FieldSet
|
||||
//
|
||||
type Field []string
|
||||
|
||||
// New parses a FieldSet string into a TinyFieldSet.
|
||||
//
|
||||
func New(raw string, prefix []string) Set {
|
||||
if !strings.Contains(raw, "{") {
|
||||
return parseUnnestedKeyFieldSet(raw, prefix)
|
||||
|
|
@ -48,7 +45,6 @@ func New(raw string, prefix []string) Set {
|
|||
}
|
||||
|
||||
// FieldDefinition looks up a field in the type.
|
||||
//
|
||||
func (f Field) FieldDefinition(schemaType *ast.Definition, schema *ast.Schema) *ast.FieldDefinition {
|
||||
objType := schemaType
|
||||
def := objType.Fields.ForName(f[0])
|
||||
|
|
@ -74,7 +70,6 @@ func (f Field) FieldDefinition(schemaType *ast.Definition, schema *ast.Schema) *
|
|||
}
|
||||
|
||||
// TypeReference looks up the type of a field.
|
||||
//
|
||||
func (f Field) TypeReference(obj *codegen.Object, objects codegen.Objects) *codegen.Field {
|
||||
var def *codegen.Field
|
||||
|
||||
|
|
@ -89,7 +84,6 @@ func (f Field) TypeReference(obj *codegen.Object, objects codegen.Objects) *code
|
|||
}
|
||||
|
||||
// ToGo converts a (possibly nested) field into a proper public Go name.
|
||||
//
|
||||
func (f Field) ToGo() string {
|
||||
var ret string
|
||||
|
||||
|
|
@ -100,7 +94,6 @@ func (f Field) ToGo() string {
|
|||
}
|
||||
|
||||
// ToGoPrivate converts a (possibly nested) field into a proper private Go name.
|
||||
//
|
||||
func (f Field) ToGoPrivate() string {
|
||||
var ret string
|
||||
|
||||
|
|
@ -115,13 +108,11 @@ func (f Field) ToGoPrivate() string {
|
|||
}
|
||||
|
||||
// Join concatenates the field parts with a string separator between. Useful in templates.
|
||||
//
|
||||
func (f Field) Join(str string) string {
|
||||
return strings.Join(f, str)
|
||||
}
|
||||
|
||||
// JoinGo concatenates the Go name of field parts with a string separator between. Useful in templates.
|
||||
//
|
||||
func (f Field) JoinGo(str string) string {
|
||||
strs := []string{}
|
||||
|
||||
|
|
@ -138,7 +129,6 @@ func (f Field) LastIndex() int {
|
|||
// local functions
|
||||
|
||||
// parseUnnestedKeyFieldSet // handles simple case where none of the fields are nested.
|
||||
//
|
||||
func parseUnnestedKeyFieldSet(raw string, prefix []string) Set {
|
||||
ret := Set{}
|
||||
|
||||
|
|
@ -150,7 +140,6 @@ func parseUnnestedKeyFieldSet(raw string, prefix []string) Set {
|
|||
}
|
||||
|
||||
// extractSubs splits out and trims sub-expressions from before, inside, and after "{}".
|
||||
//
|
||||
func extractSubs(str string) (string, string, string) {
|
||||
start := strings.Index(str, "{")
|
||||
end := matchingBracketIndex(str, start)
|
||||
|
|
@ -162,7 +151,6 @@ func extractSubs(str string) (string, string, string) {
|
|||
}
|
||||
|
||||
// matchingBracketIndex returns the index of the closing bracket, assuming an open bracket at start.
|
||||
//
|
||||
func matchingBracketIndex(str string, start int) int {
|
||||
if start < 0 || len(str) <= start+1 {
|
||||
return -1
|
||||
|
|
|
|||
329
vendor/github.com/99designs/gqlgen/plugin/modelgen/models.go
generated
vendored
329
vendor/github.com/99designs/gqlgen/plugin/modelgen/models.go
generated
vendored
|
|
@ -1,10 +1,12 @@
|
|||
package modelgen
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"go/types"
|
||||
"sort"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/99designs/gqlgen/codegen/config"
|
||||
"github.com/99designs/gqlgen/codegen/templates"
|
||||
|
|
@ -12,6 +14,9 @@ import (
|
|||
"github.com/vektah/gqlparser/v2/ast"
|
||||
)
|
||||
|
||||
//go:embed models.gotpl
|
||||
var modelTemplate string
|
||||
|
||||
type BuildMutateHook = func(b *ModelBuild) *ModelBuild
|
||||
|
||||
type FieldMutateHook = func(td *ast.Definition, fd *ast.FieldDefinition, f *Field) (*Field, error)
|
||||
|
|
@ -36,6 +41,7 @@ type ModelBuild struct {
|
|||
type Interface struct {
|
||||
Description string
|
||||
Name string
|
||||
Fields []*Field
|
||||
Implements []string
|
||||
}
|
||||
|
||||
|
|
@ -48,9 +54,12 @@ type Object struct {
|
|||
|
||||
type Field struct {
|
||||
Description string
|
||||
Name string
|
||||
Type types.Type
|
||||
Tag string
|
||||
// Name is the field's name as it appears in the schema
|
||||
Name string
|
||||
// GoName is the field's name as it appears in the generated Go code
|
||||
GoName string
|
||||
Type types.Type
|
||||
Tag string
|
||||
}
|
||||
|
||||
type Enum struct {
|
||||
|
|
@ -83,7 +92,6 @@ func (m *Plugin) Name() string {
|
|||
}
|
||||
|
||||
func (m *Plugin) MutateConfig(cfg *config.Config) error {
|
||||
binder := cfg.NewBinder()
|
||||
|
||||
b := &ModelBuild{
|
||||
PackageName: cfg.Model.Package,
|
||||
|
|
@ -95,10 +103,20 @@ func (m *Plugin) MutateConfig(cfg *config.Config) error {
|
|||
}
|
||||
switch schemaType.Kind {
|
||||
case ast.Interface, ast.Union:
|
||||
var fields []*Field
|
||||
var err error
|
||||
if !cfg.OmitGetters {
|
||||
fields, err = m.generateFields(cfg, schemaType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
it := &Interface{
|
||||
Description: schemaType.Description,
|
||||
Name: schemaType.Name,
|
||||
Implements: schemaType.Interfaces,
|
||||
Fields: fields,
|
||||
}
|
||||
|
||||
b.Interfaces = append(b.Interfaces, it)
|
||||
|
|
@ -106,9 +124,16 @@ func (m *Plugin) MutateConfig(cfg *config.Config) error {
|
|||
if schemaType == cfg.Schema.Query || schemaType == cfg.Schema.Mutation || schemaType == cfg.Schema.Subscription {
|
||||
continue
|
||||
}
|
||||
|
||||
fields, err := m.generateFields(cfg, schemaType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
it := &Object{
|
||||
Description: schemaType.Description,
|
||||
Name: schemaType.Name,
|
||||
Fields: fields,
|
||||
}
|
||||
|
||||
// If Interface A implements interface B, and Interface C also implements interface B
|
||||
|
|
@ -129,84 +154,6 @@ func (m *Plugin) MutateConfig(cfg *config.Config) error {
|
|||
}
|
||||
}
|
||||
|
||||
for _, field := range schemaType.Fields {
|
||||
var typ types.Type
|
||||
fieldDef := cfg.Schema.Types[field.Type.Name()]
|
||||
|
||||
if cfg.Models.UserDefined(field.Type.Name()) {
|
||||
var err error
|
||||
typ, err = binder.FindTypeFromName(cfg.Models[field.Type.Name()].Model[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
switch fieldDef.Kind {
|
||||
case ast.Scalar:
|
||||
// no user defined model, referencing a default scalar
|
||||
typ = types.NewNamed(
|
||||
types.NewTypeName(0, cfg.Model.Pkg(), "string", nil),
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
|
||||
case ast.Interface, ast.Union:
|
||||
// no user defined model, referencing a generated interface type
|
||||
typ = types.NewNamed(
|
||||
types.NewTypeName(0, cfg.Model.Pkg(), templates.ToGo(field.Type.Name()), nil),
|
||||
types.NewInterfaceType([]*types.Func{}, []types.Type{}),
|
||||
nil,
|
||||
)
|
||||
|
||||
case ast.Enum:
|
||||
// no user defined model, must reference a generated enum
|
||||
typ = types.NewNamed(
|
||||
types.NewTypeName(0, cfg.Model.Pkg(), templates.ToGo(field.Type.Name()), nil),
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
|
||||
case ast.Object, ast.InputObject:
|
||||
// no user defined model, must reference a generated struct
|
||||
typ = types.NewNamed(
|
||||
types.NewTypeName(0, cfg.Model.Pkg(), templates.ToGo(field.Type.Name()), nil),
|
||||
types.NewStruct(nil, nil),
|
||||
nil,
|
||||
)
|
||||
|
||||
default:
|
||||
panic(fmt.Errorf("unknown ast type %s", fieldDef.Kind))
|
||||
}
|
||||
}
|
||||
|
||||
name := field.Name
|
||||
if nameOveride := cfg.Models[schemaType.Name].Fields[field.Name].FieldName; nameOveride != "" {
|
||||
name = nameOveride
|
||||
}
|
||||
|
||||
typ = binder.CopyModifiersFromAst(field.Type, typ)
|
||||
|
||||
if isStruct(typ) && (fieldDef.Kind == ast.Object || fieldDef.Kind == ast.InputObject) {
|
||||
typ = types.NewPointer(typ)
|
||||
}
|
||||
|
||||
f := &Field{
|
||||
Name: name,
|
||||
Type: typ,
|
||||
Description: field.Description,
|
||||
Tag: `json:"` + field.Name + `"`,
|
||||
}
|
||||
|
||||
if m.FieldHook != nil {
|
||||
mf, err := m.FieldHook(schemaType, field, f)
|
||||
if err != nil {
|
||||
return fmt.Errorf("generror: field %v.%v: %w", it.Name, field.Name, err)
|
||||
}
|
||||
f = mf
|
||||
}
|
||||
|
||||
it.Fields = append(it.Fields, f)
|
||||
}
|
||||
|
||||
b.Models = append(b.Models, it)
|
||||
case ast.Enum:
|
||||
it := &Enum{
|
||||
|
|
@ -230,6 +177,12 @@ func (m *Plugin) MutateConfig(cfg *config.Config) error {
|
|||
sort.Slice(b.Models, func(i, j int) bool { return b.Models[i].Name < b.Models[j].Name })
|
||||
sort.Slice(b.Interfaces, func(i, j int) bool { return b.Interfaces[i].Name < b.Interfaces[j].Name })
|
||||
|
||||
// if we are not just turning all struct-type fields in generated structs into pointers, we need to at least
|
||||
// check for cyclical relationships and recursive structs
|
||||
if !cfg.StructFieldsAlwaysPointers {
|
||||
findAndHandleCyclicalRelationships(b)
|
||||
}
|
||||
|
||||
for _, it := range b.Enums {
|
||||
cfg.Models.Add(it.Name, cfg.Model.ImportPath()+"."+templates.ToGo(it.Name))
|
||||
}
|
||||
|
|
@ -251,12 +204,84 @@ func (m *Plugin) MutateConfig(cfg *config.Config) error {
|
|||
b = m.MutateHook(b)
|
||||
}
|
||||
|
||||
getInterfaceByName := func(name string) *Interface {
|
||||
// Allow looking up interfaces, so template can generate getters for each field
|
||||
for _, i := range b.Interfaces {
|
||||
if i.Name == name {
|
||||
return i
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
gettersGenerated := make(map[string]map[string]struct{})
|
||||
generateGetter := func(model *Object, field *Field) string {
|
||||
if model == nil || field == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Let templates check if a given getter has been generated already
|
||||
typeGetters, exists := gettersGenerated[model.Name]
|
||||
if !exists {
|
||||
typeGetters = make(map[string]struct{})
|
||||
gettersGenerated[model.Name] = typeGetters
|
||||
}
|
||||
|
||||
_, exists = typeGetters[field.GoName]
|
||||
typeGetters[field.GoName] = struct{}{}
|
||||
if exists {
|
||||
return ""
|
||||
}
|
||||
|
||||
_, interfaceFieldTypeIsPointer := field.Type.(*types.Pointer)
|
||||
var structFieldTypeIsPointer bool
|
||||
for _, f := range model.Fields {
|
||||
if f.GoName == field.GoName {
|
||||
_, structFieldTypeIsPointer = f.Type.(*types.Pointer)
|
||||
break
|
||||
}
|
||||
}
|
||||
goType := templates.CurrentImports.LookupType(field.Type)
|
||||
if strings.HasPrefix(goType, "[]") {
|
||||
getter := fmt.Sprintf("func (this %s) Get%s() %s {\n", templates.ToGo(model.Name), field.GoName, goType)
|
||||
getter += fmt.Sprintf("\tif this.%s == nil { return nil }\n", field.GoName)
|
||||
getter += fmt.Sprintf("\tinterfaceSlice := make(%s, 0, len(this.%s))\n", goType, field.GoName)
|
||||
getter += fmt.Sprintf("\tfor _, concrete := range this.%s { interfaceSlice = append(interfaceSlice, ", field.GoName)
|
||||
if interfaceFieldTypeIsPointer && !structFieldTypeIsPointer {
|
||||
getter += "&"
|
||||
} else if !interfaceFieldTypeIsPointer && structFieldTypeIsPointer {
|
||||
getter += "*"
|
||||
}
|
||||
getter += "concrete) }\n"
|
||||
getter += "\treturn interfaceSlice\n"
|
||||
getter += "}"
|
||||
return getter
|
||||
} else {
|
||||
getter := fmt.Sprintf("func (this %s) Get%s() %s { return ", templates.ToGo(model.Name), field.GoName, goType)
|
||||
|
||||
if interfaceFieldTypeIsPointer && !structFieldTypeIsPointer {
|
||||
getter += "&"
|
||||
} else if !interfaceFieldTypeIsPointer && structFieldTypeIsPointer {
|
||||
getter += "*"
|
||||
}
|
||||
|
||||
getter += fmt.Sprintf("this.%s }", field.GoName)
|
||||
return getter
|
||||
}
|
||||
}
|
||||
funcMap := template.FuncMap{
|
||||
"getInterfaceByName": getInterfaceByName,
|
||||
"generateGetter": generateGetter,
|
||||
}
|
||||
|
||||
err := templates.Render(templates.Options{
|
||||
PackageName: cfg.Model.Package,
|
||||
Filename: cfg.Model.Filename,
|
||||
Data: b,
|
||||
GeneratedHeader: true,
|
||||
Packages: cfg.Packages,
|
||||
Template: modelTemplate,
|
||||
Funcs: funcMap,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -269,6 +294,94 @@ func (m *Plugin) MutateConfig(cfg *config.Config) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (m *Plugin) generateFields(cfg *config.Config, schemaType *ast.Definition) ([]*Field, error) {
|
||||
binder := cfg.NewBinder()
|
||||
fields := make([]*Field, 0)
|
||||
|
||||
for _, field := range schemaType.Fields {
|
||||
var typ types.Type
|
||||
fieldDef := cfg.Schema.Types[field.Type.Name()]
|
||||
|
||||
if cfg.Models.UserDefined(field.Type.Name()) {
|
||||
var err error
|
||||
typ, err = binder.FindTypeFromName(cfg.Models[field.Type.Name()].Model[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
switch fieldDef.Kind {
|
||||
case ast.Scalar:
|
||||
// no user defined model, referencing a default scalar
|
||||
typ = types.NewNamed(
|
||||
types.NewTypeName(0, cfg.Model.Pkg(), "string", nil),
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
|
||||
case ast.Interface, ast.Union:
|
||||
// no user defined model, referencing a generated interface type
|
||||
typ = types.NewNamed(
|
||||
types.NewTypeName(0, cfg.Model.Pkg(), templates.ToGo(field.Type.Name()), nil),
|
||||
types.NewInterfaceType([]*types.Func{}, []types.Type{}),
|
||||
nil,
|
||||
)
|
||||
|
||||
case ast.Enum:
|
||||
// no user defined model, must reference a generated enum
|
||||
typ = types.NewNamed(
|
||||
types.NewTypeName(0, cfg.Model.Pkg(), templates.ToGo(field.Type.Name()), nil),
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
|
||||
case ast.Object, ast.InputObject:
|
||||
// no user defined model, must reference a generated struct
|
||||
typ = types.NewNamed(
|
||||
types.NewTypeName(0, cfg.Model.Pkg(), templates.ToGo(field.Type.Name()), nil),
|
||||
types.NewStruct(nil, nil),
|
||||
nil,
|
||||
)
|
||||
|
||||
default:
|
||||
panic(fmt.Errorf("unknown ast type %s", fieldDef.Kind))
|
||||
}
|
||||
}
|
||||
|
||||
name := templates.ToGo(field.Name)
|
||||
if nameOveride := cfg.Models[schemaType.Name].Fields[field.Name].FieldName; nameOveride != "" {
|
||||
name = nameOveride
|
||||
}
|
||||
|
||||
typ = binder.CopyModifiersFromAst(field.Type, typ)
|
||||
|
||||
if cfg.StructFieldsAlwaysPointers {
|
||||
if isStruct(typ) && (fieldDef.Kind == ast.Object || fieldDef.Kind == ast.InputObject) {
|
||||
typ = types.NewPointer(typ)
|
||||
}
|
||||
}
|
||||
|
||||
f := &Field{
|
||||
Name: field.Name,
|
||||
GoName: name,
|
||||
Type: typ,
|
||||
Description: field.Description,
|
||||
Tag: `json:"` + field.Name + `"`,
|
||||
}
|
||||
|
||||
if m.FieldHook != nil {
|
||||
mf, err := m.FieldHook(schemaType, field, f)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("generror: field %v.%v: %w", schemaType.Name, field.Name, err)
|
||||
}
|
||||
f = mf
|
||||
}
|
||||
|
||||
fields = append(fields, f)
|
||||
}
|
||||
|
||||
return fields, nil
|
||||
}
|
||||
|
||||
// GoTagFieldHook applies the goTag directive to the generated Field f. When applying the Tag to the field, the field
|
||||
// name is used when no value argument is present.
|
||||
func GoTagFieldHook(td *ast.Definition, fd *ast.FieldDefinition, f *Field) (*Field, error) {
|
||||
|
|
@ -303,3 +416,55 @@ func isStruct(t types.Type) bool {
|
|||
_, is := t.Underlying().(*types.Struct)
|
||||
return is
|
||||
}
|
||||
|
||||
// findAndHandleCyclicalRelationships checks for cyclical relationships between generated structs and replaces them
|
||||
// with pointers. These relationships will produce compilation errors if they are not pointers.
|
||||
// Also handles recursive structs.
|
||||
func findAndHandleCyclicalRelationships(b *ModelBuild) {
|
||||
for ii, structA := range b.Models {
|
||||
for _, fieldA := range structA.Fields {
|
||||
if strings.Contains(fieldA.Type.String(), "NotCyclicalA") {
|
||||
fmt.Print()
|
||||
}
|
||||
if !isStruct(fieldA.Type) {
|
||||
continue
|
||||
}
|
||||
|
||||
// the field Type string will be in the form "github.com/99designs/gqlgen/codegen/testserver/followschema.LoopA"
|
||||
// we only want the part after the last dot: "LoopA"
|
||||
// this could lead to false positives, as we are only checking the name of the struct type, but these
|
||||
// should be extremely rare, if it is even possible at all.
|
||||
fieldAStructNameParts := strings.Split(fieldA.Type.String(), ".")
|
||||
fieldAStructName := fieldAStructNameParts[len(fieldAStructNameParts)-1]
|
||||
|
||||
// find this struct type amongst the generated structs
|
||||
for jj, structB := range b.Models {
|
||||
if structB.Name != fieldAStructName {
|
||||
continue
|
||||
}
|
||||
|
||||
// check if structB contains a cyclical reference back to structA
|
||||
var cyclicalReferenceFound bool
|
||||
for _, fieldB := range structB.Fields {
|
||||
if !isStruct(fieldB.Type) {
|
||||
continue
|
||||
}
|
||||
|
||||
fieldBStructNameParts := strings.Split(fieldB.Type.String(), ".")
|
||||
fieldBStructName := fieldBStructNameParts[len(fieldBStructNameParts)-1]
|
||||
if fieldBStructName == structA.Name {
|
||||
cyclicalReferenceFound = true
|
||||
fieldB.Type = types.NewPointer(fieldB.Type)
|
||||
// keep looping in case this struct has additional fields of this type
|
||||
}
|
||||
}
|
||||
|
||||
// if this is a recursive struct (i.e. structA == structB), ensure that we only change this field to a pointer once
|
||||
if cyclicalReferenceFound && ii != jj {
|
||||
fieldA.Type = types.NewPointer(fieldA.Type)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
50
vendor/github.com/99designs/gqlgen/plugin/modelgen/models.gotpl
generated
vendored
50
vendor/github.com/99designs/gqlgen/plugin/modelgen/models.gotpl
generated
vendored
|
|
@ -14,74 +14,88 @@
|
|||
|
||||
{{- range $model := .Interfaces }}
|
||||
{{ with .Description }} {{.|prefixLines "// "}} {{ end }}
|
||||
type {{.Name|go }} interface {
|
||||
type {{ goModelName .Name }} interface {
|
||||
{{- range $impl := .Implements }}
|
||||
{{ $impl|go }}
|
||||
Is{{ goModelName $impl }}()
|
||||
{{- end }}
|
||||
Is{{ goModelName .Name }}()
|
||||
{{- range $field := .Fields }}
|
||||
{{- with .Description }}
|
||||
{{.|prefixLines "// "}}
|
||||
{{- end}}
|
||||
Get{{ $field.GoName }}() {{ $field.Type | ref }}
|
||||
{{- end }}
|
||||
Is{{.Name|go }}()
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
{{ range $model := .Models }}
|
||||
{{with .Description }} {{.|prefixLines "// "}} {{end}}
|
||||
type {{ .Name|go }} struct {
|
||||
type {{ goModelName .Name }} struct {
|
||||
{{- range $field := .Fields }}
|
||||
{{- with .Description }}
|
||||
{{.|prefixLines "// "}}
|
||||
{{- end}}
|
||||
{{ $field.Name|go }} {{$field.Type | ref}} `{{$field.Tag}}`
|
||||
{{ $field.GoName }} {{$field.Type | ref}} `{{$field.Tag}}`
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
{{- range $iface := .Implements }}
|
||||
func ({{ $model.Name|go }}) Is{{ $iface|go }}() {}
|
||||
{{- end }}
|
||||
{{ range .Implements }}
|
||||
func ({{ goModelName $model.Name }}) Is{{ goModelName . }}() {}
|
||||
{{- with getInterfaceByName . }}
|
||||
{{- range .Fields }}
|
||||
{{- with .Description }}
|
||||
{{.|prefixLines "// "}}
|
||||
{{- end}}
|
||||
{{ generateGetter $model . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
{{- end}}
|
||||
|
||||
{{ range $enum := .Enums }}
|
||||
{{ with .Description }} {{.|prefixLines "// "}} {{end}}
|
||||
type {{.Name|go }} string
|
||||
type {{ goModelName .Name }} string
|
||||
const (
|
||||
{{- range $value := .Values}}
|
||||
{{- with .Description}}
|
||||
{{.|prefixLines "// "}}
|
||||
{{- end}}
|
||||
{{ $enum.Name|go }}{{ .Name|go }} {{$enum.Name|go }} = {{.Name|quote}}
|
||||
{{ goModelName $enum.Name .Name }} {{ goModelName $enum.Name }} = {{ .Name|quote }}
|
||||
{{- end }}
|
||||
)
|
||||
|
||||
var All{{.Name|go }} = []{{ .Name|go }}{
|
||||
var All{{ goModelName .Name }} = []{{ goModelName .Name }}{
|
||||
{{- range $value := .Values}}
|
||||
{{$enum.Name|go }}{{ .Name|go }},
|
||||
{{ goModelName $enum.Name .Name }},
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
func (e {{.Name|go }}) IsValid() bool {
|
||||
func (e {{ goModelName .Name }}) IsValid() bool {
|
||||
switch e {
|
||||
case {{ range $index, $element := .Values}}{{if $index}},{{end}}{{ $enum.Name|go }}{{ $element.Name|go }}{{end}}:
|
||||
case {{ range $index, $element := .Values}}{{if $index}},{{end}}{{ goModelName $enum.Name $element.Name }}{{end}}:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (e {{.Name|go }}) String() string {
|
||||
func (e {{ goModelName .Name }}) String() string {
|
||||
return string(e)
|
||||
}
|
||||
|
||||
func (e *{{.Name|go }}) UnmarshalGQL(v interface{}) error {
|
||||
func (e *{{ goModelName .Name }}) UnmarshalGQL(v interface{}) error {
|
||||
str, ok := v.(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("enums must be strings")
|
||||
}
|
||||
|
||||
*e = {{ .Name|go }}(str)
|
||||
*e = {{ goModelName .Name }}(str)
|
||||
if !e.IsValid() {
|
||||
return fmt.Errorf("%s is not a valid {{ .Name }}", str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e {{.Name|go }}) MarshalGQL(w io.Writer) {
|
||||
func (e {{ goModelName .Name }}) MarshalGQL(w io.Writer) {
|
||||
fmt.Fprint(w, strconv.Quote(e.String()))
|
||||
}
|
||||
|
||||
|
|
|
|||
23
vendor/github.com/99designs/gqlgen/plugin/resolvergen/resolver.go
generated
vendored
23
vendor/github.com/99designs/gqlgen/plugin/resolvergen/resolver.go
generated
vendored
|
|
@ -1,7 +1,9 @@
|
|||
package resolvergen
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
|
@ -12,8 +14,13 @@ import (
|
|||
"github.com/99designs/gqlgen/codegen/templates"
|
||||
"github.com/99designs/gqlgen/internal/rewrite"
|
||||
"github.com/99designs/gqlgen/plugin"
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
//go:embed resolver.gotpl
|
||||
var resolverTemplate string
|
||||
|
||||
func New() plugin.Plugin {
|
||||
return &Plugin{}
|
||||
}
|
||||
|
|
@ -58,7 +65,7 @@ func (m *Plugin) generateSingleFile(data *codegen.Data) error {
|
|||
continue
|
||||
}
|
||||
|
||||
resolver := Resolver{o, f, `panic("not implemented")`}
|
||||
resolver := Resolver{o, f, "// foo", `panic("not implemented")`}
|
||||
file.Resolvers = append(file.Resolvers, &resolver)
|
||||
}
|
||||
}
|
||||
|
|
@ -76,6 +83,7 @@ func (m *Plugin) generateSingleFile(data *codegen.Data) error {
|
|||
Filename: data.Config.Resolver.Filename,
|
||||
Data: resolverBuild,
|
||||
Packages: data.Config.Packages,
|
||||
Template: resolverTemplate,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -98,8 +106,9 @@ func (m *Plugin) generatePerSchema(data *codegen.Data) error {
|
|||
files[fn] = &File{}
|
||||
}
|
||||
|
||||
caser := cases.Title(language.English, cases.NoLower)
|
||||
rewriter.MarkStructCopied(templates.LcFirst(o.Name) + templates.UcFirst(data.Config.Resolver.Type))
|
||||
rewriter.GetMethodBody(data.Config.Resolver.Type, strings.Title(o.Name))
|
||||
rewriter.GetMethodBody(data.Config.Resolver.Type, caser.String(o.Name))
|
||||
files[fn].Objects = append(files[fn].Objects, o)
|
||||
}
|
||||
for _, f := range o.Fields {
|
||||
|
|
@ -109,11 +118,15 @@ func (m *Plugin) generatePerSchema(data *codegen.Data) error {
|
|||
|
||||
structName := templates.LcFirst(o.Name) + templates.UcFirst(data.Config.Resolver.Type)
|
||||
implementation := strings.TrimSpace(rewriter.GetMethodBody(structName, f.GoFieldName))
|
||||
comment := strings.TrimSpace(strings.TrimLeft(rewriter.GetMethodComment(structName, f.GoFieldName), `\`))
|
||||
if implementation == "" {
|
||||
implementation = `panic(fmt.Errorf("not implemented"))`
|
||||
implementation = fmt.Sprintf("panic(fmt.Errorf(\"not implemented: %v - %v\"))", f.GoFieldName, f.Name)
|
||||
}
|
||||
if comment == "" {
|
||||
comment = fmt.Sprintf("%v is the resolver for the %v field.", f.GoFieldName, f.Name)
|
||||
}
|
||||
|
||||
resolver := Resolver{o, f, implementation}
|
||||
resolver := Resolver{o, f, comment, implementation}
|
||||
fn := gqlToResolverName(data.Config.Resolver.Dir(), f.Position.Src.Name, data.Config.Resolver.FilenameTemplate)
|
||||
if files[fn] == nil {
|
||||
files[fn] = &File{}
|
||||
|
|
@ -143,6 +156,7 @@ func (m *Plugin) generatePerSchema(data *codegen.Data) error {
|
|||
Filename: filename,
|
||||
Data: resolverBuild,
|
||||
Packages: data.Config.Packages,
|
||||
Template: resolverTemplate,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -198,6 +212,7 @@ func (f *File) Imports() string {
|
|||
type Resolver struct {
|
||||
Object *codegen.Object
|
||||
Field *codegen.Field
|
||||
Comment string
|
||||
Implementation string
|
||||
}
|
||||
|
||||
|
|
|
|||
1
vendor/github.com/99designs/gqlgen/plugin/resolvergen/resolver.gotpl
generated
vendored
1
vendor/github.com/99designs/gqlgen/plugin/resolvergen/resolver.gotpl
generated
vendored
|
|
@ -19,6 +19,7 @@
|
|||
{{ end }}
|
||||
|
||||
{{ range $resolver := .Resolvers -}}
|
||||
// {{ $resolver.Comment }}
|
||||
func (r *{{lcFirst $resolver.Object.Name}}{{ucFirst $.ResolverType}}) {{$resolver.Field.GoFieldName}}{{ $resolver.Field.ShortResolverDeclaration }} {
|
||||
{{ $resolver.Implementation }}
|
||||
}
|
||||
|
|
|
|||
5
vendor/github.com/99designs/gqlgen/plugin/servergen/server.go
generated
vendored
5
vendor/github.com/99designs/gqlgen/plugin/servergen/server.go
generated
vendored
|
|
@ -1,6 +1,7 @@
|
|||
package servergen
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"errors"
|
||||
"io/fs"
|
||||
"log"
|
||||
|
|
@ -11,6 +12,9 @@ import (
|
|||
"github.com/99designs/gqlgen/plugin"
|
||||
)
|
||||
|
||||
//go:embed server.gotpl
|
||||
var serverTemplate string
|
||||
|
||||
func New(filename string) plugin.Plugin {
|
||||
return &Plugin{filename}
|
||||
}
|
||||
|
|
@ -37,6 +41,7 @@ func (m *Plugin) GenerateCode(data *codegen.Data) error {
|
|||
Filename: m.filename,
|
||||
Data: serverBuild,
|
||||
Packages: data.Config.Packages,
|
||||
Template: serverTemplate,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
8
vendor/github.com/99designs/gqlgen/tools.go
generated
vendored
8
vendor/github.com/99designs/gqlgen/tools.go
generated
vendored
|
|
@ -1,8 +0,0 @@
|
|||
//go:build tools
|
||||
// +build tools
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
_ "github.com/matryer/moq"
|
||||
)
|
||||
5
vendor/github.com/Yamashou/gqlgenc/.golangci.yml
generated
vendored
5
vendor/github.com/Yamashou/gqlgenc/.golangci.yml
generated
vendored
|
|
@ -44,9 +44,13 @@ linters:
|
|||
- varnamelen
|
||||
- nilnil
|
||||
- structcheck
|
||||
- exhaustruct
|
||||
- nonamedreturns
|
||||
fast: false
|
||||
|
||||
issues:
|
||||
max-issues-per-linter: 0
|
||||
max-same-issues: 0
|
||||
exclude-rules:
|
||||
# Test
|
||||
- path: _test\.go
|
||||
|
|
@ -57,6 +61,7 @@ issues:
|
|||
linters:
|
||||
- unused
|
||||
- structcheck
|
||||
- forcetypeassert
|
||||
- path: introspection/type.go
|
||||
linters:
|
||||
- structcheck # These types fits IntrospectionQuery
|
||||
|
|
|
|||
6
vendor/github.com/Yamashou/gqlgenc/README.md
generated
vendored
6
vendor/github.com/Yamashou/gqlgenc/README.md
generated
vendored
|
|
@ -48,6 +48,9 @@ endpoint:
|
|||
Authorization: "Bearer ${ANNICT_KEY}" # support environment variables
|
||||
query:
|
||||
- "./query/*.graphql" # Where are all the query files located?
|
||||
generate:
|
||||
clientV2: true # Generate a Client that provides a new signature
|
||||
clientInterfaceName: "GithubGraphQLClient" # Determine the name of the generated client interface
|
||||
```
|
||||
|
||||
Load a schema from a local file:
|
||||
|
|
@ -68,6 +71,9 @@ schema:
|
|||
- "schema/**/*.graphql" # Where are all the schema files located?
|
||||
query:
|
||||
- "./query/*.graphql" # Where are all the query files located?
|
||||
generate:
|
||||
clientV2: true # Generate a Client that provides a new signature
|
||||
clientInterfaceName: "GithubGraphQLClient" # Determine the name of the generated client interface
|
||||
```
|
||||
|
||||
Execute the following command on same directory for .gqlgenc.yml
|
||||
|
|
|
|||
9
vendor/github.com/Yamashou/gqlgenc/client/client.go
generated
vendored
9
vendor/github.com/Yamashou/gqlgenc/client/client.go
generated
vendored
|
|
@ -5,7 +5,7 @@ import (
|
|||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/Yamashou/gqlgenc/graphqljson"
|
||||
|
|
@ -55,6 +55,9 @@ func (c *Client) newRequest(ctx context.Context, operationName, query string, va
|
|||
return nil, fmt.Errorf("create request struct failed: %w", err)
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json; charset=utf-8")
|
||||
req.Header.Set("Accept", "application/json; charset=utf-8")
|
||||
|
||||
for _, httpRequestOption := range c.HTTPRequestOptions {
|
||||
httpRequestOption(req)
|
||||
}
|
||||
|
|
@ -109,8 +112,6 @@ func (c *Client) Post(ctx context.Context, operationName, query string, respData
|
|||
if err != nil {
|
||||
return fmt.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 {
|
||||
|
|
@ -118,7 +119,7 @@ func (c *Client) Post(ctx context.Context, operationName, query string, respData
|
|||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read response body: %w", err)
|
||||
}
|
||||
|
|
|
|||
3
vendor/github.com/Yamashou/gqlgenc/clientgen/query_source.go
generated
vendored
3
vendor/github.com/Yamashou/gqlgenc/clientgen/query_source.go
generated
vendored
|
|
@ -24,7 +24,6 @@ package clientgen
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
|
|
@ -94,7 +93,7 @@ func LoadQuerySources(queryFileNames []string) ([]*ast.Source, error) {
|
|||
filename = filepath.ToSlash(filename)
|
||||
var err error
|
||||
var schemaRaw []byte
|
||||
schemaRaw, err = ioutil.ReadFile(filename)
|
||||
schemaRaw, err = os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to open schema: %w", err)
|
||||
}
|
||||
|
|
|
|||
2
vendor/github.com/Yamashou/gqlgenc/clientgen/template.go
generated
vendored
2
vendor/github.com/Yamashou/gqlgenc/clientgen/template.go
generated
vendored
|
|
@ -19,7 +19,7 @@ func RenderTemplate(cfg *config.Config, query *Query, mutation *Mutation, fragme
|
|||
"Operation": operations,
|
||||
"OperationResponse": operationResponses,
|
||||
"GenerateClient": generateCfg.ShouldGenerateClient(),
|
||||
"ClientInterfaceName": generateCfg.ClientInterfaceName,
|
||||
"ClientInterfaceName": generateCfg.GetClientInterfaceName(),
|
||||
},
|
||||
Packages: cfg.Packages,
|
||||
PackageDoc: "// Code generated by github.com/Yamashou/gqlgenc, DO NOT EDIT.\n",
|
||||
|
|
|
|||
1
vendor/github.com/Yamashou/gqlgenc/clientgen/template.gotpl
generated
vendored
1
vendor/github.com/Yamashou/gqlgenc/clientgen/template.gotpl
generated
vendored
|
|
@ -4,7 +4,6 @@
|
|||
{{ reserveImport "encoding/json" }}
|
||||
{{ reserveImport "fmt" }}
|
||||
{{ reserveImport "io" }}
|
||||
{{ reserveImport "io/ioutil" }}
|
||||
{{ reserveImport "net/http" }}
|
||||
{{ reserveImport "net/url" }}
|
||||
{{ reserveImport "path" }}
|
||||
|
|
|
|||
3
vendor/github.com/Yamashou/gqlgenc/clientgenv2/query_source.go
generated
vendored
3
vendor/github.com/Yamashou/gqlgenc/clientgenv2/query_source.go
generated
vendored
|
|
@ -24,7 +24,6 @@ package clientgenv2
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
|
|
@ -94,7 +93,7 @@ func LoadQuerySources(queryFileNames []string) ([]*ast.Source, error) {
|
|||
filename = filepath.ToSlash(filename)
|
||||
var err error
|
||||
var schemaRaw []byte
|
||||
schemaRaw, err = ioutil.ReadFile(filename)
|
||||
schemaRaw, err = os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to open schema: %w", err)
|
||||
}
|
||||
|
|
|
|||
1
vendor/github.com/Yamashou/gqlgenc/clientgenv2/template.gotpl
generated
vendored
1
vendor/github.com/Yamashou/gqlgenc/clientgenv2/template.gotpl
generated
vendored
|
|
@ -4,7 +4,6 @@
|
|||
{{ reserveImport "encoding/json" }}
|
||||
{{ reserveImport "fmt" }}
|
||||
{{ reserveImport "io" }}
|
||||
{{ reserveImport "io/ioutil" }}
|
||||
{{ reserveImport "net/http" }}
|
||||
{{ reserveImport "net/url" }}
|
||||
{{ reserveImport "path" }}
|
||||
|
|
|
|||
7
vendor/github.com/Yamashou/gqlgenc/config/config.go
generated
vendored
7
vendor/github.com/Yamashou/gqlgenc/config/config.go
generated
vendored
|
|
@ -3,7 +3,6 @@ package config
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
|
@ -116,7 +115,7 @@ var path2regex = strings.NewReplacer(
|
|||
// LoadConfig loads and parses the config gqlgenc config
|
||||
func LoadConfig(filename string) (*Config, error) {
|
||||
var cfg Config
|
||||
b, err := ioutil.ReadFile(filename)
|
||||
b, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to read config: %w", err)
|
||||
}
|
||||
|
|
@ -188,7 +187,7 @@ func LoadConfig(filename string) (*Config, error) {
|
|||
filename = filepath.ToSlash(filename)
|
||||
var err error
|
||||
var schemaRaw []byte
|
||||
schemaRaw, err = ioutil.ReadFile(filename)
|
||||
schemaRaw, err = os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to open schema: %w", err)
|
||||
}
|
||||
|
|
@ -269,7 +268,7 @@ func (c *Config) loadRemoteSchema(ctx context.Context) (*ast.Schema, error) {
|
|||
func (c *Config) loadLocalSchema() (*ast.Schema, error) {
|
||||
schema, err := gqlparser.LoadSchema(c.GQLConfig.Sources...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("loadLocalSchema: %w", err)
|
||||
}
|
||||
|
||||
return schema, nil
|
||||
|
|
|
|||
38
vendor/github.com/Yamashou/gqlgenc/generator/generater.go
generated
vendored
38
vendor/github.com/Yamashou/gqlgenc/generator/generater.go
generated
vendored
|
|
@ -5,33 +5,43 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/99designs/gqlgen/api"
|
||||
codegenconfig "github.com/99designs/gqlgen/codegen/config"
|
||||
"github.com/99designs/gqlgen/plugin"
|
||||
"github.com/99designs/gqlgen/plugin/modelgen"
|
||||
"github.com/Yamashou/gqlgenc/config"
|
||||
)
|
||||
|
||||
// mutateHook adds the "omitempty" option to nilable fields.
|
||||
// mutateHook adds the "omitempty" option to optional field from input type model as defined in graphql schema
|
||||
// For more info see https://github.com/99designs/gqlgen/blob/master/docs/content/recipes/modelgen-hook.md
|
||||
func mutateHook(build *modelgen.ModelBuild) *modelgen.ModelBuild {
|
||||
for _, model := range build.Models {
|
||||
for _, field := range model.Fields {
|
||||
field.Tag = `json:"` + field.Name
|
||||
if codegenconfig.IsNilable(field.Type) {
|
||||
field.Tag += ",omitempty"
|
||||
}
|
||||
field.Tag += `"`
|
||||
}
|
||||
}
|
||||
func mutateHook(cfg *config.Config) func(b *modelgen.ModelBuild) *modelgen.ModelBuild {
|
||||
return func(build *modelgen.ModelBuild) *modelgen.ModelBuild {
|
||||
for _, model := range build.Models {
|
||||
// only handle input type model
|
||||
if schemaModel, ok := cfg.GQLConfig.Schema.Types[model.Name]; ok && schemaModel.IsInputType() {
|
||||
for _, field := range model.Fields {
|
||||
// find field in graphql schema
|
||||
for _, def := range schemaModel.Fields {
|
||||
if def.Name == field.Name {
|
||||
// only add 'omitempty' on optional field as defined in graphql schema
|
||||
if !def.Type.NonNull {
|
||||
field.Tag = `json:"` + field.Name + `,omitempty"`
|
||||
}
|
||||
|
||||
return build
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return build
|
||||
}
|
||||
}
|
||||
|
||||
func Generate(ctx context.Context, cfg *config.Config, option ...api.Option) error {
|
||||
var plugins []plugin.Plugin
|
||||
if cfg.Model.IsDefined() {
|
||||
p := modelgen.Plugin{
|
||||
MutateHook: mutateHook,
|
||||
MutateHook: mutateHook(cfg),
|
||||
}
|
||||
plugins = append(plugins, &p)
|
||||
}
|
||||
|
|
|
|||
13
vendor/github.com/Yamashou/gqlgenc/graphqljson/graphql.go
generated
vendored
13
vendor/github.com/Yamashou/gqlgenc/graphqljson/graphql.go
generated
vendored
|
|
@ -146,12 +146,17 @@ func (d *Decoder) decode() error {
|
|||
|
||||
// We've just consumed the current token, which was the key.
|
||||
// Read the next token, which should be the value.
|
||||
// If it's of json.RawMessage type, decode the value.
|
||||
if matchingFieldValue.Type() == reflect.TypeOf(json.RawMessage{}) {
|
||||
// If it's of json.RawMessage or map type, decode the value.
|
||||
switch matchingFieldValue.Type() {
|
||||
case reflect.TypeOf(json.RawMessage{}):
|
||||
var data json.RawMessage
|
||||
err = d.jsonDecoder.Decode(&data)
|
||||
tok = data
|
||||
} else {
|
||||
case reflect.TypeOf(map[string]interface{}{}):
|
||||
var data map[string]interface{}
|
||||
err = d.jsonDecoder.Decode(&data)
|
||||
tok = data
|
||||
default:
|
||||
tok, err = d.jsonDecoder.Token()
|
||||
}
|
||||
|
||||
|
|
@ -183,7 +188,7 @@ func (d *Decoder) decode() error {
|
|||
}
|
||||
|
||||
switch tok := tok.(type) {
|
||||
case string, json.Number, bool, nil, json.RawMessage:
|
||||
case string, json.Number, bool, nil, json.RawMessage, map[string]interface{}:
|
||||
// Value.
|
||||
|
||||
for i := range d.vs {
|
||||
|
|
|
|||
121
vendor/github.com/Yamashou/gqlgenc/introspection/parse.go
generated
vendored
121
vendor/github.com/Yamashou/gqlgenc/introspection/parse.go
generated
vendored
|
|
@ -2,6 +2,7 @@ package introspection
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/vektah/gqlparser/v2/ast"
|
||||
)
|
||||
|
|
@ -12,6 +13,7 @@ func ParseIntrospectionQuery(url string, query Query) *ast.SchemaDocument {
|
|||
Name: "remote",
|
||||
BuiltIn: false,
|
||||
}},
|
||||
typeMap: query.Schema.Types.NameMap(),
|
||||
}
|
||||
|
||||
if url != "" {
|
||||
|
|
@ -22,23 +24,27 @@ func ParseIntrospectionQuery(url string, query Query) *ast.SchemaDocument {
|
|||
}
|
||||
|
||||
type parser struct {
|
||||
sharedPosition *ast.Position
|
||||
sharedPosition *ast.Position
|
||||
typeMap map[string]*FullType
|
||||
deprecatedDirectiveDefinition *ast.DirectiveDefinition
|
||||
}
|
||||
|
||||
func (p parser) parseIntrospectionQuery(query Query) *ast.SchemaDocument {
|
||||
var doc ast.SchemaDocument
|
||||
typeMap := query.Schema.Types.NameMap()
|
||||
|
||||
doc.Schema = append(doc.Schema, p.parseSchemaDefinition(query, typeMap))
|
||||
doc.Schema = append(doc.Schema, p.parseSchemaDefinition(query, p.typeMap))
|
||||
doc.Position = p.sharedPosition
|
||||
|
||||
for _, typeVale := range typeMap {
|
||||
doc.Definitions = append(doc.Definitions, p.parseTypeSystemDefinition(typeVale))
|
||||
}
|
||||
|
||||
// parseDirectiveDefinition before parseTypeSystemDefinition
|
||||
// Because SystemDefinition depends on DirectiveDefinition
|
||||
for _, directiveValue := range query.Schema.Directives {
|
||||
doc.Directives = append(doc.Directives, p.parseDirectiveDefinition(directiveValue))
|
||||
}
|
||||
p.deprecatedDirectiveDefinition = doc.Directives.ForName("deprecated")
|
||||
|
||||
for _, typeVale := range p.typeMap {
|
||||
doc.Definitions = append(doc.Definitions, p.parseTypeSystemDefinition(typeVale))
|
||||
}
|
||||
|
||||
return &doc
|
||||
}
|
||||
|
|
@ -116,6 +122,7 @@ func (p parser) parseObjectFields(typeVale *FullType) ast.FieldList {
|
|||
Arguments: args,
|
||||
Type: typ,
|
||||
Position: p.sharedPosition,
|
||||
Directives: p.buildDeprecatedDirective(field),
|
||||
}
|
||||
fieldList = append(fieldList, fieldDefinition)
|
||||
}
|
||||
|
|
@ -164,7 +171,7 @@ func (p parser) parseObjectTypeDefinition(typeVale *FullType) *ast.Definition {
|
|||
Fields: fieldList,
|
||||
EnumValues: enums,
|
||||
Position: p.sharedPosition,
|
||||
BuiltIn: true,
|
||||
BuiltIn: builtInObject(typeVale),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -182,7 +189,7 @@ func (p parser) parseInterfaceTypeDefinition(typeVale *FullType) *ast.Definition
|
|||
Interfaces: interfaces,
|
||||
Fields: fieldList,
|
||||
Position: p.sharedPosition,
|
||||
BuiltIn: true,
|
||||
BuiltIn: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -200,7 +207,7 @@ func (p parser) parseInputObjectTypeDefinition(typeVale *FullType) *ast.Definiti
|
|||
Interfaces: interfaces,
|
||||
Fields: fieldList,
|
||||
Position: p.sharedPosition,
|
||||
BuiltIn: true,
|
||||
BuiltIn: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -216,7 +223,7 @@ func (p parser) parseUnionTypeDefinition(typeVale *FullType) *ast.Definition {
|
|||
Name: pointerString(typeVale.Name),
|
||||
Types: unions,
|
||||
Position: p.sharedPosition,
|
||||
BuiltIn: true,
|
||||
BuiltIn: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -237,7 +244,7 @@ func (p parser) parseEnumTypeDefinition(typeVale *FullType) *ast.Definition {
|
|||
Name: pointerString(typeVale.Name),
|
||||
EnumValues: enums,
|
||||
Position: p.sharedPosition,
|
||||
BuiltIn: true,
|
||||
BuiltIn: builtInEnum(typeVale),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -247,7 +254,7 @@ func (p parser) parseScalarTypeExtension(typeVale *FullType) *ast.Definition {
|
|||
Description: pointerString(typeVale.Description),
|
||||
Name: pointerString(typeVale.Name),
|
||||
Position: p.sharedPosition,
|
||||
BuiltIn: true,
|
||||
BuiltIn: builtInScalar(typeVale),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -279,7 +286,7 @@ func (p parser) buildInputValue(input *InputValue) *ast.ArgumentDefinition {
|
|||
if input.DefaultValue != nil {
|
||||
defaultValue = &ast.Value{
|
||||
Raw: pointerString(input.DefaultValue),
|
||||
Kind: ast.Variable,
|
||||
Kind: p.parseValueKind(typ),
|
||||
Position: p.sharedPosition,
|
||||
}
|
||||
}
|
||||
|
|
@ -317,6 +324,67 @@ func (p parser) getType(typeRef *TypeRef) *ast.Type {
|
|||
return ast.NamedType(pointerString(typeRef.Name), p.sharedPosition)
|
||||
}
|
||||
|
||||
func (p parser) buildDeprecatedDirective(field *FieldValue) ast.DirectiveList {
|
||||
var directives ast.DirectiveList
|
||||
if field.IsDeprecated {
|
||||
var arguments ast.ArgumentList
|
||||
if field.DeprecationReason != nil {
|
||||
arguments = append(arguments, &ast.Argument{
|
||||
Name: "reason",
|
||||
Value: &ast.Value{
|
||||
Raw: *field.DeprecationReason,
|
||||
Kind: ast.StringValue,
|
||||
Position: p.sharedPosition,
|
||||
},
|
||||
Position: p.sharedPosition,
|
||||
})
|
||||
}
|
||||
deprecatedDirective := &ast.Directive{
|
||||
Name: "deprecated",
|
||||
Arguments: arguments,
|
||||
Position: p.sharedPosition,
|
||||
ParentDefinition: nil,
|
||||
Definition: p.deprecatedDirectiveDefinition,
|
||||
Location: ast.LocationVariableDefinition,
|
||||
}
|
||||
directives = append(directives, deprecatedDirective)
|
||||
}
|
||||
|
||||
return directives
|
||||
}
|
||||
|
||||
func (p parser) parseValueKind(typ *ast.Type) ast.ValueKind {
|
||||
typName := typ.Name()
|
||||
|
||||
if fullType, ok := p.typeMap[typName]; ok {
|
||||
switch fullType.Kind {
|
||||
case TypeKindEnum:
|
||||
return ast.EnumValue
|
||||
case TypeKindInputObject, TypeKindObject, TypeKindUnion, TypeKindInterface:
|
||||
return ast.ObjectValue
|
||||
case TypeKindList:
|
||||
return ast.ListValue
|
||||
case TypeKindNonNull:
|
||||
panic(fmt.Sprintf("parseValueKind not match Type Name: %s", typ.Name()))
|
||||
case TypeKindScalar:
|
||||
switch typName {
|
||||
case "Int":
|
||||
return ast.IntValue
|
||||
case "Float":
|
||||
return ast.FloatValue
|
||||
case "Boolean":
|
||||
return ast.BooleanValue
|
||||
case "String", "ID":
|
||||
return ast.StringValue
|
||||
default:
|
||||
return ast.StringValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("parseValueKind not match Type Name: %s", typ.Name()))
|
||||
}
|
||||
|
||||
func pointerString(s *string) string {
|
||||
if s == nil {
|
||||
return ""
|
||||
|
|
@ -324,3 +392,28 @@ func pointerString(s *string) string {
|
|||
|
||||
return *s
|
||||
}
|
||||
|
||||
func builtInScalar(fullType *FullType) bool {
|
||||
name := pointerString(fullType.Name)
|
||||
if strings.HasPrefix(name, "__") {
|
||||
return true
|
||||
}
|
||||
switch name {
|
||||
case "String", "Int", "Float", "Boolean", "ID":
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func builtInEnum(fullType *FullType) bool {
|
||||
name := pointerString(fullType.Name)
|
||||
|
||||
return strings.HasPrefix(name, "__")
|
||||
}
|
||||
|
||||
func builtInObject(fullType *FullType) bool {
|
||||
name := pointerString(fullType.Name)
|
||||
|
||||
return strings.HasPrefix(name, "__")
|
||||
}
|
||||
|
|
|
|||
5
vendor/github.com/anacrolix/dms/dlna/dlna.go
generated
vendored
5
vendor/github.com/anacrolix/dms/dlna/dlna.go
generated
vendored
|
|
@ -31,8 +31,8 @@ func BinaryInt(b bool) uint {
|
|||
// flags are in hex. trailing 24 zeroes, 26 are after the space
|
||||
// "DLNA.ORG_OP=" time-seek-range-supp bytes-range-header-supp
|
||||
func (cf ContentFeatures) String() (ret string) {
|
||||
//DLNA.ORG_PN=[a-zA-Z0-9_]*
|
||||
params := make([]string, 0, 2)
|
||||
// DLNA.ORG_PN=[a-zA-Z0-9_]*
|
||||
params := make([]string, 0, 3)
|
||||
if cf.ProfileName != "" {
|
||||
params = append(params, "DLNA.ORG_PN="+cf.ProfileName)
|
||||
}
|
||||
|
|
@ -41,6 +41,7 @@ func (cf ContentFeatures) String() (ret string) {
|
|||
BinaryInt(cf.SupportTimeSeek),
|
||||
BinaryInt(cf.SupportRange),
|
||||
BinaryInt(cf.Transcoded)))
|
||||
params = append(params, "DLNA.ORG_FLAGS=01700000000000000000000000000000")
|
||||
return strings.Join(params, ";")
|
||||
}
|
||||
|
||||
|
|
|
|||
50
vendor/github.com/anacrolix/dms/ssdp/ssdp.go
generated
vendored
50
vendor/github.com/anacrolix/dms/ssdp/ssdp.go
generated
vendored
|
|
@ -5,7 +5,6 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
|
|
@ -14,6 +13,8 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/anacrolix/log"
|
||||
|
||||
"golang.org/x/net/ipv4"
|
||||
)
|
||||
|
||||
|
|
@ -24,15 +25,13 @@ const (
|
|||
byebyeNTS = "ssdp:byebye"
|
||||
)
|
||||
|
||||
var (
|
||||
NetAddr *net.UDPAddr
|
||||
)
|
||||
var NetAddr *net.UDPAddr
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
NetAddr, err = net.ResolveUDPAddr("udp4", AddrString)
|
||||
if err != nil {
|
||||
log.Panicf("Could not resolve %s: %s", AddrString, err)
|
||||
log.Printf("Could not resolve %s: %s", AddrString, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -85,10 +84,12 @@ type Server struct {
|
|||
Server string
|
||||
Services []string
|
||||
Devices []string
|
||||
IPFilter func(net.IP) bool
|
||||
Location func(net.IP) string
|
||||
UUID string
|
||||
NotifyInterval time.Duration
|
||||
closed chan struct{}
|
||||
Logger log.Logger
|
||||
}
|
||||
|
||||
func makeConn(ifi net.Interface) (ret *net.UDPConn, err error) {
|
||||
|
|
@ -98,17 +99,23 @@ func makeConn(ifi net.Interface) (ret *net.UDPConn, err error) {
|
|||
}
|
||||
p := ipv4.NewPacketConn(ret)
|
||||
if err := p.SetMulticastTTL(2); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
if err := p.SetMulticastLoopback(true); err != nil {
|
||||
log.Println(err)
|
||||
log.Print(err)
|
||||
}
|
||||
// if err := p.SetMulticastLoopback(true); err != nil {
|
||||
// log.Println(err)
|
||||
// }
|
||||
return
|
||||
}
|
||||
|
||||
func (me *Server) serve() {
|
||||
for {
|
||||
b := make([]byte, me.Interface.MTU)
|
||||
size := me.Interface.MTU
|
||||
if size > 65536 {
|
||||
size = 65536
|
||||
} else if size <= 0 { // fix for windows with mtu 4gb
|
||||
size = 65536
|
||||
}
|
||||
b := make([]byte, size)
|
||||
n, addr, err := me.conn.ReadFromUDP(b)
|
||||
select {
|
||||
case <-me.closed:
|
||||
|
|
@ -116,7 +123,7 @@ func (me *Server) serve() {
|
|||
default:
|
||||
}
|
||||
if err != nil {
|
||||
log.Printf("error reading from UDP socket: %s", err)
|
||||
me.Logger.Printf("error reading from UDP socket: %s", err)
|
||||
break
|
||||
}
|
||||
go me.handle(b[:n], addr)
|
||||
|
|
@ -126,6 +133,9 @@ func (me *Server) serve() {
|
|||
func (me *Server) Init() (err error) {
|
||||
me.closed = make(chan struct{})
|
||||
me.conn, err = makeConn(me.Interface)
|
||||
if me.IPFilter == nil {
|
||||
me.IPFilter = func(net.IP) bool { return true }
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -152,6 +162,14 @@ func (me *Server) Serve() (err error) {
|
|||
}
|
||||
panic(fmt.Sprint("unexpected addr type:", addr))
|
||||
}()
|
||||
if !me.IPFilter(ip) {
|
||||
continue
|
||||
}
|
||||
if ip.IsLinkLocalUnicast() {
|
||||
// These addresses seem to confuse VLC. Possibly there's supposed to be a zone
|
||||
// included in the address, but I don't see one.
|
||||
continue
|
||||
}
|
||||
extraHdrs := [][2]string{
|
||||
{"CACHE-CONTROL", fmt.Sprintf("max-age=%d", 5*me.NotifyInterval/2/time.Second)},
|
||||
{"LOCATION", me.Location(ip)},
|
||||
|
|
@ -194,9 +212,9 @@ func (me *Server) makeNotifyMessage(target, nts string, extraHdrs [][2]string) [
|
|||
|
||||
func (me *Server) send(buf []byte, addr *net.UDPAddr) {
|
||||
if n, err := me.conn.WriteToUDP(buf, addr); err != nil {
|
||||
log.Printf("error writing to UDP socket: %s", err)
|
||||
me.Logger.Printf("error writing to UDP socket: %s", err)
|
||||
} else if n != len(buf) {
|
||||
log.Printf("short write: %d/%d bytes", n, len(buf))
|
||||
me.Logger.Printf("short write: %d/%d bytes", n, len(buf))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -212,7 +230,7 @@ func (me *Server) delayedSend(delay time.Duration, buf []byte, addr *net.UDPAddr
|
|||
|
||||
func (me *Server) log(args ...interface{}) {
|
||||
args = append([]interface{}{me.Interface.Name + ":"}, args...)
|
||||
log.Print(args...)
|
||||
me.Logger.Print(args...)
|
||||
}
|
||||
|
||||
func (me *Server) sendByeBye() {
|
||||
|
|
@ -244,7 +262,7 @@ func (me *Server) allTypes() (ret []string) {
|
|||
func (me *Server) handle(buf []byte, sender *net.UDPAddr) {
|
||||
req, err := ReadRequest(bufio.NewReader(bytes.NewReader(buf)))
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
me.Logger.Println(err)
|
||||
return
|
||||
}
|
||||
if req.Method != "M-SEARCH" || req.Header.Get("man") != `"ssdp:discover"` {
|
||||
|
|
@ -255,7 +273,7 @@ func (me *Server) handle(buf []byte, sender *net.UDPAddr) {
|
|||
mxHeader := req.Header.Get("mx")
|
||||
i, err := strconv.ParseUint(mxHeader, 0, 0)
|
||||
if err != nil {
|
||||
log.Printf("Invalid mx header %q: %s", mxHeader, err)
|
||||
me.Logger.Printf("Invalid mx header %q: %s", mxHeader, err)
|
||||
return
|
||||
}
|
||||
mx = uint(i)
|
||||
|
|
|
|||
3
vendor/github.com/anacrolix/dms/upnp/eventing.go
generated
vendored
3
vendor/github.com/anacrolix/dms/upnp/eventing.go
generated
vendored
|
|
@ -5,10 +5,11 @@ import (
|
|||
"encoding/xml"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"github.com/anacrolix/log"
|
||||
)
|
||||
|
||||
// TODO: Why use namespace prefixes in PropertySet et al? Because the spec
|
||||
|
|
|
|||
35
vendor/github.com/anacrolix/dms/upnp/upnp.go
generated
vendored
35
vendor/github.com/anacrolix/dms/upnp/upnp.go
generated
vendored
|
|
@ -4,21 +4,23 @@ import (
|
|||
"encoding/xml"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/anacrolix/log"
|
||||
)
|
||||
|
||||
var serviceURNRegexp *regexp.Regexp = regexp.MustCompile(`^urn:schemas-upnp-org:service:(\w+):(\d+)$`)
|
||||
var serviceURNRegexp *regexp.Regexp = regexp.MustCompile(`^urn:(.*):service:(\w+):(\d+)$`)
|
||||
|
||||
type ServiceURN struct {
|
||||
Auth string
|
||||
Type string
|
||||
Version uint64
|
||||
}
|
||||
|
||||
func (me ServiceURN) String() string {
|
||||
return fmt.Sprintf("urn:schemas-upnp-org:service:%s:%d", me.Type, me.Version)
|
||||
return fmt.Sprintf("urn:%s:service:%s:%d", me.Auth, me.Type, me.Version)
|
||||
}
|
||||
|
||||
func ParseServiceType(s string) (ret ServiceURN, err error) {
|
||||
|
|
@ -27,11 +29,12 @@ func ParseServiceType(s string) (ret ServiceURN, err error) {
|
|||
err = errors.New(s)
|
||||
return
|
||||
}
|
||||
if len(matches) != 3 {
|
||||
log.Panicf("Invalid serviceURNRegexp ?")
|
||||
if len(matches) != 4 {
|
||||
log.Panicf("Invalid serviceURNRegexp?")
|
||||
}
|
||||
ret.Type = matches[1]
|
||||
ret.Version, err = strconv.ParseUint(matches[2], 0, 0)
|
||||
ret.Auth = matches[1]
|
||||
ret.Type = matches[2]
|
||||
ret.Version, err = strconv.ParseUint(matches[3], 0, 0)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -80,17 +83,21 @@ type Service struct {
|
|||
}
|
||||
|
||||
type Device struct {
|
||||
DeviceType string `xml:"deviceType"`
|
||||
FriendlyName string `xml:"friendlyName"`
|
||||
Manufacturer string `xml:"manufacturer"`
|
||||
ModelName string `xml:"modelName"`
|
||||
UDN string
|
||||
IconList []Icon `xml:"iconList>icon"`
|
||||
ServiceList []Service `xml:"serviceList>service"`
|
||||
DeviceType string `xml:"deviceType"`
|
||||
FriendlyName string `xml:"friendlyName"`
|
||||
Manufacturer string `xml:"manufacturer"`
|
||||
ModelName string `xml:"modelName"`
|
||||
UDN string
|
||||
VendorXML string `xml:",innerxml"`
|
||||
IconList []Icon `xml:"iconList>icon"`
|
||||
ServiceList []Service `xml:"serviceList>service"`
|
||||
PresentationURL string `xml:"presentationURL,omitempty"`
|
||||
}
|
||||
|
||||
type DeviceDesc struct {
|
||||
XMLName xml.Name `xml:"urn:schemas-upnp-org:device-1-0 root"`
|
||||
NSDLNA string `xml:"xmlns:dlna,attr"`
|
||||
NSSEC string `xml:"xmlns:sec,attr"`
|
||||
SpecVersion SpecVersion `xml:"specVersion"`
|
||||
Device Device `xml:"device"`
|
||||
}
|
||||
|
|
|
|||
45
vendor/github.com/anacrolix/dms/upnpav/upnpav.go
generated
vendored
45
vendor/github.com/anacrolix/dms/upnpav/upnpav.go
generated
vendored
|
|
@ -2,12 +2,15 @@ package upnpav
|
|||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// NoSuchObjectErrorCode : The specified ObjectID is invalid.
|
||||
NoSuchObjectErrorCode = 701
|
||||
)
|
||||
|
||||
// Resource description
|
||||
type Resource struct {
|
||||
XMLName xml.Name `xml:"res"`
|
||||
ProtocolInfo string `xml:"protocolInfo,attr"`
|
||||
|
|
@ -18,28 +21,44 @@ type Resource struct {
|
|||
Resolution string `xml:"resolution,attr,omitempty"`
|
||||
}
|
||||
|
||||
// Container description
|
||||
type Container struct {
|
||||
Object
|
||||
XMLName xml.Name `xml:"container"`
|
||||
ChildCount int `xml:"childCount,attr"`
|
||||
}
|
||||
|
||||
// Item description
|
||||
type Item struct {
|
||||
Object
|
||||
XMLName xml.Name `xml:"item"`
|
||||
Res []Resource
|
||||
XMLName xml.Name `xml:"item"`
|
||||
Res []Resource
|
||||
InnerXML string `xml:",innerxml"`
|
||||
}
|
||||
|
||||
// Object description
|
||||
type Object struct {
|
||||
ID string `xml:"id,attr"`
|
||||
ParentID string `xml:"parentID,attr"`
|
||||
Restricted int `xml:"restricted,attr"` // indicates whether the object is modifiable
|
||||
Class string `xml:"upnp:class"`
|
||||
Icon string `xml:"upnp:icon,omitempty"`
|
||||
Title string `xml:"dc:title"`
|
||||
Artist string `xml:"upnp:artist,omitempty"`
|
||||
Album string `xml:"upnp:album,omitempty"`
|
||||
Genre string `xml:"upnp:genre,omitempty"`
|
||||
AlbumArtURI string `xml:"upnp:albumArtURI,omitempty"`
|
||||
Searchable int `xml:"searchable,attr"`
|
||||
ID string `xml:"id,attr"`
|
||||
ParentID string `xml:"parentID,attr"`
|
||||
Restricted int `xml:"restricted,attr"` // indicates whether the object is modifiable
|
||||
Title string `xml:"dc:title"`
|
||||
Class string `xml:"upnp:class"`
|
||||
Icon string `xml:"upnp:icon,omitempty"`
|
||||
Date Timestamp `xml:"dc:date"`
|
||||
Artist string `xml:"upnp:artist,omitempty"`
|
||||
Album string `xml:"upnp:album,omitempty"`
|
||||
Genre string `xml:"upnp:genre,omitempty"`
|
||||
AlbumArtURI string `xml:"upnp:albumArtURI,omitempty"`
|
||||
Searchable int `xml:"searchable,attr"`
|
||||
SearchXML string `xml:",innerxml"`
|
||||
}
|
||||
|
||||
// Timestamp wraps time.Time for formatting purposes
|
||||
type Timestamp struct {
|
||||
time.Time
|
||||
}
|
||||
|
||||
// MarshalXML formats the Timestamp per DIDL-Lite spec
|
||||
func (t Timestamp) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
|
||||
return e.EncodeElement(t.Format("2006-01-02"), start)
|
||||
}
|
||||
|
|
|
|||
373
vendor/github.com/anacrolix/log/LICENSE
generated
vendored
Normal file
373
vendor/github.com/anacrolix/log/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,373 @@
|
|||
Mozilla Public License Version 2.0
|
||||
==================================
|
||||
|
||||
1. Definitions
|
||||
--------------
|
||||
|
||||
1.1. "Contributor"
|
||||
means each individual or legal entity that creates, contributes to
|
||||
the creation of, or owns Covered Software.
|
||||
|
||||
1.2. "Contributor Version"
|
||||
means the combination of the Contributions of others (if any) used
|
||||
by a Contributor and that particular Contributor's Contribution.
|
||||
|
||||
1.3. "Contribution"
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. "Covered Software"
|
||||
means Source Code Form to which the initial Contributor has attached
|
||||
the notice in Exhibit A, the Executable Form of such Source Code
|
||||
Form, and Modifications of such Source Code Form, in each case
|
||||
including portions thereof.
|
||||
|
||||
1.5. "Incompatible With Secondary Licenses"
|
||||
means
|
||||
|
||||
(a) that the initial Contributor has attached the notice described
|
||||
in Exhibit B to the Covered Software; or
|
||||
|
||||
(b) that the Covered Software was made available under the terms of
|
||||
version 1.1 or earlier of the License, but not also under the
|
||||
terms of a Secondary License.
|
||||
|
||||
1.6. "Executable Form"
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. "Larger Work"
|
||||
means a work that combines Covered Software with other material, in
|
||||
a separate file or files, that is not Covered Software.
|
||||
|
||||
1.8. "License"
|
||||
means this document.
|
||||
|
||||
1.9. "Licensable"
|
||||
means having the right to grant, to the maximum extent possible,
|
||||
whether at the time of the initial grant or subsequently, any and
|
||||
all of the rights conveyed by this License.
|
||||
|
||||
1.10. "Modifications"
|
||||
means any of the following:
|
||||
|
||||
(a) any file in Source Code Form that results from an addition to,
|
||||
deletion from, or modification of the contents of Covered
|
||||
Software; or
|
||||
|
||||
(b) any new file in Source Code Form that contains any Covered
|
||||
Software.
|
||||
|
||||
1.11. "Patent Claims" of a Contributor
|
||||
means any patent claim(s), including without limitation, method,
|
||||
process, and apparatus claims, in any patent Licensable by such
|
||||
Contributor that would be infringed, but for the grant of the
|
||||
License, by the making, using, selling, offering for sale, having
|
||||
made, import, or transfer of either its Contributions or its
|
||||
Contributor Version.
|
||||
|
||||
1.12. "Secondary License"
|
||||
means either the GNU General Public License, Version 2.0, the GNU
|
||||
Lesser General Public License, Version 2.1, the GNU Affero General
|
||||
Public License, Version 3.0, or any later versions of those
|
||||
licenses.
|
||||
|
||||
1.13. "Source Code Form"
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. "You" (or "Your")
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, "You" includes any entity that
|
||||
controls, is controlled by, or is under common control with You. For
|
||||
purposes of this definition, "control" means (a) the power, direct
|
||||
or indirect, to cause the direction or management of such entity,
|
||||
whether by contract or otherwise, or (b) ownership of more than
|
||||
fifty percent (50%) of the outstanding shares or beneficial
|
||||
ownership of such entity.
|
||||
|
||||
2. License Grants and Conditions
|
||||
--------------------------------
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
(a) under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or
|
||||
as part of a Larger Work; and
|
||||
|
||||
(b) under Patent Claims of such Contributor to make, use, sell, offer
|
||||
for sale, have made, import, and otherwise transfer either its
|
||||
Contributions or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution
|
||||
become effective for each Contribution on the date the Contributor first
|
||||
distributes such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under
|
||||
this License. No additional rights or licenses will be implied from the
|
||||
distribution or licensing of Covered Software under this License.
|
||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||
Contributor:
|
||||
|
||||
(a) for any code that a Contributor has removed from Covered Software;
|
||||
or
|
||||
|
||||
(b) for infringements caused by: (i) Your and any other third party's
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
(c) under Patent Claims infringed by Covered Software in the absence of
|
||||
its Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks,
|
||||
or logos of any Contributor (except as may be necessary to comply with
|
||||
the notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this
|
||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||
permitted under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its
|
||||
Contributions are its original creation(s) or it has sufficient rights
|
||||
to grant the rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under
|
||||
applicable copyright doctrines of fair use, fair dealing, or other
|
||||
equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
|
||||
in Section 2.1.
|
||||
|
||||
3. Responsibilities
|
||||
-------------------
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under
|
||||
the terms of this License. You must inform recipients that the Source
|
||||
Code Form of the Covered Software is governed by the terms of this
|
||||
License, and how they can obtain a copy of this License. You may not
|
||||
attempt to alter or restrict the recipients' rights in the Source Code
|
||||
Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
(a) such Covered Software must also be made available in Source Code
|
||||
Form, as described in Section 3.1, and You must inform recipients of
|
||||
the Executable Form how they can obtain a copy of such Source Code
|
||||
Form by reasonable means in a timely manner, at a charge no more
|
||||
than the cost of distribution to the recipient; and
|
||||
|
||||
(b) You may distribute such Executable Form under the terms of this
|
||||
License, or sublicense it under different terms, provided that the
|
||||
license for the Executable Form does not attempt to limit or alter
|
||||
the recipients' rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for
|
||||
the Covered Software. If the Larger Work is a combination of Covered
|
||||
Software with a work governed by one or more Secondary Licenses, and the
|
||||
Covered Software is not Incompatible With Secondary Licenses, this
|
||||
License permits You to additionally distribute such Covered Software
|
||||
under the terms of such Secondary License(s), so that the recipient of
|
||||
the Larger Work may, at their option, further distribute the Covered
|
||||
Software under the terms of either this License or such Secondary
|
||||
License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices
|
||||
(including copyright notices, patent notices, disclaimers of warranty,
|
||||
or limitations of liability) contained within the Source Code Form of
|
||||
the Covered Software, except that You may alter any license notices to
|
||||
the extent required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on
|
||||
behalf of any Contributor. You must make it absolutely clear that any
|
||||
such warranty, support, indemnity, or liability obligation is offered by
|
||||
You alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
---------------------------------------------------
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this
|
||||
License with respect to some or all of the Covered Software due to
|
||||
statute, judicial order, or regulation then You must: (a) comply with
|
||||
the terms of this License to the maximum extent possible; and (b)
|
||||
describe the limitations and the code they affect. Such description must
|
||||
be placed in a text file included with all distributions of the Covered
|
||||
Software under this License. Except to the extent prohibited by statute
|
||||
or regulation, such description must be sufficiently detailed for a
|
||||
recipient of ordinary skill to be able to understand it.
|
||||
|
||||
5. Termination
|
||||
--------------
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically
|
||||
if You fail to comply with any of its terms. However, if You become
|
||||
compliant, then the rights granted under this License from a particular
|
||||
Contributor are reinstated (a) provisionally, unless and until such
|
||||
Contributor explicitly and finally terminates Your grants, and (b) on an
|
||||
ongoing basis, if such Contributor fails to notify You of the
|
||||
non-compliance by some reasonable means prior to 60 days after You have
|
||||
come back into compliance. Moreover, Your grants from a particular
|
||||
Contributor are reinstated on an ongoing basis if such Contributor
|
||||
notifies You of the non-compliance by some reasonable means, this is the
|
||||
first time You have received notice of non-compliance with this License
|
||||
from such Contributor, and You become compliant prior to 30 days after
|
||||
Your receipt of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions,
|
||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||
directly or indirectly infringes any patent, then the rights granted to
|
||||
You by any and all Contributors for the Covered Software under Section
|
||||
2.1 of this License shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
||||
end user license agreements (excluding distributors and resellers) which
|
||||
have been validly granted by You or Your distributors under this License
|
||||
prior to termination shall survive termination.
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 6. Disclaimer of Warranty *
|
||||
* ------------------------- *
|
||||
* *
|
||||
* Covered Software is provided under this License on an "as is" *
|
||||
* basis, without warranty of any kind, either expressed, implied, or *
|
||||
* statutory, including, without limitation, warranties that the *
|
||||
* Covered Software is free of defects, merchantable, fit for a *
|
||||
* particular purpose or non-infringing. The entire risk as to the *
|
||||
* quality and performance of the Covered Software is with You. *
|
||||
* Should any Covered Software prove defective in any respect, You *
|
||||
* (not any Contributor) assume the cost of any necessary servicing, *
|
||||
* repair, or correction. This disclaimer of warranty constitutes an *
|
||||
* essential part of this License. No use of any Covered Software is *
|
||||
* authorized under this License except under this disclaimer. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 7. Limitation of Liability *
|
||||
* -------------------------- *
|
||||
* *
|
||||
* Under no circumstances and under no legal theory, whether tort *
|
||||
* (including negligence), contract, or otherwise, shall any *
|
||||
* Contributor, or anyone who distributes Covered Software as *
|
||||
* permitted above, be liable to You for any direct, indirect, *
|
||||
* special, incidental, or consequential damages of any character *
|
||||
* including, without limitation, damages for lost profits, loss of *
|
||||
* goodwill, work stoppage, computer failure or malfunction, or any *
|
||||
* and all other commercial damages or losses, even if such party *
|
||||
* shall have been informed of the possibility of such damages. This *
|
||||
* limitation of liability shall not apply to liability for death or *
|
||||
* personal injury resulting from such party's negligence to the *
|
||||
* extent applicable law prohibits such limitation. Some *
|
||||
* jurisdictions do not allow the exclusion or limitation of *
|
||||
* incidental or consequential damages, so this exclusion and *
|
||||
* limitation may not apply to You. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
8. Litigation
|
||||
-------------
|
||||
|
||||
Any litigation relating to this License may be brought only in the
|
||||
courts of a jurisdiction where the defendant maintains its principal
|
||||
place of business and such litigation shall be governed by laws of that
|
||||
jurisdiction, without reference to its conflict-of-law provisions.
|
||||
Nothing in this Section shall prevent a party's ability to bring
|
||||
cross-claims or counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
----------------
|
||||
|
||||
This License represents the complete agreement concerning the subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. Any law or regulation which provides
|
||||
that the language of a contract shall be construed against the drafter
|
||||
shall not be used to construe this License against a Contributor.
|
||||
|
||||
10. Versions of the License
|
||||
---------------------------
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version
|
||||
of the License under which You originally received the Covered Software,
|
||||
or under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a
|
||||
modified version of this License if you rename the license and remove
|
||||
any references to the name of the license steward (except to note that
|
||||
such modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||
Licenses
|
||||
|
||||
If You choose to distribute Source Code Form that is Incompatible With
|
||||
Secondary Licenses under the terms of this version of the License, the
|
||||
notice described in Exhibit B of this License must be attached.
|
||||
|
||||
Exhibit A - Source Code Form License Notice
|
||||
-------------------------------------------
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular
|
||||
file, then You may include the notice in a location (such as a LICENSE
|
||||
file in a relevant directory) where a recipient would be likely to look
|
||||
for such a notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
|
||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||
---------------------------------------------------------
|
||||
|
||||
This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
defined by the Mozilla Public License, v. 2.0.
|
||||
15
vendor/github.com/anacrolix/log/context.go
generated
vendored
Normal file
15
vendor/github.com/anacrolix/log/context.go
generated
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
package log
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
var loggerContextKey interface{} = (*Logger)(nil)
|
||||
|
||||
func ContextWithLogger(ctx context.Context, logger Logger) context.Context {
|
||||
return context.WithValue(ctx, loggerContextKey, logger)
|
||||
}
|
||||
|
||||
func ContextLogger(ctx context.Context) Logger {
|
||||
return ctx.Value(loggerContextKey).(Logger)
|
||||
}
|
||||
8
vendor/github.com/anacrolix/log/doc.go
generated
vendored
Normal file
8
vendor/github.com/anacrolix/log/doc.go
generated
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
// Package log implements a std log compatible logging system that draws some inspiration from the
|
||||
// Python standard library [logging module](https://docs.python.org/3/library/logging.html). It
|
||||
// supports multiple handlers, log levels, zero-allocation, scopes, custom formatting, and
|
||||
// environment and runtime configuration.
|
||||
//
|
||||
// When not used to replace std log, the import should use the package name "analog" as in:
|
||||
// import analog "github.com/anacrolix/log".
|
||||
package log
|
||||
41
vendor/github.com/anacrolix/log/global.go
generated
vendored
Normal file
41
vendor/github.com/anacrolix/log/global.go
generated
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
)
|
||||
|
||||
var (
|
||||
DefaultHandler = StreamHandler{
|
||||
W: os.Stderr,
|
||||
Fmt: LineFormatter,
|
||||
}
|
||||
Default Logger // Inited after GO_LOG is parsed.
|
||||
DiscardHandler = StreamHandler{
|
||||
W: ioutil.Discard,
|
||||
Fmt: func(Record) []byte { return nil },
|
||||
}
|
||||
)
|
||||
|
||||
func Levelf(level Level, format string, a ...interface{}) {
|
||||
Default.LazyLog(level, func() Msg {
|
||||
return Fmsg(format, a...).Skip(1)
|
||||
})
|
||||
}
|
||||
|
||||
func Printf(format string, a ...interface{}) {
|
||||
Default.Log(Fmsg(format, a...).Skip(1))
|
||||
}
|
||||
|
||||
// Prints the arguments to the Default Logger.
|
||||
func Print(a ...interface{}) {
|
||||
// TODO: There's no "Print" equivalent constructor for a Msg, and I don't know what I'd call it.
|
||||
Str(fmt.Sprint(a...)).Skip(1).Log(Default)
|
||||
}
|
||||
|
||||
func Println(a ...interface{}) {
|
||||
Default.LazyLogDefaultLevel(func() Msg {
|
||||
return Str(fmt.Sprintln(a...)).Skip(1)
|
||||
})
|
||||
}
|
||||
11
vendor/github.com/anacrolix/log/handler.go
generated
vendored
Normal file
11
vendor/github.com/anacrolix/log/handler.go
generated
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
package log
|
||||
|
||||
type Handler interface {
|
||||
Handle(Record)
|
||||
}
|
||||
|
||||
type Record struct {
|
||||
Msg
|
||||
Level Level
|
||||
Names []string
|
||||
}
|
||||
22
vendor/github.com/anacrolix/log/init.go
generated
vendored
Normal file
22
vendor/github.com/anacrolix/log/init.go
generated
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
package log
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
rules, err = parseEnvRules()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
Default = loggerCore{
|
||||
nonZero: true,
|
||||
filterLevel: Error,
|
||||
Handlers: []Handler{DefaultHandler},
|
||||
}.withFilterLevelFromRules()
|
||||
Default.defaultLevel, _, err = levelFromString(os.Getenv("GO_LOG_DEFAULT_LEVEL"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
75
vendor/github.com/anacrolix/log/level.go
generated
vendored
Normal file
75
vendor/github.com/anacrolix/log/level.go
generated
vendored
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
package log
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Level struct {
|
||||
rank int
|
||||
}
|
||||
|
||||
var (
|
||||
Never = Level{-1} // A message at this level should never be logged.
|
||||
NotSet = Level{0}
|
||||
Debug = Level{1}
|
||||
Info = Level{2}
|
||||
Warning = Level{3}
|
||||
Error = Level{4}
|
||||
Critical = Level{5}
|
||||
disabled = Level{6} // It shouldn't be possible to define a message at this level.
|
||||
)
|
||||
|
||||
func (l Level) isNotSet() bool {
|
||||
return l.rank == 0
|
||||
}
|
||||
|
||||
func (l Level) LogString() string {
|
||||
switch l.rank {
|
||||
case NotSet.rank:
|
||||
return "NIL"
|
||||
case Debug.rank:
|
||||
return "DBG"
|
||||
case Info.rank:
|
||||
return "INF"
|
||||
case Warning.rank:
|
||||
return "WRN"
|
||||
case Error.rank:
|
||||
return "ERR"
|
||||
case Critical.rank:
|
||||
return "CRT"
|
||||
default:
|
||||
return strconv.FormatInt(int64(l.rank), 10)
|
||||
}
|
||||
}
|
||||
|
||||
func (l Level) LessThan(r Level) bool {
|
||||
if l.rank == NotSet.rank {
|
||||
return false
|
||||
}
|
||||
return l.rank < r.rank
|
||||
}
|
||||
|
||||
var _ encoding.TextUnmarshaler = (*Level)(nil)
|
||||
|
||||
func (l *Level) UnmarshalText(text []byte) error {
|
||||
switch strings.ToLower(string(text)) {
|
||||
case "nil", "notset", "unset", "all", "*":
|
||||
*l = NotSet
|
||||
case "dbg", "debug":
|
||||
*l = Debug
|
||||
case "inf", "info":
|
||||
*l = Info
|
||||
case "wrn", "warning", "warn":
|
||||
*l = Warning
|
||||
case "err", "error":
|
||||
*l = Error
|
||||
case "crt", "critical", "crit":
|
||||
*l = Critical
|
||||
default:
|
||||
return fmt.Errorf("unknown log level: %q", text)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
13
vendor/github.com/anacrolix/log/log.go
generated
vendored
Normal file
13
vendor/github.com/anacrolix/log/log.go
generated
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
package log
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
)
|
||||
|
||||
func Call() Msg {
|
||||
var pc [1]uintptr
|
||||
n := runtime.Callers(4, pc[:])
|
||||
fs := runtime.CallersFrames(pc[:n])
|
||||
f, _ := fs.Next()
|
||||
return Fmsg("called %q", f.Function)
|
||||
}
|
||||
102
vendor/github.com/anacrolix/log/logger-core.go
generated
vendored
Normal file
102
vendor/github.com/anacrolix/log/logger-core.go
generated
vendored
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// loggerCore is the essential part of Logger.
|
||||
type loggerCore struct {
|
||||
nonZero bool
|
||||
names []string
|
||||
values []interface{}
|
||||
defaultLevel Level
|
||||
filterLevel Level
|
||||
msgMaps []func(Msg) Msg
|
||||
Handlers []Handler
|
||||
}
|
||||
|
||||
func (l loggerCore) asLogger() Logger {
|
||||
return Logger{l}
|
||||
}
|
||||
|
||||
// Returns a logger that adds the given values to logged messages.
|
||||
func (l loggerCore) WithValues(v ...interface{}) Logger {
|
||||
l.values = append(l.values, v...)
|
||||
return l.asLogger()
|
||||
}
|
||||
|
||||
// Returns a logger that for a given message propagates the result of `f` instead.
|
||||
func (l loggerCore) WithMap(f func(m Msg) Msg) Logger {
|
||||
l.msgMaps = append(l.msgMaps, f)
|
||||
return l.asLogger()
|
||||
}
|
||||
|
||||
func (l loggerCore) WithDefaultLevel(level Level) Logger {
|
||||
l.defaultLevel = level
|
||||
return l.asLogger()
|
||||
}
|
||||
|
||||
func (l loggerCore) FilterLevel(minLevel Level) Logger {
|
||||
if _, ok := levelFromRules(l.names); !ok {
|
||||
l.filterLevel = minLevel
|
||||
}
|
||||
return l.asLogger()
|
||||
}
|
||||
|
||||
func (l loggerCore) IsZero() bool {
|
||||
return !l.nonZero
|
||||
}
|
||||
|
||||
func (l loggerCore) IsEnabledFor(level Level) bool {
|
||||
return !level.LessThan(l.filterLevel)
|
||||
}
|
||||
|
||||
func (l loggerCore) LazyLog(level Level, f func() Msg) {
|
||||
l.lazyLog(level, 1, f)
|
||||
}
|
||||
|
||||
func (l loggerCore) LazyLogDefaultLevel(f func() Msg) {
|
||||
l.lazyLog(l.defaultLevel, 1, f)
|
||||
}
|
||||
|
||||
func (l loggerCore) lazyLog(level Level, skip int, f func() Msg) {
|
||||
if !l.IsEnabledFor(level) {
|
||||
// have a big sook
|
||||
//internalLogger.Levelf(Debug, "skipped logging %v for %q", level, l.names)
|
||||
return
|
||||
}
|
||||
r := f().Skip(skip + 1)
|
||||
for i := len(l.msgMaps) - 1; i >= 0; i-- {
|
||||
r = l.msgMaps[i](r)
|
||||
}
|
||||
l.handle(level, r)
|
||||
}
|
||||
|
||||
func (l loggerCore) handle(level Level, m Msg) {
|
||||
r := Record{
|
||||
Msg: m.Skip(1),
|
||||
Level: level,
|
||||
Names: l.names,
|
||||
}
|
||||
if !l.nonZero {
|
||||
panic(fmt.Sprintf("Logger uninitialized. names=%q", l.names))
|
||||
}
|
||||
for _, h := range l.Handlers {
|
||||
h.Handle(r)
|
||||
}
|
||||
}
|
||||
|
||||
func (l loggerCore) WithNames(names ...string) Logger {
|
||||
// Avoid sharing after appending. This might not be enough because some formatters might add
|
||||
// more elements concurrently, or names could be empty.
|
||||
l.names = append(l.names[:len(l.names):len(l.names)], names...)
|
||||
return l.withFilterLevelFromRules()
|
||||
}
|
||||
|
||||
func (l loggerCore) withFilterLevelFromRules() Logger {
|
||||
level, ok := levelFromRules(l.names)
|
||||
if ok {
|
||||
l.filterLevel = level
|
||||
}
|
||||
return l.asLogger()
|
||||
}
|
||||
72
vendor/github.com/anacrolix/log/logger.go
generated
vendored
Normal file
72
vendor/github.com/anacrolix/log/logger.go
generated
vendored
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Logger handles logging in a specific context. It includes a bunch of helpers and compatibility
|
||||
// over the loggerCore.
|
||||
type Logger struct {
|
||||
loggerCore
|
||||
}
|
||||
|
||||
func (l Logger) WithText(f func(Msg) string) Logger {
|
||||
l.msgMaps = append(l.msgMaps, func(msg Msg) Msg {
|
||||
return msg.WithText(f)
|
||||
})
|
||||
return l
|
||||
}
|
||||
|
||||
// Helper for compatibility with "log".Logger.
|
||||
func (l Logger) Printf(format string, a ...interface{}) {
|
||||
l.LazyLog(l.defaultLevel, func() Msg {
|
||||
return Fmsg(format, a...).Skip(1)
|
||||
})
|
||||
}
|
||||
|
||||
func (l Logger) Log(m Msg) {
|
||||
l.LogLevel(l.defaultLevel, m.Skip(1))
|
||||
}
|
||||
|
||||
func (l Logger) LogLevel(level Level, m Msg) {
|
||||
l.LazyLog(level, func() Msg {
|
||||
return m.Skip(1)
|
||||
})
|
||||
}
|
||||
|
||||
// Helper for compatibility with "log".Logger.
|
||||
func (l Logger) Print(v ...interface{}) {
|
||||
l.LazyLog(l.defaultLevel, func() Msg {
|
||||
return Str(fmt.Sprint(v...)).Skip(1)
|
||||
})
|
||||
}
|
||||
|
||||
func (l Logger) WithContextValue(v interface{}) Logger {
|
||||
return l.WithText(func(m Msg) string {
|
||||
return fmt.Sprintf("%v: %v", v, m)
|
||||
})
|
||||
}
|
||||
|
||||
func (l Logger) WithContextText(s string) Logger {
|
||||
return l.WithText(func(m Msg) string {
|
||||
return s + ": " + m.Text()
|
||||
})
|
||||
}
|
||||
|
||||
func (l Logger) SkipCallers(skip int) Logger {
|
||||
return l.WithMap(func(m Msg) Msg {
|
||||
return m.Skip(skip)
|
||||
})
|
||||
}
|
||||
|
||||
func (l Logger) Levelf(level Level, format string, a ...interface{}) {
|
||||
l.LazyLog(level, func() Msg {
|
||||
return Fmsg(format, a...).Skip(1)
|
||||
})
|
||||
}
|
||||
|
||||
func (l Logger) Println(a ...interface{}) {
|
||||
l.LazyLogDefaultLevel(func() Msg {
|
||||
return Str(fmt.Sprintln(a...)).Skip(1)
|
||||
})
|
||||
}
|
||||
153
vendor/github.com/anacrolix/log/msg.go
generated
vendored
Normal file
153
vendor/github.com/anacrolix/log/msg.go
generated
vendored
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type Msg struct {
|
||||
MsgImpl
|
||||
}
|
||||
|
||||
func (me Msg) String() string {
|
||||
return me.Text()
|
||||
}
|
||||
|
||||
func newMsg(text func() string) Msg {
|
||||
return Msg{rootMsgImpl{text}}
|
||||
}
|
||||
|
||||
func Fmsg(format string, a ...interface{}) Msg {
|
||||
return newMsg(func() string { return fmt.Sprintf(format, a...) })
|
||||
}
|
||||
|
||||
var Fstr = Fmsg
|
||||
|
||||
func Str(s string) (m Msg) {
|
||||
return newMsg(func() string { return s })
|
||||
}
|
||||
|
||||
type msgSkipCaller struct {
|
||||
MsgImpl
|
||||
skip int
|
||||
}
|
||||
|
||||
func (me msgSkipCaller) Callers(skip int, pc []uintptr) int {
|
||||
return me.MsgImpl.Callers(skip+1+me.skip, pc)
|
||||
}
|
||||
|
||||
func (m Msg) Skip(skip int) Msg {
|
||||
return Msg{msgSkipCaller{m.MsgImpl, skip}}
|
||||
}
|
||||
|
||||
type item struct {
|
||||
key, value interface{}
|
||||
}
|
||||
|
||||
// rename sink
|
||||
func (m Msg) Log(l Logger) Msg {
|
||||
l.Log(m.Skip(1))
|
||||
return m
|
||||
}
|
||||
|
||||
func (m Msg) LogLevel(level Level, l Logger) Msg {
|
||||
l.LogLevel(level, m.Skip(1))
|
||||
return m
|
||||
}
|
||||
|
||||
type msgWithValues struct {
|
||||
MsgImpl
|
||||
values []interface{}
|
||||
}
|
||||
|
||||
func (me msgWithValues) Values(cb valueIterCallback) {
|
||||
for _, v := range me.values {
|
||||
if !cb(v) {
|
||||
return
|
||||
}
|
||||
}
|
||||
me.MsgImpl.Values(cb)
|
||||
}
|
||||
|
||||
// TODO: What ordering should be applied to the values here, per MsgImpl.Values. For now they're
|
||||
// traversed in order of the slice.
|
||||
func (m Msg) WithValues(v ...interface{}) Msg {
|
||||
return Msg{msgWithValues{m.MsgImpl, v}}
|
||||
}
|
||||
|
||||
func (m Msg) AddValues(v ...interface{}) Msg {
|
||||
return m.WithValues(v...)
|
||||
}
|
||||
|
||||
func (m Msg) With(key, value interface{}) Msg {
|
||||
return m.WithValues(item{key, value})
|
||||
}
|
||||
|
||||
func (m Msg) Add(key, value interface{}) Msg {
|
||||
return m.With(key, value)
|
||||
}
|
||||
|
||||
//func (m Msg) SetLevel(level Level) Msg {
|
||||
// return m.With(levelKey, level)
|
||||
//}
|
||||
|
||||
//func (m Msg) GetByKey(key interface{}) (value interface{}, ok bool) {
|
||||
// m.Values(func(i interface{}) bool {
|
||||
// if keyValue, isKeyValue := i.(item); isKeyValue && keyValue.key == key {
|
||||
// value = keyValue.value
|
||||
// ok = true
|
||||
// }
|
||||
// return !ok
|
||||
// })
|
||||
// return
|
||||
//}
|
||||
|
||||
//func (m Msg) GetLevel() (l Level, ok bool) {
|
||||
// v, ok := m.GetByKey(levelKey)
|
||||
// if ok {
|
||||
// l = v.(Level)
|
||||
// }
|
||||
// return
|
||||
//}
|
||||
|
||||
func (m Msg) HasValue(v interface{}) (has bool) {
|
||||
m.Values(func(i interface{}) bool {
|
||||
if i == v {
|
||||
has = true
|
||||
}
|
||||
return !has
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (m Msg) AddValue(v interface{}) Msg {
|
||||
return m.AddValues(v)
|
||||
}
|
||||
|
||||
//func (m Msg) GetValueByType(p interface{}) bool {
|
||||
// pve := reflect.ValueOf(p).Elem()
|
||||
// t := pve.Type()
|
||||
// return !iter.All(func(i interface{}) bool {
|
||||
// iv := reflect.ValueOf(i)
|
||||
// if iv.Type() == t {
|
||||
// pve.Set(iv)
|
||||
// return false
|
||||
// }
|
||||
// return true
|
||||
// }, m.Values)
|
||||
//}
|
||||
|
||||
func (m Msg) WithText(f func(Msg) string) Msg {
|
||||
return Msg{msgWithText{
|
||||
m,
|
||||
func() string { return f(m) },
|
||||
}}
|
||||
}
|
||||
|
||||
type msgWithText struct {
|
||||
MsgImpl
|
||||
text func() string
|
||||
}
|
||||
|
||||
func (me msgWithText) Text() string {
|
||||
return me.text()
|
||||
}
|
||||
33
vendor/github.com/anacrolix/log/msgimpl.go
generated
vendored
Normal file
33
vendor/github.com/anacrolix/log/msgimpl.go
generated
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
package log
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
)
|
||||
|
||||
type valueIterCallback func(value interface{}) (more bool)
|
||||
|
||||
// The minimal interface required for the Msg helper/wrapper to operate on.
|
||||
type MsgImpl interface {
|
||||
// Returns the message text. Allows for lazy evaluation/prefixing etc.
|
||||
Text() string
|
||||
// Sets the program counters in pc. Having it in the interface may allow us to cache/freeze them
|
||||
// for serialization etc.
|
||||
Callers(skip int, pc []uintptr) int
|
||||
// Iterates over the values as added LIFO.
|
||||
Values(callback valueIterCallback)
|
||||
}
|
||||
|
||||
// maybe implement finalizer to ensure msgs are sunk
|
||||
type rootMsgImpl struct {
|
||||
text func() string
|
||||
}
|
||||
|
||||
func (m rootMsgImpl) Text() string {
|
||||
return m.text()
|
||||
}
|
||||
|
||||
func (m rootMsgImpl) Callers(skip int, pc []uintptr) int {
|
||||
return runtime.Callers(skip+2, pc)
|
||||
}
|
||||
|
||||
func (m rootMsgImpl) Values(valueIterCallback) {}
|
||||
100
vendor/github.com/anacrolix/log/rules.go
generated
vendored
Normal file
100
vendor/github.com/anacrolix/log/rules.go
generated
vendored
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var rules []Rule
|
||||
|
||||
type Rule func(names []string) (level Level, matched bool)
|
||||
|
||||
func alwaysLevel(level Level) Rule {
|
||||
return func(names []string) (Level, bool) {
|
||||
return level, true
|
||||
}
|
||||
}
|
||||
|
||||
func stringSliceContains(s string, ss []string) bool {
|
||||
for _, sss := range ss {
|
||||
if s == sss {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func containsAllNames(all []string, level Level) Rule {
|
||||
return func(names []string) (_ Level, matched bool) {
|
||||
for _, s := range all {
|
||||
//log.Println(s, all, names)
|
||||
if !stringSliceContains(s, names) {
|
||||
return
|
||||
}
|
||||
}
|
||||
return level, true
|
||||
}
|
||||
}
|
||||
|
||||
func parseRuleString(s string) (_ Rule, ok bool, _ error) {
|
||||
if s == "" {
|
||||
return
|
||||
}
|
||||
ss := strings.SplitN(s, "=", 2)
|
||||
level := NotSet
|
||||
var names []string
|
||||
if ss[0] != "*" {
|
||||
names = []string{ss[0]}
|
||||
}
|
||||
if len(ss) > 1 {
|
||||
var ok bool
|
||||
var err error
|
||||
level, ok, err = levelFromString(ss[1])
|
||||
if !ok {
|
||||
// blah= means disable the name, but just blah means to always include it
|
||||
level = disabled
|
||||
}
|
||||
if err != nil {
|
||||
return nil, false, fmt.Errorf("parsing level %q: %w", ss[1], err)
|
||||
}
|
||||
}
|
||||
return containsAllNames(names, level), true, nil
|
||||
}
|
||||
|
||||
func parseEnvRules() (rules []Rule, err error) {
|
||||
rulesStr := os.Getenv("GO_LOG")
|
||||
ruleStrs := strings.Split(rulesStr, ",")
|
||||
for _, ruleStr := range ruleStrs {
|
||||
rule, ok, err := parseRuleString(ruleStr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing rule %q: %w", ruleStr, err)
|
||||
}
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
rules = append(rules, rule)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func levelFromString(s string) (level Level, ok bool, err error) {
|
||||
if s == "" {
|
||||
return
|
||||
}
|
||||
ok = true
|
||||
err = level.UnmarshalText([]byte(s))
|
||||
return
|
||||
}
|
||||
|
||||
func levelFromRules(names []string) (_ Level, ok bool) {
|
||||
// Later rules take precedence
|
||||
for i := len(rules) - 1; i >= 0; i-- {
|
||||
r := rules[i]
|
||||
level, ok := r(names)
|
||||
if ok {
|
||||
return level, true
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
12
vendor/github.com/anacrolix/log/stdlog.go
generated
vendored
Normal file
12
vendor/github.com/anacrolix/log/stdlog.go
generated
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
package log
|
||||
|
||||
import (
|
||||
"log"
|
||||
)
|
||||
|
||||
// Deprecated: Logging shouldn't include control flow.
|
||||
var (
|
||||
Panicf = log.Panicf
|
||||
Fatalf = log.Fatalf
|
||||
Fatal = log.Fatal
|
||||
)
|
||||
59
vendor/github.com/anacrolix/log/stream-handler.go
generated
vendored
Normal file
59
vendor/github.com/anacrolix/log/stream-handler.go
generated
vendored
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"runtime"
|
||||
"time"
|
||||
)
|
||||
|
||||
type StreamHandler struct {
|
||||
W io.Writer
|
||||
Fmt ByteFormatter
|
||||
}
|
||||
|
||||
func (me StreamHandler) Handle(r Record) {
|
||||
r.Msg = r.Skip(1)
|
||||
me.W.Write(me.Fmt(r))
|
||||
}
|
||||
|
||||
type ByteFormatter func(Record) []byte
|
||||
|
||||
func LineFormatter(msg Record) []byte {
|
||||
names := msg.Names
|
||||
if true || len(names) == 0 {
|
||||
var pc [1]uintptr
|
||||
msg.Callers(1, pc[:])
|
||||
names = pcNames(pc[0], names)
|
||||
}
|
||||
ret := []byte(fmt.Sprintf(
|
||||
"%s %s %s: %s",
|
||||
time.Now().Format("2006-01-02T15:04:05-0700"),
|
||||
msg.Level.LogString(),
|
||||
names,
|
||||
msg.Text(),
|
||||
))
|
||||
if ret[len(ret)-1] != '\n' {
|
||||
ret = append(ret, '\n')
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func pcNames(pc uintptr, names []string) []string {
|
||||
if pc == 0 {
|
||||
panic(pc)
|
||||
}
|
||||
funcName, file, line := func() (string, string, int) {
|
||||
if false {
|
||||
// This seems to result in one less allocation, but doesn't handle inlining?
|
||||
func_ := runtime.FuncForPC(pc)
|
||||
file, line := func_.FileLine(pc)
|
||||
return func_.Name(), file, line
|
||||
} else {
|
||||
f, _ := runtime.CallersFrames([]uintptr{pc}).Next()
|
||||
return f.Function, f.File, f.Line
|
||||
}
|
||||
}()
|
||||
_ = file
|
||||
return append(names, fmt.Sprintf("%s:%v", funcName, line))
|
||||
}
|
||||
15
vendor/github.com/antchfx/xpath/README.md
generated
vendored
15
vendor/github.com/antchfx/xpath/README.md
generated
vendored
|
|
@ -57,6 +57,7 @@ Supported Features
|
|||
|
||||
- `(a, b, c)` : Evaluates each of its operands and concatenates the resulting sequences, in order, into a single result sequence
|
||||
|
||||
- `(a/b)` : Selects all matches nodes as grouping set.
|
||||
|
||||
#### Node Axes
|
||||
|
||||
|
|
@ -158,16 +159,4 @@ Supported Features
|
|||
`system-property()`| ✗ |
|
||||
`translate()`| ✓ |
|
||||
`true()`| ✓ |
|
||||
`unparsed-entity-url()` | ✗ |
|
||||
|
||||
Changelogs
|
||||
===
|
||||
|
||||
2019-03-19
|
||||
- optimize XPath `|` operation performance. [#33](https://github.com/antchfx/xpath/issues/33). Tips: suggest split into multiple subquery if you have a lot of `|` operations.
|
||||
|
||||
2019-01-29
|
||||
- improvement `normalize-space` function. [#32](https://github.com/antchfx/xpath/issues/32)
|
||||
|
||||
2018-12-07
|
||||
- supports XPath 2.0 Sequence expressions. [#30](https://github.com/antchfx/xpath/pull/30) by [@minherz](https://github.com/minherz).
|
||||
`unparsed-entity-url()` | ✗ |
|
||||
2
vendor/github.com/antchfx/xpath/build.go
generated
vendored
2
vendor/github.com/antchfx/xpath/build.go
generated
vendored
|
|
@ -42,7 +42,7 @@ func axisPredicate(root *axisNode) func(NodeNavigator) bool {
|
|||
}
|
||||
nametest := root.LocalName != "" || root.Prefix != ""
|
||||
predicate := func(n NodeNavigator) bool {
|
||||
if typ == n.NodeType() || typ == allNode || typ == TextNode {
|
||||
if typ == n.NodeType() || typ == allNode {
|
||||
if nametest {
|
||||
if root.LocalName == n.LocalName() && root.Prefix == n.Prefix() {
|
||||
return true
|
||||
|
|
|
|||
10
vendor/github.com/antchfx/xpath/func.go
generated
vendored
10
vendor/github.com/antchfx/xpath/func.go
generated
vendored
|
|
@ -122,17 +122,19 @@ func asNumber(t iterator, o interface{}) float64 {
|
|||
return typ
|
||||
case string:
|
||||
v, err := strconv.ParseFloat(typ, 64)
|
||||
if err != nil {
|
||||
panic(errors.New("ceiling() function argument type must be a node-set or number"))
|
||||
if err == nil {
|
||||
return v
|
||||
}
|
||||
return v
|
||||
}
|
||||
return 0
|
||||
return math.NaN()
|
||||
}
|
||||
|
||||
// ceilingFunc is a XPath Node Set functions ceiling(node-set).
|
||||
func ceilingFunc(q query, t iterator) interface{} {
|
||||
val := asNumber(t, functionArgs(q).Evaluate(t))
|
||||
// if math.IsNaN(val) {
|
||||
// panic(errors.New("ceiling() function argument type must be a valid number"))
|
||||
// }
|
||||
return math.Ceil(val)
|
||||
}
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue