mirror of
https://github.com/stashapp/stash.git
synced 2025-12-06 08:26:00 +01:00
Removed vendoring
This commit is contained in:
parent
6a75d5551f
commit
e13dae6012
1399 changed files with 54 additions and 654646 deletions
|
|
@ -16,7 +16,7 @@ before_install:
|
|||
script:
|
||||
#- make lint
|
||||
#- make vet
|
||||
- go test -mod=vendor
|
||||
- go test
|
||||
before_deploy:
|
||||
- docker pull stashappdev/compiler
|
||||
- sh ./scripts/cross-compile.sh
|
||||
|
|
|
|||
8
Makefile
8
Makefile
|
|
@ -6,7 +6,7 @@ endif
|
|||
build:
|
||||
$(eval DATE := $(shell go run scripts/getDate.go))
|
||||
$(eval GITHASH := $(shell git rev-parse --short HEAD))
|
||||
$(SET) CGO_ENABLED=1 $(SEPARATOR) go build -mod=vendor -v -ldflags "-X 'github.com/stashapp/stash/pkg/api.buildstamp=$(DATE)' -X 'github.com/stashapp/stash/pkg/api.githash=$(GITHASH)'"
|
||||
$(SET) CGO_ENABLED=1 $(SEPARATOR) go build -v -ldflags "-X 'github.com/stashapp/stash/pkg/api.buildstamp=$(DATE)' -X 'github.com/stashapp/stash/pkg/api.githash=$(GITHASH)'"
|
||||
|
||||
install:
|
||||
packr2 install
|
||||
|
|
@ -17,7 +17,7 @@ clean:
|
|||
# Regenerates GraphQL files
|
||||
.PHONY: generate
|
||||
generate:
|
||||
go generate -mod=vendor
|
||||
go generate
|
||||
cd ui/v2 && yarn run gqlgen
|
||||
|
||||
# Runs gofmt -w on the project's source code, modifying any files that do not match its style.
|
||||
|
|
@ -28,11 +28,11 @@ fmt:
|
|||
# Runs go vet on the project's source code.
|
||||
.PHONY: vet
|
||||
vet:
|
||||
go vet -mod=vendor ./...
|
||||
go vet ./...
|
||||
|
||||
.PHONY: lint
|
||||
lint:
|
||||
revive -config revive.toml -exclude ./vendor/... ./...
|
||||
revive -config revive.toml -exclude ./...
|
||||
|
||||
.PHONY: ui
|
||||
ui:
|
||||
|
|
|
|||
22
go.mod
22
go.mod
|
|
@ -1,26 +1,26 @@
|
|||
module github.com/stashapp/stash
|
||||
|
||||
require (
|
||||
github.com/99designs/gqlgen v0.9.0
|
||||
github.com/99designs/gqlgen v0.10.1
|
||||
github.com/PuerkitoBio/goquery v1.5.0
|
||||
github.com/bmatcuk/doublestar v1.1.5
|
||||
github.com/disintegration/imaging v1.6.0
|
||||
github.com/disintegration/imaging v1.6.1
|
||||
github.com/go-chi/chi v4.0.2+incompatible
|
||||
github.com/gobuffalo/packr/v2 v2.0.2
|
||||
github.com/golang-migrate/migrate/v4 v4.3.1
|
||||
github.com/gorilla/websocket v1.4.0
|
||||
github.com/h2non/filetype v1.0.8
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/golang-migrate/migrate/v4 v4.7.0
|
||||
github.com/gorilla/websocket v1.4.1
|
||||
github.com/h2non/filetype v1.0.10
|
||||
github.com/jmoiron/sqlx v1.2.0
|
||||
github.com/mattn/go-sqlite3 v1.10.0
|
||||
github.com/microcosm-cc/bluemonday v1.0.2 // indirect
|
||||
github.com/rs/cors v1.6.0
|
||||
github.com/rs/cors v1.7.0
|
||||
github.com/sirupsen/logrus v1.4.2
|
||||
github.com/spf13/pflag v1.0.3
|
||||
github.com/spf13/viper v1.4.0
|
||||
github.com/vektah/gqlparser v1.1.2
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/spf13/viper v1.5.0
|
||||
github.com/vektah/gqlparser v1.2.0
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
|
||||
golang.org/x/image v0.0.0-20190118043309-183bebdce1b2 // indirect
|
||||
)
|
||||
|
||||
replace git.apache.org/thrift.git => github.com/apache/thrift v0.0.0-20180902110319-2566ecd5d999
|
||||
|
||||
go 1.13
|
||||
|
|
|
|||
91
go.sum
91
go.sum
|
|
@ -1,20 +1,14 @@
|
|||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.28.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.36.0/go.mod h1:RUoy9p/M4ge0HzT8L+SDZ8jg+Q6fth0CiBuhFJpSV40=
|
||||
cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw=
|
||||
contrib.go.opencensus.io/exporter/stackdriver v0.6.0/go.mod h1:QeFzMJDAw8TXt5+aRaSuE8l5BwaMIOIlaVkBOPRuMuw=
|
||||
dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU=
|
||||
dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU=
|
||||
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
|
||||
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
|
||||
github.com/99designs/gqlgen v0.4.5-0.20190127090136-055fb4bc9a6a h1:oTsAt8YXjEk1fo7uZR7gya1jrH48oPulx5oF6zWTHRw=
|
||||
github.com/99designs/gqlgen v0.4.5-0.20190127090136-055fb4bc9a6a/go.mod h1:st7qHA6ssU3uRZkmv+wzrzgX4srvIqEIdE5iuRW8GhE=
|
||||
github.com/99designs/gqlgen v0.8.2 h1:xOkDPWn/MZjkQ32pu6Axx15mNah0NAq9WalFqT+RavA=
|
||||
github.com/99designs/gqlgen v0.8.2/go.mod h1:aLyJw9xUgdJxZ8EqNQxo2pGFhXXJ/hq8t7J4yn8TgI4=
|
||||
github.com/99designs/gqlgen v0.9.0 h1:g1arBPML74Vqv0L3Q+TqIhGXLspV+2MYtRLkBxuZrlE=
|
||||
github.com/99designs/gqlgen v0.9.0/go.mod h1:HrrG7ic9EgLPsULxsZh/Ti+p0HNWgR3XRuvnD0pb5KY=
|
||||
github.com/99designs/gqlgen v0.10.1 h1:1BgB6XKGTHq7uH4G1/PYyKe2Kz7/vw3AlvMZlD3TEEY=
|
||||
github.com/99designs/gqlgen v0.10.1/go.mod h1:IviubpnyI4gbBcj8IcxSSc/Q/+af5riwCmJmwF0uaPE=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
|
|
@ -39,13 +33,10 @@ github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYU
|
|||
github.com/apache/thrift v0.0.0-20180902110319-2566ecd5d999/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/aws/aws-sdk-go v1.15.54/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
|
||||
github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k=
|
||||
github.com/bmatcuk/doublestar v1.1.1 h1:YroD6BJCZBYx06yYFEWvUuKVWQn3vLLQAVmDmvTSaiQ=
|
||||
github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
|
||||
github.com/bmatcuk/doublestar v1.1.5 h1:2bNwBOmhyFEFcoB3tGvTD5xanq+4kyOZlB8wFYbMjkk=
|
||||
github.com/bmatcuk/doublestar v1.1.5/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE=
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
||||
|
|
@ -55,6 +46,7 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
|
|||
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
|
||||
github.com/cockroachdb/cockroach-go v0.0.0-20181001143604-e0a95dfd547c/go.mod h1:XGLbWH/ujMcbPbhZq52Nv6UrCghb1yGn//133kEsvDk=
|
||||
github.com/codegangsta/negroni v1.0.0/go.mod h1:v0y3T5G7Y1UlFfyxFn/QLRU4a2EuNau2iZY63YTKWo0=
|
||||
github.com/containerd/containerd v1.2.7/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||
|
|
@ -75,14 +67,15 @@ github.com/cznic/zappy v0.0.0-20160723133515-2533cb5b45cc/go.mod h1:Y1SNZ4dRUOKX
|
|||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/dhui/dktest v0.3.0/go.mod h1:cyzIUfGsBEbZ6BT7tnXqAShHSXCZhSNmFl70sZ7c1yc=
|
||||
github.com/disintegration/imaging v1.6.0 h1:nVPXRUUQ36Z7MNf0O77UzgnOb1mkMMor7lmJMJXc/mA=
|
||||
github.com/disintegration/imaging v1.6.0/go.mod h1:xuIt+sRxDFrHS0drzXUlCJthkJ8k7lkkUojDSR247MQ=
|
||||
github.com/disintegration/imaging v1.6.1 h1:JnBbK6ECIZb1NsWIikP9pd8gIlTIRx7fuDNpU9fsxOE=
|
||||
github.com/disintegration/imaging v1.6.1/go.mod h1:xuIt+sRxDFrHS0drzXUlCJthkJ8k7lkkUojDSR247MQ=
|
||||
github.com/docker/distribution v2.7.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v0.7.3-0.20190103212154-2b7e084dc98b/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v0.7.3-0.20190108045446-77df18c24acf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v0.7.3-0.20190817195342-4760db040282/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/dustin/go-humanize v0.0.0-20180713052910-9f541cc9db5d/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
|
|
@ -97,17 +90,12 @@ github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga
|
|||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsouza/fake-gcs-server v1.3.0/go.mod h1:Lq+43m2znsXfDKHnQMfdA0HpYYAEJsfizsbpk5k3TLo=
|
||||
github.com/fsouza/fake-gcs-server v1.7.0/go.mod h1:5XIRs4YvwNbNoz+1JF8j6KLAyDh7RHGAyAK3EP2EsNk=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||
github.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
||||
github.com/go-chi/chi v4.0.1+incompatible h1:RSRC5qmFPtO90t7pTL0DBMNpZFsb/sHF3RXVlDgFisA=
|
||||
github.com/go-chi/chi v4.0.1+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
||||
github.com/go-chi/chi v4.0.2+incompatible h1:maB6vn6FqCxrpz4FqWdh4+lwpyZIQS7YEAUcHlgXVRs=
|
||||
github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
||||
github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||
github.com/go-ini/ini v1.39.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
|
|
@ -268,6 +256,7 @@ github.com/gobuffalo/packr v1.15.0/go.mod h1:t5gXzEhIviQwVlNx/+3SfS07GS+cZ2hn76W
|
|||
github.com/gobuffalo/packr v1.15.1/go.mod h1:IeqicJ7jm8182yrVmNbM6PR4g79SjN9tZLH8KduZZwE=
|
||||
github.com/gobuffalo/packr v1.19.0/go.mod h1:MstrNkfCQhd5o+Ct4IJ0skWlxN8emOq8DsoT1G98VIU=
|
||||
github.com/gobuffalo/packr v1.20.0/go.mod h1:JDytk1t2gP+my1ig7iI4NcVaXr886+N0ecUga6884zw=
|
||||
github.com/gobuffalo/packr v1.21.0 h1:p2ujcDJQp2QTiYWcI0ByHbr/gMoCouok6M0vXs/yTYQ=
|
||||
github.com/gobuffalo/packr v1.21.0/go.mod h1:H00jGfj1qFKxscFJSw8wcL4hpQtPe1PfU2wa6sg/SR0=
|
||||
github.com/gobuffalo/packr/v2 v2.0.0-rc.8/go.mod h1:y60QCdzwuMwO2R49fdQhsjCPv7tLQFR0ayzxxla9zes=
|
||||
github.com/gobuffalo/packr/v2 v2.0.0-rc.9/go.mod h1:fQqADRfZpEsgkc7c/K7aMew3n4aF1Kji7+lIZeR98Fc=
|
||||
|
|
@ -322,7 +311,6 @@ github.com/gobuffalo/uuid v2.0.5+incompatible/go.mod h1:ErhIzkRhm0FtRuiE/PeORqcw
|
|||
github.com/gobuffalo/validate v2.0.3+incompatible/go.mod h1:N+EtDe0J8252BgfzQUChBgfd6L93m9weay53EWFVsMM=
|
||||
github.com/gobuffalo/x v0.0.0-20181003152136-452098b06085/go.mod h1:WevpGD+5YOreDJznWevcn8NTmQEW5STSBgIkpkjzqXc=
|
||||
github.com/gobuffalo/x v0.0.0-20181007152206-913e47c59ca7/go.mod h1:9rDPXaB3kXdKWzMc4odGQQdG2e2DIEmANy5aSJ9yesY=
|
||||
github.com/gocql/gocql v0.0.0-20181124151448-70385f88b28b/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0=
|
||||
github.com/gocql/gocql v0.0.0-20190301043612-f6df8288f9b4/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0=
|
||||
github.com/gofrs/uuid v3.1.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
|
|
@ -330,10 +318,8 @@ github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
|
|||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/golang-migrate/migrate/v4 v4.2.2 h1:m9WF3B3yge1mKm5+/q6C3qPETMWqphrod3+osb+sP8A=
|
||||
github.com/golang-migrate/migrate/v4 v4.2.2/go.mod h1:JRwdki93/aFawDXMUM4GcRu/FAIfyw+1Kuyd9vkbaeA=
|
||||
github.com/golang-migrate/migrate/v4 v4.3.1 h1:3eR1NY+pplX+m6yJ1fQf5dFWX3fBgUtZfDiaS/kJVu4=
|
||||
github.com/golang-migrate/migrate/v4 v4.3.1/go.mod h1:mJ89KBgbXmM3P49BqOxRL3riNF/ATlg5kMhm17GA0dE=
|
||||
github.com/golang-migrate/migrate/v4 v4.7.0 h1:gONcHxHApDTKXDyLH/H97gEHmpu1zcnnbAaq2zgrPrs=
|
||||
github.com/golang-migrate/migrate/v4 v4.7.0/go.mod h1:Qvut3N4xKWjoH3sokBccML6WyHSnggXm/DvMMnTsQIc=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
|
||||
|
|
@ -356,7 +342,6 @@ github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OI
|
|||
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
||||
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181004151105-1babbf986f6f/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
|
|
@ -371,15 +356,15 @@ github.com/gorilla/websocket v1.2.0 h1:VJtLvh6VQym50czpZzx07z/kw9EgAxI3x1ZB8taTM
|
|||
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
|
||||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/h2non/filetype v1.0.6 h1:g84/+gdkAT1hnYO+tHpCLoikm13Ju55OkN4KCb1uGEQ=
|
||||
github.com/h2non/filetype v1.0.6/go.mod h1:isekKqOuhMj+s/7r3rIeTErIRy4Rub5uBWHfvMusLMU=
|
||||
github.com/h2non/filetype v1.0.8 h1:le8gpf+FQA0/DlDABbtisA1KiTS0Xi+YSC/E8yY3Y14=
|
||||
github.com/h2non/filetype v1.0.8/go.mod h1:isekKqOuhMj+s/7r3rIeTErIRy4Rub5uBWHfvMusLMU=
|
||||
github.com/h2non/filetype v1.0.10 h1:z+SJfnL6thYJ9kAST+6nPRXp1lMxnOVbMZHNYHMar0s=
|
||||
github.com/h2non/filetype v1.0.10/go.mod h1:isekKqOuhMj+s/7r3rIeTErIRy4Rub5uBWHfvMusLMU=
|
||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
|
||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
|
|
@ -397,7 +382,6 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt
|
|||
github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ=
|
||||
github.com/jackc/pgx v3.2.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I=
|
||||
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmoiron/sqlx v0.0.0-20180614180643-0dae4fefe7c0/go.mod h1:IiEW3SEiiErVyFdH8NTuWjSifiEQKUoyK3LNqr2kCHU=
|
||||
github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA=
|
||||
|
|
@ -407,7 +391,6 @@ github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
|
|||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
|
||||
github.com/karrick/godirwalk v1.7.5/go.mod h1:2c9FRhkDxdIbgkOnCEvnSWs71Bhugbl46shStcFDJ34=
|
||||
|
|
@ -429,12 +412,13 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
|||
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kshvakov/clickhouse v1.3.4/go.mod h1:DMzX7FxRymoNkVgizH0DWAL8Cur7wHLgx3MUnGwJqpE=
|
||||
github.com/kshvakov/clickhouse v1.3.5/go.mod h1:DMzX7FxRymoNkVgizH0DWAL8Cur7wHLgx3MUnGwJqpE=
|
||||
github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/markbates/deplist v1.0.4/go.mod h1:gRRbPbbuA8TmMiRvaOzUlRfzfjeCCBqX2A6arxN01MM=
|
||||
github.com/markbates/deplist v1.0.5/go.mod h1:gRRbPbbuA8TmMiRvaOzUlRfzfjeCCBqX2A6arxN01MM=
|
||||
github.com/markbates/going v1.0.2/go.mod h1:UWCk3zm0UKefHZ7l8BNqi26UyiEMniznk8naLdTcy6c=
|
||||
|
|
@ -470,9 +454,8 @@ github.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047/go.mod h1:F
|
|||
github.com/mitchellh/mapstructure v1.0.0/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mongodb/mongo-go-driver v0.1.0/go.mod h1:NK/HWDIIZkaYsnYa0hmtP443T5ELr0KDecmIioVuuyU=
|
||||
github.com/mongodb/mongo-go-driver v0.3.0/go.mod h1:NK/HWDIIZkaYsnYa0hmtP443T5ELr0KDecmIioVuuyU=
|
||||
github.com/monoculum/formam v0.0.0-20180901015400-4e68be1d79ba/go.mod h1:RKgILGEJq24YyJ2ban8EO0RUVSJlF1pGsEvoLEACr/Q=
|
||||
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8/go.mod h1:86wM1zFnC6/uDBfZGNwB65O+pR2OFi5q/YQaEUid1qA=
|
||||
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
|
||||
|
|
@ -510,7 +493,6 @@ github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7q
|
|||
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20180920065004-418d78d0b9a7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
|
|
@ -524,6 +506,8 @@ github.com/rogpeppe/go-internal v1.2.2 h1:J7U/N7eRtzjhs26d6GqMh2HBuXP8/Z64Densii
|
|||
github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rs/cors v1.6.0 h1:G9tHG9lebljV9mfp9SNPDL36nCDxmo3zTlAf1YgvzmI=
|
||||
github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||
github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
|
||||
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/serenize/snaker v0.0.0-20171204205717-a683aaf2d516/go.mod h1:Yow6lPLSAXx2ifx470yD/nUe22Dv5vBvxK/UK9UUTVs=
|
||||
|
|
@ -564,8 +548,6 @@ github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
|
|||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
|
||||
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
|
||||
|
|
@ -583,18 +565,20 @@ github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb6
|
|||
github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.2.1/go.mod h1:P4AexN0a+C9tGAnUFNwDMYYZv3pjFuvmeiMyKRaNVlI=
|
||||
github.com/spf13/viper v1.3.1/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||
github.com/spf13/viper v1.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M=
|
||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||
github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU=
|
||||
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
||||
github.com/spf13/viper v1.5.0 h1:GpsTwfsQ27oS/Aha/6d1oD7tpKIqWnOA6tgOX9HHkt4=
|
||||
github.com/spf13/viper v1.5.0/go.mod h1:AkYRkVJF8TkSG/xet6PzXX+l39KhhXa2pdqVSxnTcn4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
|
||||
github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
|
|
@ -604,13 +588,12 @@ github.com/unrolled/secure v0.0.0-20180918153822-f340ee86eb8b/go.mod h1:mnPT77IA
|
|||
github.com/unrolled/secure v0.0.0-20181005190816-ff9db2ff917f/go.mod h1:mnPT77IAdsi/kV7+Es7y+pXALeV3h7G6dQF6mNYjcLA=
|
||||
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/vektah/dataloaden v0.2.0/go.mod h1:vxM6NuRlgiR0M6wbVTJeKp9vQIs81ZMfCYO+4yq/jbE=
|
||||
github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e h1:+w0Zm/9gaWpEAyDlU1eKOuk5twTjAjuevXqcJJw8hrg=
|
||||
github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U=
|
||||
github.com/vektah/gqlparser v1.1.0 h1:3668p2gUlO+PiS81x957Rpr3/FPRWG6cxgCXAvTS1hw=
|
||||
github.com/vektah/gqlparser v1.1.0/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
|
||||
github.com/vektah/gqlparser v1.1.2 h1:ZsyLGn7/7jDNI+y4SEhI4yAxRChlv15pUHMjijT+e68=
|
||||
github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
|
||||
github.com/vektah/gqlparser v1.2.0 h1:ntkSCX7F5ZJKl+HIVnmLaO269MruasVpNiMOjX9kgo0=
|
||||
github.com/vektah/gqlparser v1.2.0/go.mod h1:bkVf0FX+Stjg/MHnm8mEyubuaArhNEqfQhF+OTiAL74=
|
||||
github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs=
|
||||
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
|
||||
github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
|
||||
|
|
@ -618,7 +601,7 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q
|
|||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.opencensus.io v0.17.0/go.mod h1:mp1VrMQxhlqqDpKvH4UcQUa4YwlzNmymAjPrDdfxNpI=
|
||||
go.mongodb.org/mongo-driver v1.1.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
|
||||
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
||||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
|
|
@ -645,6 +628,7 @@ golang.org/x/crypto v0.0.0-20190103213133-ff983b9c42bc h1:F5tKCVGp+MUAHhKp5MZtGq
|
|||
golang.org/x/crypto v0.0.0-20190103213133-ff983b9c42bc/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734 h1:p/H982KKEjUnLJkM3tt/LemDnOc1GiZL5FCVlORJ5zo=
|
||||
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
|
||||
|
|
@ -659,13 +643,11 @@ golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvx
|
|||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180404174746-b3c676e531a6/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180816102801-aaf60122140d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180921000356-2f5d2388922f/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180925072008-f04abc6bdfa7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180926154720-4dfa2610cdf3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
|
@ -699,6 +681,7 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
|
|||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180816055513-1c9583448a9c/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
|
@ -706,7 +689,6 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h
|
|||
golang.org/x/sys v0.0.0-20180906133057-8cf3aee42992/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180921163948-d47a0f339242/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180925112736-b09afc3d579e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180927150500-dad3d9fb7b6e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181005133103-4497e2df6f9e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181011152604-fa43e7bc11ba/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
|
@ -723,7 +705,6 @@ golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5h
|
|||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181206074257-70b957f3b65e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190102155601-82a175fd1598/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190108104531-7fbe1cd0fcc2/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190116161447-11f53e031339 h1:g/Jesu8+QLnA0CPzF3E1pURg0Byr7i6jLoX5sqjcAh0=
|
||||
golang.org/x/sys v0.0.0-20190116161447-11f53e031339/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
|
@ -742,7 +723,6 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxb
|
|||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180924175601-e93be7f42f9f/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181003024731-2f84ea8ef872/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181006002542-f60d9635b16a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181008205924-a2b3f7f249e9/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
|
@ -764,7 +744,6 @@ golang.org/x/tools v0.0.0-20181207183836-8bc39b988060/go.mod h1:n7NCudcB/nEzxVGm
|
|||
golang.org/x/tools v0.0.0-20181212172921-837e80568c09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190102213336-ca9055ed7d04/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190104182027-498d95493402/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190108222858-421f03a57a64/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190111214448-fc1d57b08d7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190118193359-16909d206f00 h1:6OmoTtlNJlHuWNIjTEyUtMBHrryp8NRuf/XtnC7MmXM=
|
||||
|
|
@ -783,8 +762,6 @@ golang.org/x/tools v0.0.0-20190425222832-ad9eeb80039a/go.mod h1:RgjU9mgBXZiqYHBn
|
|||
golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd h1:oMEQDWVXVNpceQoVd1JN3CQ7LYJJzs5qWqZIUcxXHHw=
|
||||
golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
google.golang.org/api v0.0.0-20180921000521-920bb1beccf7/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
google.golang.org/api v0.0.0-20181015145326-625cd1887957/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
|
||||
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
||||
|
|
@ -795,19 +772,17 @@ google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
|
|||
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20180924164928-221a8d4f7494/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
|
||||
google.golang.org/genproto v0.0.0-20190108161440-ae2f86662275/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
|
||||
google.golang.org/genproto v0.0.0-20190201180003-4b09977fb922/go.mod h1:L3J43x8/uS+qIUoksaLKe6OS3nUKxOKuIFz1sl2/jx4=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.15.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
||||
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
|
|
@ -824,7 +799,6 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy
|
|||
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/ini.v1 v1.39.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/mail.v2 v2.0.0-20180731213649-a0242b2233b4/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
|
|
@ -832,10 +806,11 @@ gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bl
|
|||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20180920025451-e3ad64cb4ed3/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
sourcegraph.com/sourcegraph/appdash v0.0.0-20180110180208-2cc67fd64755/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
|
||||
|
|
|
|||
2
main.go
2
main.go
|
|
@ -1,4 +1,4 @@
|
|||
//go:generate go run -mod=vendor github.com/99designs/gqlgen
|
||||
//go:generate go run github.com/99designs/gqlgen
|
||||
package main
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@ GITHASH=`git rev-parse --short HEAD`
|
|||
VERSION_FLAGS="-X 'github.com/stashapp/stash/pkg/api.buildstamp=$DATE' -X 'github.com/stashapp/stash/pkg/api.githash=$GITHASH'"
|
||||
|
||||
SETUP="export GO111MODULE=on; export CGO_ENABLED=1;"
|
||||
WINDOWS="GOOS=windows GOARCH=amd64 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ packr2 build -o dist/stash-win.exe -ldflags \"-extldflags '-static' $VERSION_FLAGS\" -tags extended -v -mod=vendor;"
|
||||
DARWIN="GOOS=darwin GOARCH=amd64 CC=o64-clang CXX=o64-clang++ packr2 build -o dist/stash-osx -ldflags \"$VERSION_FLAGS\" -tags extended -v -mod=vendor;"
|
||||
LINUX="packr2 build -o dist/stash-linux -ldflags \"$VERSION_FLAGS\" -v -mod=vendor;"
|
||||
RASPPI="GOOS=linux GOARCH=arm GOARM=5 CC=arm-linux-gnueabi-gcc packr2 build -o dist/stash-pi -ldflags \"$VERSION_FLAGS\" -v -mod=vendor;"
|
||||
WINDOWS="GOOS=windows GOARCH=amd64 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ packr2 build -o dist/stash-win.exe -ldflags \"-extldflags '-static' $VERSION_FLAGS\" -tags extended -v;"
|
||||
DARWIN="GOOS=darwin GOARCH=amd64 CC=o64-clang CXX=o64-clang++ packr2 build -o dist/stash-osx -ldflags \"$VERSION_FLAGS\" -tags extended -v;"
|
||||
LINUX="packr2 build -o dist/stash-linux -ldflags \"$VERSION_FLAGS\" -v;"
|
||||
RASPPI="GOOS=linux GOARCH=arm GOARM=5 CC=arm-linux-gnueabi-gcc packr2 build -o dist/stash-pi -ldflags \"$VERSION_FLAGS\" -v;"
|
||||
|
||||
COMMAND="$SETUP $WINDOWS $DARWIN $LINUX $RASPPI"
|
||||
|
||||
|
|
|
|||
3
vendor/github.com/99designs/gqlgen/.dockerignore
generated
vendored
3
vendor/github.com/99designs/gqlgen/.dockerignore
generated
vendored
|
|
@ -1,3 +0,0 @@
|
|||
/**/node_modules
|
||||
/codegen/tests/gen
|
||||
/vendor
|
||||
20
vendor/github.com/99designs/gqlgen/.editorconfig
generated
vendored
20
vendor/github.com/99designs/gqlgen/.editorconfig
generated
vendored
|
|
@ -1,20 +0,0 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.{go,gotpl}]
|
||||
indent_style = tab
|
||||
|
||||
[*.yml]
|
||||
indent_size = 2
|
||||
|
||||
# These often end up with go code inside, so lets keep tabs
|
||||
[*.{html,md}]
|
||||
indent_size = 2
|
||||
indent_style = tab
|
||||
3
vendor/github.com/99designs/gqlgen/.gitattributes
generated
vendored
3
vendor/github.com/99designs/gqlgen/.gitattributes
generated
vendored
|
|
@ -1,3 +0,0 @@
|
|||
/codegen/templates/data.go linguist-generated
|
||||
/example/dataloader/*_gen.go linguist-generated
|
||||
generated.go linguist-generated
|
||||
12
vendor/github.com/99designs/gqlgen/.gitignore
generated
vendored
12
vendor/github.com/99designs/gqlgen/.gitignore
generated
vendored
|
|
@ -1,12 +0,0 @@
|
|||
/vendor
|
||||
/docs/public
|
||||
/example/chat/node_modules
|
||||
/integration/node_modules
|
||||
/integration/schema-fetched.graphql
|
||||
/example/chat/package-lock.json
|
||||
/codegen/gen
|
||||
/gen
|
||||
|
||||
.idea/
|
||||
*.test
|
||||
*.out
|
||||
3
vendor/github.com/99designs/gqlgen/.golangci.yml
generated
vendored
3
vendor/github.com/99designs/gqlgen/.golangci.yml
generated
vendored
|
|
@ -1,3 +0,0 @@
|
|||
linters-settings:
|
||||
errcheck:
|
||||
ignore: fmt:.*,[rR]ead|[wW]rite|[cC]lose,io:Copy
|
||||
27
vendor/github.com/99designs/gqlgen/CONTRIBUTING.md
generated
vendored
27
vendor/github.com/99designs/gqlgen/CONTRIBUTING.md
generated
vendored
|
|
@ -1,27 +0,0 @@
|
|||
# Contribution Guidelines
|
||||
|
||||
Want to contribute to gqlgen? Here are some guidelines for how we accept help.
|
||||
|
||||
## Getting in Touch
|
||||
|
||||
Our [gitter](https://gitter.im/gqlgen/Lobby) channel is the best place to ask questions or get advice on using gqlgen.
|
||||
|
||||
## Reporting Bugs and Issues
|
||||
|
||||
We use [GitHub Issues](https://github.com/99designs/gqlgen/issues) to track bugs, so please do a search before submitting to ensure your problem isn't already tracked.
|
||||
|
||||
### New Issues
|
||||
|
||||
Please provide the expected and observed behaviours in your issue. A minimal GraphQL schema or configuration file should be provided where appropriate.
|
||||
|
||||
## Proposing a Change
|
||||
|
||||
If you intend to implement a feature for gqlgen, or make a non-trivial change to the current implementation, we recommend [first filing an issue](https://github.com/99designs/gqlgen/issues/new) marked with the `proposal` tag, so that the engineering team can provide guidance and feedback on the direction of an implementation. This also help ensure that other people aren't also working on the same thing.
|
||||
|
||||
Bug fixes are welcome and should come with appropriate test coverage.
|
||||
|
||||
New features should be made against the `next` branch.
|
||||
|
||||
### License
|
||||
|
||||
By contributing to gqlgen, you agree that your contributions will be licensed under its MIT license.
|
||||
19
vendor/github.com/99designs/gqlgen/LICENSE
generated
vendored
19
vendor/github.com/99designs/gqlgen/LICENSE
generated
vendored
|
|
@ -1,19 +0,0 @@
|
|||
Copyright (c) 2018 Adam Scarr
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
31
vendor/github.com/99designs/gqlgen/README.md
generated
vendored
31
vendor/github.com/99designs/gqlgen/README.md
generated
vendored
|
|
@ -1,31 +0,0 @@
|
|||
# gqlgen [](https://circleci.com/gh/99designs/gqlgen) [](http://gqlgen.com/)
|
||||
|
||||
## What is gqlgen?
|
||||
|
||||
[gqlgen](https://github.com/99designs/gqlgen) is a Go library for building GraphQL servers without any fuss. gqlgen is:
|
||||
|
||||
- **Schema first** — Define your API using the GraphQL [Schema Definition Language](http://graphql.org/learn/schema/).
|
||||
- **Type safe** — You should never see `map[string]interface{}` here.
|
||||
- **Codegen** — Let us generate the boring bits, so you can build your app quickly.
|
||||
|
||||
[Feature Comparison](https://gqlgen.com/feature-comparison/)
|
||||
|
||||
## Getting Started
|
||||
|
||||
First work your way through the [Getting Started](https://gqlgen.com/getting-started/) tutorial.
|
||||
|
||||
If you can't find what your looking for, look at our [examples](https://github.com/99designs/gqlgen/tree/master/example) for example usage of gqlgen.
|
||||
|
||||
## Reporting Issues
|
||||
|
||||
If you think you've found a bug, or something isn't behaving the way you think it should, please raise an [issue](https://github.com/99designs/gqlgen/issues) on GitHub.
|
||||
|
||||
## Contributing
|
||||
|
||||
Read our [Contribution Guidelines](https://github.com/99designs/gqlgen/blob/master/CONTRIBUTING.md) for information on how you can help out gqlgen.
|
||||
|
||||
## 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/)
|
||||
- [GraphQL workshop for Golang developers by Iván Corrales Solera](https://graphql-go.wesovilabs.com)
|
||||
40
vendor/github.com/99designs/gqlgen/TESTING.md
generated
vendored
40
vendor/github.com/99designs/gqlgen/TESTING.md
generated
vendored
|
|
@ -1,40 +0,0 @@
|
|||
How to write tests for gqlgen
|
||||
===
|
||||
|
||||
Testing generated code is a little tricky, heres how its currently set up.
|
||||
|
||||
### Testing responses from a server
|
||||
|
||||
There is a server in `codegen/testserver` that is generated as part
|
||||
of `go generate ./...`, and tests written against it.
|
||||
|
||||
There are also a bunch of tests in against the examples, feel free to take examples from there.
|
||||
|
||||
|
||||
### Testing the errors generated by the binary
|
||||
|
||||
These tests are **really** slow, because they need to run the whole codegen step. Use them very sparingly. If you can, find a way to unit test it instead.
|
||||
|
||||
Take a look at `codegen/input_test.go` for an example.
|
||||
|
||||
### Testing introspection
|
||||
|
||||
Introspection is tested by diffing the output of `graphql get-schema` against an expected output.
|
||||
|
||||
Setting up the integration environment is a little tricky:
|
||||
```bash
|
||||
cd integration
|
||||
go generate ./...
|
||||
go run ./server/server.go
|
||||
```
|
||||
in another terminal
|
||||
```bash
|
||||
cd integration
|
||||
npm install
|
||||
SERVER_URL=http://localhost:8080/query ./node_modules/.bin/graphql get-schema
|
||||
```
|
||||
|
||||
will write the schema to `integration/schema-fetched.graphql`, compare that with `schema-expected.graphql`
|
||||
|
||||
CI will run this and fail the build if the two files dont match.
|
||||
|
||||
76
vendor/github.com/99designs/gqlgen/api/generate.go
generated
vendored
76
vendor/github.com/99designs/gqlgen/api/generate.go
generated
vendored
|
|
@ -1,76 +0,0 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
|
||||
"github.com/99designs/gqlgen/codegen"
|
||||
"github.com/99designs/gqlgen/codegen/config"
|
||||
"github.com/99designs/gqlgen/plugin"
|
||||
"github.com/99designs/gqlgen/plugin/modelgen"
|
||||
"github.com/99designs/gqlgen/plugin/resolvergen"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/tools/go/packages"
|
||||
)
|
||||
|
||||
func Generate(cfg *config.Config, option ...Option) error {
|
||||
_ = syscall.Unlink(cfg.Exec.Filename)
|
||||
_ = syscall.Unlink(cfg.Model.Filename)
|
||||
|
||||
plugins := []plugin.Plugin{
|
||||
modelgen.New(),
|
||||
resolvergen.New(),
|
||||
}
|
||||
|
||||
for _, o := range option {
|
||||
o(cfg, &plugins)
|
||||
}
|
||||
|
||||
for _, p := range plugins {
|
||||
if mut, ok := p.(plugin.ConfigMutator); ok {
|
||||
err := mut.MutateConfig(cfg)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, p.Name())
|
||||
}
|
||||
}
|
||||
}
|
||||
// Merge again now that the generated models have been injected into the typemap
|
||||
data, err := codegen.BuildData(cfg)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "merging failed")
|
||||
}
|
||||
|
||||
if err = codegen.GenerateCode(data); err != nil {
|
||||
return errors.Wrap(err, "generating core failed")
|
||||
}
|
||||
|
||||
for _, p := range plugins {
|
||||
if mut, ok := p.(plugin.CodeGenerator); ok {
|
||||
err := mut.GenerateCode(data)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, p.Name())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := validate(cfg); err != nil {
|
||||
return errors.Wrap(err, "validation failed")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func validate(cfg *config.Config) error {
|
||||
roots := []string{cfg.Exec.ImportPath()}
|
||||
if cfg.Model.IsDefined() {
|
||||
roots = append(roots, cfg.Model.ImportPath())
|
||||
}
|
||||
|
||||
if cfg.Resolver.IsDefined() {
|
||||
roots = append(roots, cfg.Resolver.ImportPath())
|
||||
}
|
||||
_, err := packages.Load(&packages.Config{Mode: packages.LoadTypes | packages.LoadSyntax}, roots...)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "validation failed")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
20
vendor/github.com/99designs/gqlgen/api/option.go
generated
vendored
20
vendor/github.com/99designs/gqlgen/api/option.go
generated
vendored
|
|
@ -1,20 +0,0 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"github.com/99designs/gqlgen/codegen/config"
|
||||
"github.com/99designs/gqlgen/plugin"
|
||||
)
|
||||
|
||||
type Option func(cfg *config.Config, plugins *[]plugin.Plugin)
|
||||
|
||||
func NoPlugins() Option {
|
||||
return func(cfg *config.Config, plugins *[]plugin.Plugin) {
|
||||
*plugins = nil
|
||||
}
|
||||
}
|
||||
|
||||
func AddPlugin(p plugin.Plugin) Option {
|
||||
return func(cfg *config.Config, plugins *[]plugin.Plugin) {
|
||||
*plugins = append(*plugins, p)
|
||||
}
|
||||
}
|
||||
32
vendor/github.com/99designs/gqlgen/appveyor.yml
generated
vendored
32
vendor/github.com/99designs/gqlgen/appveyor.yml
generated
vendored
|
|
@ -1,32 +0,0 @@
|
|||
version: "{build}"
|
||||
|
||||
# Source Config
|
||||
|
||||
skip_branch_with_pr: true
|
||||
clone_folder: c:\projects\gqlgen
|
||||
|
||||
# Build host
|
||||
|
||||
environment:
|
||||
GOPATH: c:\gopath
|
||||
GOVERSION: 1.11.5
|
||||
PATH: '%PATH%;c:\gopath\bin'
|
||||
|
||||
init:
|
||||
- git config --global core.autocrlf input
|
||||
|
||||
# Build
|
||||
|
||||
install:
|
||||
# Install the specific Go version.
|
||||
- rmdir c:\go /s /q
|
||||
- appveyor DownloadFile https://storage.googleapis.com/golang/go%GOVERSION%.windows-amd64.msi
|
||||
- msiexec /i go%GOVERSION%.windows-amd64.msi /q
|
||||
- go version
|
||||
|
||||
build: false
|
||||
deploy: false
|
||||
|
||||
test_script:
|
||||
- go generate ./...
|
||||
- go test -timeout 20m ./...
|
||||
10
vendor/github.com/99designs/gqlgen/cmd/ambient.go
generated
vendored
10
vendor/github.com/99designs/gqlgen/cmd/ambient.go
generated
vendored
|
|
@ -1,10 +0,0 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
// Import and ignore the ambient imports listed below so dependency managers
|
||||
// don't prune unused code for us. Both lists should be kept in sync.
|
||||
_ "github.com/99designs/gqlgen/graphql"
|
||||
_ "github.com/99designs/gqlgen/graphql/introspection"
|
||||
_ "github.com/vektah/gqlparser"
|
||||
_ "github.com/vektah/gqlparser/ast"
|
||||
)
|
||||
44
vendor/github.com/99designs/gqlgen/cmd/gen.go
generated
vendored
44
vendor/github.com/99designs/gqlgen/cmd/gen.go
generated
vendored
|
|
@ -1,44 +0,0 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/99designs/gqlgen/api"
|
||||
"github.com/99designs/gqlgen/codegen/config"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var genCmd = cli.Command{
|
||||
Name: "generate",
|
||||
Usage: "generate a graphql server based on schema",
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{Name: "verbose, v", Usage: "show logs"},
|
||||
cli.StringFlag{Name: "config, c", Usage: "the config filename"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
var cfg *config.Config
|
||||
var err error
|
||||
if configFilename := ctx.String("config"); configFilename != "" {
|
||||
cfg, err = config.LoadConfig(configFilename)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
} else {
|
||||
cfg, err = config.LoadConfigFromDefaultLocations()
|
||||
if os.IsNotExist(errors.Cause(err)) {
|
||||
cfg = config.DefaultConfig()
|
||||
} else if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err.Error())
|
||||
os.Exit(2)
|
||||
}
|
||||
}
|
||||
|
||||
if err = api.Generate(cfg); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err.Error())
|
||||
os.Exit(3)
|
||||
}
|
||||
},
|
||||
}
|
||||
144
vendor/github.com/99designs/gqlgen/cmd/init.go
generated
vendored
144
vendor/github.com/99designs/gqlgen/cmd/init.go
generated
vendored
|
|
@ -1,144 +0,0 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/99designs/gqlgen/api"
|
||||
"github.com/99designs/gqlgen/plugin/servergen"
|
||||
|
||||
"github.com/99designs/gqlgen/codegen/config"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
var configComment = `
|
||||
# .gqlgen.yml example
|
||||
#
|
||||
# Refer to https://gqlgen.com/config/
|
||||
# for detailed .gqlgen.yml documentation.
|
||||
`
|
||||
|
||||
var schemaDefault = `
|
||||
# GraphQL schema example
|
||||
#
|
||||
# https://gqlgen.com/getting-started/
|
||||
|
||||
type Todo {
|
||||
id: ID!
|
||||
text: String!
|
||||
done: Boolean!
|
||||
user: User!
|
||||
}
|
||||
|
||||
type User {
|
||||
id: ID!
|
||||
name: String!
|
||||
}
|
||||
|
||||
type Query {
|
||||
todos: [Todo!]!
|
||||
}
|
||||
|
||||
input NewTodo {
|
||||
text: String!
|
||||
userId: String!
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
createTodo(input: NewTodo!): Todo!
|
||||
}
|
||||
`
|
||||
|
||||
var initCmd = cli.Command{
|
||||
Name: "init",
|
||||
Usage: "create a new gqlgen project",
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{Name: "verbose, v", Usage: "show logs"},
|
||||
cli.StringFlag{Name: "config, c", Usage: "the config filename"},
|
||||
cli.StringFlag{Name: "server", Usage: "where to write the server stub to", Value: "server/server.go"},
|
||||
cli.StringFlag{Name: "schema", Usage: "where to write the schema stub to", Value: "schema.graphql"},
|
||||
},
|
||||
Action: func(ctx *cli.Context) {
|
||||
initSchema(ctx.String("schema"))
|
||||
config := initConfig(ctx)
|
||||
|
||||
GenerateGraphServer(config, ctx.String("server"))
|
||||
},
|
||||
}
|
||||
|
||||
func GenerateGraphServer(cfg *config.Config, serverFilename string) {
|
||||
err := api.Generate(cfg, api.AddPlugin(servergen.New(serverFilename)))
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err.Error())
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stdout, "Exec \"go run ./%s\" to start GraphQL server\n", serverFilename)
|
||||
}
|
||||
|
||||
func initConfig(ctx *cli.Context) *config.Config {
|
||||
var cfg *config.Config
|
||||
var err error
|
||||
configFilename := ctx.String("config")
|
||||
if configFilename != "" {
|
||||
cfg, err = config.LoadConfig(configFilename)
|
||||
} else {
|
||||
cfg, err = config.LoadConfigFromDefaultLocations()
|
||||
}
|
||||
|
||||
if cfg != nil {
|
||||
fmt.Fprintf(os.Stderr, "init failed: a configuration file already exists\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if !os.IsNotExist(errors.Cause(err)) {
|
||||
fmt.Fprintln(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if configFilename == "" {
|
||||
configFilename = "gqlgen.yml"
|
||||
}
|
||||
cfg = config.DefaultConfig()
|
||||
|
||||
cfg.Resolver = config.PackageConfig{
|
||||
Filename: "resolver.go",
|
||||
Type: "Resolver",
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
buf.WriteString(strings.TrimSpace(configComment))
|
||||
buf.WriteString("\n\n")
|
||||
var b []byte
|
||||
b, err = yaml.Marshal(cfg)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "unable to marshal yaml: "+err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
buf.Write(b)
|
||||
|
||||
err = ioutil.WriteFile(configFilename, buf.Bytes(), 0644)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "unable to write cfg file: "+err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
||||
func initSchema(schemaFilename string) {
|
||||
_, err := os.Stat(schemaFilename)
|
||||
if !os.IsNotExist(err) {
|
||||
return
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(schemaFilename, []byte(strings.TrimSpace(schemaDefault)), 0644)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "unable to write schema file: "+err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
44
vendor/github.com/99designs/gqlgen/cmd/root.go
generated
vendored
44
vendor/github.com/99designs/gqlgen/cmd/root.go
generated
vendored
|
|
@ -1,44 +0,0 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/99designs/gqlgen/graphql"
|
||||
"github.com/urfave/cli"
|
||||
|
||||
// Required since otherwise dep will prune away these unused packages before codegen has a chance to run
|
||||
_ "github.com/99designs/gqlgen/handler"
|
||||
)
|
||||
|
||||
func Execute() {
|
||||
app := cli.NewApp()
|
||||
app.Name = "gqlgen"
|
||||
app.Usage = genCmd.Usage
|
||||
app.Description = "This is a library for quickly creating strictly typed graphql servers in golang. See https://gqlgen.com/ for a getting started guide."
|
||||
app.HideVersion = true
|
||||
app.Flags = genCmd.Flags
|
||||
app.Version = graphql.Version
|
||||
app.Before = func(context *cli.Context) error {
|
||||
if context.Bool("verbose") {
|
||||
log.SetFlags(0)
|
||||
} else {
|
||||
log.SetOutput(ioutil.Discard)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
app.Action = genCmd.Action
|
||||
app.Commands = []cli.Command{
|
||||
genCmd,
|
||||
initCmd,
|
||||
versionCmd,
|
||||
}
|
||||
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
fmt.Fprint(os.Stderr, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
16
vendor/github.com/99designs/gqlgen/cmd/version.go
generated
vendored
16
vendor/github.com/99designs/gqlgen/cmd/version.go
generated
vendored
|
|
@ -1,16 +0,0 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/99designs/gqlgen/graphql"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var versionCmd = cli.Command{
|
||||
Name: "version",
|
||||
Usage: "print the version string",
|
||||
Action: func(ctx *cli.Context) {
|
||||
fmt.Println(graphql.Version)
|
||||
},
|
||||
}
|
||||
104
vendor/github.com/99designs/gqlgen/codegen/args.go
generated
vendored
104
vendor/github.com/99designs/gqlgen/codegen/args.go
generated
vendored
|
|
@ -1,104 +0,0 @@
|
|||
package codegen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/types"
|
||||
"strings"
|
||||
|
||||
"github.com/99designs/gqlgen/codegen/config"
|
||||
"github.com/99designs/gqlgen/codegen/templates"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/vektah/gqlparser/ast"
|
||||
)
|
||||
|
||||
type ArgSet struct {
|
||||
Args []*FieldArgument
|
||||
FuncDecl string
|
||||
}
|
||||
|
||||
type FieldArgument struct {
|
||||
*ast.ArgumentDefinition
|
||||
TypeReference *config.TypeReference
|
||||
VarName string // The name of the var in go
|
||||
Object *Object // A link back to the parent object
|
||||
Default interface{} // The default value
|
||||
Directives []*Directive
|
||||
Value interface{} // value set in Data
|
||||
}
|
||||
|
||||
func (f *FieldArgument) Stream() bool {
|
||||
return f.Object != nil && f.Object.Stream
|
||||
}
|
||||
|
||||
func (b *builder) buildArg(obj *Object, arg *ast.ArgumentDefinition) (*FieldArgument, error) {
|
||||
tr, err := b.Binder.TypeReference(arg.Type, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
argDirs, err := b.getDirectives(arg.Directives)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newArg := FieldArgument{
|
||||
ArgumentDefinition: arg,
|
||||
TypeReference: tr,
|
||||
Object: obj,
|
||||
VarName: templates.ToGoPrivate(arg.Name),
|
||||
Directives: argDirs,
|
||||
}
|
||||
|
||||
if arg.DefaultValue != nil {
|
||||
newArg.Default, err = arg.DefaultValue.Value(nil)
|
||||
if err != nil {
|
||||
return nil, errors.Errorf("default value is not valid: %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
return &newArg, nil
|
||||
}
|
||||
|
||||
func (b *builder) bindArgs(field *Field, params *types.Tuple) error {
|
||||
var newArgs []*FieldArgument
|
||||
|
||||
nextArg:
|
||||
for j := 0; j < params.Len(); j++ {
|
||||
param := params.At(j)
|
||||
for _, oldArg := range field.Args {
|
||||
if strings.EqualFold(oldArg.Name, param.Name()) {
|
||||
tr, err := b.Binder.TypeReference(oldArg.Type, param.Type())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
oldArg.TypeReference = tr
|
||||
|
||||
newArgs = append(newArgs, oldArg)
|
||||
continue nextArg
|
||||
}
|
||||
}
|
||||
|
||||
// no matching arg found, abort
|
||||
return fmt.Errorf("arg %s not in schema", param.Name())
|
||||
}
|
||||
|
||||
field.Args = newArgs
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Data) Args() map[string][]*FieldArgument {
|
||||
ret := map[string][]*FieldArgument{}
|
||||
for _, o := range a.Objects {
|
||||
for _, f := range o.Fields {
|
||||
if len(f.Args) > 0 {
|
||||
ret[f.ArgsFunc()] = f.Args
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, d := range a.Directives {
|
||||
if len(d.Args) > 0 {
|
||||
ret[d.ArgsFunc()] = d.Args
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
43
vendor/github.com/99designs/gqlgen/codegen/args.gotpl
generated
vendored
43
vendor/github.com/99designs/gqlgen/codegen/args.gotpl
generated
vendored
|
|
@ -1,43 +0,0 @@
|
|||
{{ range $name, $args := .Args }}
|
||||
func (ec *executionContext) {{ $name }}(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
||||
var err error
|
||||
args := map[string]interface{}{}
|
||||
{{- range $i, $arg := . }}
|
||||
var arg{{$i}} {{ $arg.TypeReference.GO | ref}}
|
||||
if tmp, ok := rawArgs[{{$arg.Name|quote}}]; ok {
|
||||
{{- if $arg.Directives }}
|
||||
getArg0 := func(ctx context.Context) (interface{}, error) { return ec.{{ $arg.TypeReference.UnmarshalFunc }}(ctx, tmp) }
|
||||
|
||||
{{- range $i, $directive := $arg.Directives }}
|
||||
getArg{{add $i 1}} := func(ctx context.Context) (res interface{}, err error) {
|
||||
{{- range $dArg := $directive.Args }}
|
||||
{{- if and $dArg.TypeReference.IsPtr ( notNil "Value" $dArg ) }}
|
||||
{{ $dArg.VarName }} := {{ $dArg.Value | dump }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
n := getArg{{$i}}
|
||||
return ec.directives.{{$directive.Name|ucFirst}}({{$directive.ResolveArgs "tmp" "n" }})
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
tmp, err = getArg{{$arg.Directives|len}}(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if data, ok := tmp.({{ $arg.TypeReference.GO | ref }}) ; ok {
|
||||
arg{{$i}} = data
|
||||
} else {
|
||||
return nil, fmt.Errorf(`unexpected type %T from directive, should be {{ $arg.TypeReference.GO }}`, tmp)
|
||||
}
|
||||
{{- else }}
|
||||
arg{{$i}}, err = ec.{{ $arg.TypeReference.UnmarshalFunc }}(ctx, tmp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
{{- end }}
|
||||
}
|
||||
args[{{$arg.Name|quote}}] = arg{{$i}}
|
||||
{{- end }}
|
||||
return args, nil
|
||||
}
|
||||
{{ end }}
|
||||
11
vendor/github.com/99designs/gqlgen/codegen/complexity.go
generated
vendored
11
vendor/github.com/99designs/gqlgen/codegen/complexity.go
generated
vendored
|
|
@ -1,11 +0,0 @@
|
|||
package codegen
|
||||
|
||||
func (o *Object) UniqueFields() map[string][]*Field {
|
||||
m := map[string][]*Field{}
|
||||
|
||||
for _, f := range o.Fields {
|
||||
m[f.GoFieldName] = append(m[f.GoFieldName], f)
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
436
vendor/github.com/99designs/gqlgen/codegen/config/binder.go
generated
vendored
436
vendor/github.com/99designs/gqlgen/codegen/config/binder.go
generated
vendored
|
|
@ -1,436 +0,0 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/token"
|
||||
"go/types"
|
||||
|
||||
"github.com/99designs/gqlgen/codegen/templates"
|
||||
"github.com/99designs/gqlgen/internal/code"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/vektah/gqlparser/ast"
|
||||
"golang.org/x/tools/go/packages"
|
||||
)
|
||||
|
||||
// Binder connects graphql types to golang types using static analysis
|
||||
type Binder struct {
|
||||
pkgs []*packages.Package
|
||||
schema *ast.Schema
|
||||
cfg *Config
|
||||
References []*TypeReference
|
||||
}
|
||||
|
||||
func (c *Config) NewBinder(s *ast.Schema) (*Binder, error) {
|
||||
pkgs, err := packages.Load(&packages.Config{Mode: packages.LoadTypes | packages.LoadSyntax}, c.Models.ReferencedPackages()...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, p := range pkgs {
|
||||
for _, e := range p.Errors {
|
||||
if e.Kind == packages.ListError {
|
||||
return nil, p.Errors[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &Binder{
|
||||
pkgs: pkgs,
|
||||
schema: s,
|
||||
cfg: c,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (b *Binder) TypePosition(typ types.Type) token.Position {
|
||||
named, isNamed := typ.(*types.Named)
|
||||
if !isNamed {
|
||||
return token.Position{
|
||||
Filename: "unknown",
|
||||
}
|
||||
}
|
||||
|
||||
return b.ObjectPosition(named.Obj())
|
||||
}
|
||||
|
||||
func (b *Binder) ObjectPosition(typ types.Object) token.Position {
|
||||
if typ == nil {
|
||||
return token.Position{
|
||||
Filename: "unknown",
|
||||
}
|
||||
}
|
||||
pkg := b.getPkg(typ.Pkg().Path())
|
||||
return pkg.Fset.Position(typ.Pos())
|
||||
}
|
||||
|
||||
func (b *Binder) FindType(pkgName string, typeName string) (types.Type, error) {
|
||||
obj, err := b.FindObject(pkgName, typeName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if fun, isFunc := obj.(*types.Func); isFunc {
|
||||
return fun.Type().(*types.Signature).Params().At(0).Type(), nil
|
||||
}
|
||||
return obj.Type(), nil
|
||||
}
|
||||
|
||||
func (b *Binder) getPkg(find string) *packages.Package {
|
||||
for _, p := range b.pkgs {
|
||||
if code.NormalizeVendor(find) == code.NormalizeVendor(p.PkgPath) {
|
||||
return p
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var MapType = types.NewMap(types.Typ[types.String], types.NewInterfaceType(nil, nil).Complete())
|
||||
var InterfaceType = types.NewInterfaceType(nil, nil)
|
||||
|
||||
func (b *Binder) DefaultUserObject(name string) (types.Type, error) {
|
||||
models := b.cfg.Models[name].Model
|
||||
if len(models) == 0 {
|
||||
return nil, fmt.Errorf(name + " not found in typemap")
|
||||
}
|
||||
|
||||
if models[0] == "map[string]interface{}" {
|
||||
return MapType, nil
|
||||
}
|
||||
|
||||
if models[0] == "interface{}" {
|
||||
return InterfaceType, nil
|
||||
}
|
||||
|
||||
pkgName, typeName := code.PkgAndType(models[0])
|
||||
if pkgName == "" {
|
||||
return nil, fmt.Errorf("missing package name for %s", name)
|
||||
}
|
||||
|
||||
obj, err := b.FindObject(pkgName, typeName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return obj.Type(), nil
|
||||
}
|
||||
|
||||
func (b *Binder) FindObject(pkgName string, typeName string) (types.Object, error) {
|
||||
if pkgName == "" {
|
||||
return nil, fmt.Errorf("package cannot be nil")
|
||||
}
|
||||
fullName := typeName
|
||||
if pkgName != "" {
|
||||
fullName = pkgName + "." + typeName
|
||||
}
|
||||
|
||||
pkg := b.getPkg(pkgName)
|
||||
if pkg == nil {
|
||||
return nil, errors.Errorf("required package was not loaded: %s", fullName)
|
||||
}
|
||||
|
||||
// function based marshalers take precedence
|
||||
for astNode, def := range pkg.TypesInfo.Defs {
|
||||
// only look at defs in the top scope
|
||||
if def == nil || def.Parent() == nil || def.Parent() != pkg.Types.Scope() {
|
||||
continue
|
||||
}
|
||||
|
||||
if astNode.Name == "Marshal"+typeName {
|
||||
return def, nil
|
||||
}
|
||||
}
|
||||
|
||||
// then look for types directly
|
||||
for astNode, def := range pkg.TypesInfo.Defs {
|
||||
// only look at defs in the top scope
|
||||
if def == nil || def.Parent() == nil || def.Parent() != pkg.Types.Scope() {
|
||||
continue
|
||||
}
|
||||
|
||||
if astNode.Name == typeName {
|
||||
return def, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, errors.Errorf("unable to find type %s\n", fullName)
|
||||
}
|
||||
|
||||
func (b *Binder) PointerTo(ref *TypeReference) *TypeReference {
|
||||
newRef := &TypeReference{
|
||||
GO: types.NewPointer(ref.GO),
|
||||
GQL: ref.GQL,
|
||||
CastType: ref.CastType,
|
||||
Definition: ref.Definition,
|
||||
Unmarshaler: ref.Unmarshaler,
|
||||
Marshaler: ref.Marshaler,
|
||||
IsMarshaler: ref.IsMarshaler,
|
||||
}
|
||||
|
||||
b.References = append(b.References, newRef)
|
||||
return newRef
|
||||
}
|
||||
|
||||
// TypeReference is used by args and field types. The Definition can refer to both input and output types.
|
||||
type TypeReference struct {
|
||||
Definition *ast.Definition
|
||||
GQL *ast.Type
|
||||
GO types.Type
|
||||
CastType types.Type // Before calling marshalling functions cast from/to this base type
|
||||
Marshaler *types.Func // When using external marshalling functions this will point to the Marshal function
|
||||
Unmarshaler *types.Func // When using external marshalling functions this will point to the Unmarshal function
|
||||
IsMarshaler bool // Does the type implement graphql.Marshaler and graphql.Unmarshaler
|
||||
}
|
||||
|
||||
func (ref *TypeReference) Elem() *TypeReference {
|
||||
if p, isPtr := ref.GO.(*types.Pointer); isPtr {
|
||||
return &TypeReference{
|
||||
GO: p.Elem(),
|
||||
GQL: ref.GQL,
|
||||
CastType: ref.CastType,
|
||||
Definition: ref.Definition,
|
||||
Unmarshaler: ref.Unmarshaler,
|
||||
Marshaler: ref.Marshaler,
|
||||
IsMarshaler: ref.IsMarshaler,
|
||||
}
|
||||
}
|
||||
|
||||
if ref.IsSlice() {
|
||||
return &TypeReference{
|
||||
GO: ref.GO.(*types.Slice).Elem(),
|
||||
GQL: ref.GQL.Elem,
|
||||
CastType: ref.CastType,
|
||||
Definition: ref.Definition,
|
||||
Unmarshaler: ref.Unmarshaler,
|
||||
Marshaler: ref.Marshaler,
|
||||
IsMarshaler: ref.IsMarshaler,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *TypeReference) IsPtr() bool {
|
||||
_, isPtr := t.GO.(*types.Pointer)
|
||||
return isPtr
|
||||
}
|
||||
|
||||
func (t *TypeReference) IsNilable() bool {
|
||||
_, isPtr := t.GO.(*types.Pointer)
|
||||
_, isMap := t.GO.(*types.Map)
|
||||
_, isInterface := t.GO.(*types.Interface)
|
||||
return isPtr || isMap || isInterface
|
||||
}
|
||||
|
||||
func (t *TypeReference) IsSlice() bool {
|
||||
_, isSlice := t.GO.(*types.Slice)
|
||||
return t.GQL.Elem != nil && isSlice
|
||||
}
|
||||
|
||||
func (t *TypeReference) IsNamed() bool {
|
||||
_, isSlice := t.GO.(*types.Named)
|
||||
return isSlice
|
||||
}
|
||||
|
||||
func (t *TypeReference) IsStruct() bool {
|
||||
_, isStruct := t.GO.Underlying().(*types.Struct)
|
||||
return isStruct
|
||||
}
|
||||
|
||||
func (t *TypeReference) IsScalar() bool {
|
||||
return t.Definition.Kind == ast.Scalar
|
||||
}
|
||||
|
||||
func (t *TypeReference) UniquenessKey() string {
|
||||
var nullability = "O"
|
||||
if t.GQL.NonNull {
|
||||
nullability = "N"
|
||||
}
|
||||
|
||||
return nullability + t.Definition.Name + "2" + templates.TypeIdentifier(t.GO)
|
||||
}
|
||||
|
||||
func (t *TypeReference) MarshalFunc() string {
|
||||
if t.Definition == nil {
|
||||
panic(errors.New("Definition missing for " + t.GQL.Name()))
|
||||
}
|
||||
|
||||
if t.Definition.Kind == ast.InputObject {
|
||||
return ""
|
||||
}
|
||||
|
||||
return "marshal" + t.UniquenessKey()
|
||||
}
|
||||
|
||||
func (t *TypeReference) UnmarshalFunc() string {
|
||||
if t.Definition == nil {
|
||||
panic(errors.New("Definition missing for " + t.GQL.Name()))
|
||||
}
|
||||
|
||||
if !t.Definition.IsInputType() {
|
||||
return ""
|
||||
}
|
||||
|
||||
return "unmarshal" + t.UniquenessKey()
|
||||
}
|
||||
|
||||
func (b *Binder) PushRef(ret *TypeReference) {
|
||||
b.References = append(b.References, ret)
|
||||
}
|
||||
|
||||
func isMap(t types.Type) bool {
|
||||
if t == nil {
|
||||
return true
|
||||
}
|
||||
_, ok := t.(*types.Map)
|
||||
return ok
|
||||
}
|
||||
|
||||
func isIntf(t types.Type) bool {
|
||||
if t == nil {
|
||||
return true
|
||||
}
|
||||
_, ok := t.(*types.Interface)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (b *Binder) TypeReference(schemaType *ast.Type, bindTarget types.Type) (ret *TypeReference, err error) {
|
||||
var pkgName, typeName string
|
||||
def := b.schema.Types[schemaType.Name()]
|
||||
defer func() {
|
||||
if err == nil && ret != nil {
|
||||
b.PushRef(ret)
|
||||
}
|
||||
}()
|
||||
|
||||
if len(b.cfg.Models[schemaType.Name()].Model) == 0 {
|
||||
return nil, fmt.Errorf("%s was not found", schemaType.Name())
|
||||
}
|
||||
|
||||
for _, model := range b.cfg.Models[schemaType.Name()].Model {
|
||||
if model == "map[string]interface{}" {
|
||||
if !isMap(bindTarget) {
|
||||
continue
|
||||
}
|
||||
return &TypeReference{
|
||||
Definition: def,
|
||||
GQL: schemaType,
|
||||
GO: MapType,
|
||||
}, nil
|
||||
}
|
||||
|
||||
if model == "interface{}" {
|
||||
if !isIntf(bindTarget) {
|
||||
continue
|
||||
}
|
||||
return &TypeReference{
|
||||
Definition: def,
|
||||
GQL: schemaType,
|
||||
GO: InterfaceType,
|
||||
}, nil
|
||||
}
|
||||
|
||||
pkgName, typeName = code.PkgAndType(model)
|
||||
if pkgName == "" {
|
||||
return nil, fmt.Errorf("missing package name for %s", schemaType.Name())
|
||||
}
|
||||
|
||||
ref := &TypeReference{
|
||||
Definition: def,
|
||||
GQL: schemaType,
|
||||
}
|
||||
|
||||
obj, err := b.FindObject(pkgName, typeName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if fun, isFunc := obj.(*types.Func); isFunc {
|
||||
ref.GO = fun.Type().(*types.Signature).Params().At(0).Type()
|
||||
ref.Marshaler = fun
|
||||
ref.Unmarshaler = types.NewFunc(0, fun.Pkg(), "Unmarshal"+typeName, nil)
|
||||
} else if hasMethod(obj.Type(), "MarshalGQL") && hasMethod(obj.Type(), "UnmarshalGQL") {
|
||||
ref.GO = obj.Type()
|
||||
ref.IsMarshaler = true
|
||||
} else if underlying := basicUnderlying(obj.Type()); def.IsLeafType() && underlying != nil && underlying.Kind() == types.String {
|
||||
// Special case for named types wrapping strings. Used by default enum implementations.
|
||||
|
||||
ref.GO = obj.Type()
|
||||
ref.CastType = underlying
|
||||
|
||||
underlyingRef, err := b.TypeReference(&ast.Type{NamedType: "String"}, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ref.Marshaler = underlyingRef.Marshaler
|
||||
ref.Unmarshaler = underlyingRef.Unmarshaler
|
||||
} else {
|
||||
ref.GO = obj.Type()
|
||||
}
|
||||
|
||||
ref.GO = b.CopyModifiersFromAst(schemaType, ref.GO)
|
||||
|
||||
if bindTarget != nil {
|
||||
if err = code.CompatibleTypes(ref.GO, bindTarget); err != nil {
|
||||
continue
|
||||
}
|
||||
ref.GO = bindTarget
|
||||
}
|
||||
|
||||
return ref, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("%s has type compatible with %s", schemaType.Name(), bindTarget.String())
|
||||
}
|
||||
|
||||
func (b *Binder) CopyModifiersFromAst(t *ast.Type, base types.Type) types.Type {
|
||||
if t.Elem != nil {
|
||||
child := b.CopyModifiersFromAst(t.Elem, base)
|
||||
if _, isStruct := child.Underlying().(*types.Struct); isStruct {
|
||||
child = types.NewPointer(child)
|
||||
}
|
||||
return types.NewSlice(child)
|
||||
}
|
||||
|
||||
var isInterface bool
|
||||
if named, ok := base.(*types.Named); ok {
|
||||
_, isInterface = named.Underlying().(*types.Interface)
|
||||
}
|
||||
|
||||
if !isInterface && !t.NonNull {
|
||||
return types.NewPointer(base)
|
||||
}
|
||||
|
||||
return base
|
||||
}
|
||||
|
||||
func hasMethod(it types.Type, name string) bool {
|
||||
if ptr, isPtr := it.(*types.Pointer); isPtr {
|
||||
it = ptr.Elem()
|
||||
}
|
||||
namedType, ok := it.(*types.Named)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := 0; i < namedType.NumMethods(); i++ {
|
||||
if namedType.Method(i).Name() == name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func basicUnderlying(it types.Type) *types.Basic {
|
||||
if ptr, isPtr := it.(*types.Pointer); isPtr {
|
||||
it = ptr.Elem()
|
||||
}
|
||||
namedType, ok := it.(*types.Named)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
if basic, ok := namedType.Underlying().(*types.Basic); ok {
|
||||
return basic
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
410
vendor/github.com/99designs/gqlgen/codegen/config/config.go
generated
vendored
410
vendor/github.com/99designs/gqlgen/codegen/config/config.go
generated
vendored
|
|
@ -1,410 +0,0 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/types"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/99designs/gqlgen/internal/code"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/vektah/gqlparser"
|
||||
"github.com/vektah/gqlparser/ast"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
SchemaFilename StringList `yaml:"schema,omitempty"`
|
||||
Exec PackageConfig `yaml:"exec"`
|
||||
Model PackageConfig `yaml:"model"`
|
||||
Resolver PackageConfig `yaml:"resolver,omitempty"`
|
||||
Models TypeMap `yaml:"models,omitempty"`
|
||||
StructTag string `yaml:"struct_tag,omitempty"`
|
||||
}
|
||||
|
||||
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: PackageConfig{Filename: "generated.go"},
|
||||
}
|
||||
}
|
||||
|
||||
// LoadConfigFromDefaultLocations looks for a config file in the current directory, and all parent directories
|
||||
// walking up the tree. The closest config file will be returned.
|
||||
func LoadConfigFromDefaultLocations() (*Config, error) {
|
||||
cfgFile, err := findCfg()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = os.Chdir(filepath.Dir(cfgFile))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to enter config dir")
|
||||
}
|
||||
return LoadConfig(cfgFile)
|
||||
}
|
||||
|
||||
// LoadConfig reads the gqlgen.yml config file
|
||||
func LoadConfig(filename string) (*Config, error) {
|
||||
config := DefaultConfig()
|
||||
|
||||
b, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to read config")
|
||||
}
|
||||
|
||||
if err := yaml.UnmarshalStrict(b, config); err != nil {
|
||||
return nil, errors.Wrap(err, "unable to parse config")
|
||||
}
|
||||
|
||||
preGlobbing := config.SchemaFilename
|
||||
config.SchemaFilename = StringList{}
|
||||
for _, f := range preGlobbing {
|
||||
matches, err := filepath.Glob(f)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to glob schema filename %s", f)
|
||||
}
|
||||
|
||||
for _, m := range matches {
|
||||
if config.SchemaFilename.Has(m) {
|
||||
continue
|
||||
}
|
||||
config.SchemaFilename = append(config.SchemaFilename, m)
|
||||
}
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
type PackageConfig struct {
|
||||
Filename string `yaml:"filename,omitempty"`
|
||||
Package string `yaml:"package,omitempty"`
|
||||
Type string `yaml:"type,omitempty"`
|
||||
}
|
||||
|
||||
type TypeMapEntry struct {
|
||||
Model StringList `yaml:"model"`
|
||||
Fields map[string]TypeMapField `yaml:"fields,omitempty"`
|
||||
}
|
||||
|
||||
type TypeMapField struct {
|
||||
Resolver bool `yaml:"resolver"`
|
||||
FieldName string `yaml:"fieldName"`
|
||||
}
|
||||
|
||||
type StringList []string
|
||||
|
||||
func (a *StringList) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||
var single string
|
||||
err := unmarshal(&single)
|
||||
if err == nil {
|
||||
*a = []string{single}
|
||||
return nil
|
||||
}
|
||||
|
||||
var multi []string
|
||||
err = unmarshal(&multi)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*a = multi
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a StringList) Has(file string) bool {
|
||||
for _, existing := range a {
|
||||
if existing == file {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *PackageConfig) normalize() error {
|
||||
if c.Filename == "" {
|
||||
return errors.New("Filename is required")
|
||||
}
|
||||
c.Filename = abs(c.Filename)
|
||||
// If Package is not set, first attempt to load the package at the output dir. If that fails
|
||||
// fallback to just the base dir name of the output filename.
|
||||
if c.Package == "" {
|
||||
c.Package = code.NameForDir(c.Dir())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *PackageConfig) ImportPath() string {
|
||||
return code.ImportPathForDir(c.Dir())
|
||||
}
|
||||
|
||||
func (c *PackageConfig) Dir() string {
|
||||
return filepath.Dir(c.Filename)
|
||||
}
|
||||
|
||||
func (c *PackageConfig) Check() error {
|
||||
if strings.ContainsAny(c.Package, "./\\") {
|
||||
return fmt.Errorf("package should be the output package name only, do not include the output filename")
|
||||
}
|
||||
if c.Filename != "" && !strings.HasSuffix(c.Filename, ".go") {
|
||||
return fmt.Errorf("filename should be path to a go source file")
|
||||
}
|
||||
|
||||
return c.normalize()
|
||||
}
|
||||
|
||||
func (c *PackageConfig) Pkg() *types.Package {
|
||||
return types.NewPackage(c.ImportPath(), c.Dir())
|
||||
}
|
||||
|
||||
func (c *PackageConfig) IsDefined() bool {
|
||||
return c.Filename != ""
|
||||
}
|
||||
|
||||
func (c *Config) Check() error {
|
||||
if err := c.Models.Check(); err != nil {
|
||||
return errors.Wrap(err, "config.models")
|
||||
}
|
||||
if err := c.Exec.Check(); err != nil {
|
||||
return errors.Wrap(err, "config.exec")
|
||||
}
|
||||
if err := c.Model.Check(); err != nil {
|
||||
return errors.Wrap(err, "config.model")
|
||||
}
|
||||
if c.Resolver.IsDefined() {
|
||||
if err := c.Resolver.Check(); err != nil {
|
||||
return errors.Wrap(err, "config.resolver")
|
||||
}
|
||||
}
|
||||
|
||||
// check packages names against conflict, if present in the same dir
|
||||
// and check filenames for uniqueness
|
||||
packageConfigList := []PackageConfig{
|
||||
c.Model,
|
||||
c.Exec,
|
||||
c.Resolver,
|
||||
}
|
||||
filesMap := make(map[string]bool)
|
||||
pkgConfigsByDir := make(map[string]PackageConfig)
|
||||
for _, current := range packageConfigList {
|
||||
_, fileFound := filesMap[current.Filename]
|
||||
if fileFound {
|
||||
return fmt.Errorf("filename %s defined more than once", current.Filename)
|
||||
}
|
||||
filesMap[current.Filename] = true
|
||||
previous, inSameDir := pkgConfigsByDir[current.Dir()]
|
||||
if inSameDir && current.Package != previous.Package {
|
||||
return fmt.Errorf("filenames %s and %s are in the same directory but have different package definitions", stripPath(current.Filename), stripPath(previous.Filename))
|
||||
}
|
||||
pkgConfigsByDir[current.Dir()] = current
|
||||
}
|
||||
|
||||
return c.normalize()
|
||||
}
|
||||
|
||||
func stripPath(path string) string {
|
||||
return filepath.Base(path)
|
||||
}
|
||||
|
||||
type TypeMap map[string]TypeMapEntry
|
||||
|
||||
func (tm TypeMap) Exists(typeName string) bool {
|
||||
_, ok := tm[typeName]
|
||||
return ok
|
||||
}
|
||||
|
||||
func (tm TypeMap) UserDefined(typeName string) bool {
|
||||
m, ok := tm[typeName]
|
||||
return ok && len(m.Model) > 0
|
||||
}
|
||||
|
||||
func (tm TypeMap) Check() error {
|
||||
for typeName, entry := range tm {
|
||||
for _, model := range entry.Model {
|
||||
if strings.LastIndex(model, ".") < strings.LastIndex(model, "/") {
|
||||
return fmt.Errorf("model %s: invalid type specifier \"%s\" - you need to specify a struct to map to", typeName, entry.Model)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tm TypeMap) ReferencedPackages() []string {
|
||||
var pkgs []string
|
||||
|
||||
for _, typ := range tm {
|
||||
for _, model := range typ.Model {
|
||||
if model == "map[string]interface{}" || model == "interface{}" {
|
||||
continue
|
||||
}
|
||||
pkg, _ := code.PkgAndType(model)
|
||||
if pkg == "" || inStrSlice(pkgs, pkg) {
|
||||
continue
|
||||
}
|
||||
pkgs = append(pkgs, code.QualifyPackagePath(pkg))
|
||||
}
|
||||
}
|
||||
|
||||
sort.Slice(pkgs, func(i, j int) bool {
|
||||
return pkgs[i] > pkgs[j]
|
||||
})
|
||||
return pkgs
|
||||
}
|
||||
|
||||
func (tm TypeMap) Add(Name string, goType string) {
|
||||
modelCfg := tm[Name]
|
||||
modelCfg.Model = append(modelCfg.Model, goType)
|
||||
tm[Name] = modelCfg
|
||||
}
|
||||
|
||||
func inStrSlice(haystack []string, needle string) bool {
|
||||
for _, v := range haystack {
|
||||
if needle == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// findCfg searches for the config file in this directory and all parents up the tree
|
||||
// looking for the closest match
|
||||
func findCfg() (string, error) {
|
||||
dir, err := os.Getwd()
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "unable to get working dir to findCfg")
|
||||
}
|
||||
|
||||
cfg := findCfgInDir(dir)
|
||||
|
||||
for cfg == "" && dir != filepath.Dir(dir) {
|
||||
dir = filepath.Dir(dir)
|
||||
cfg = findCfgInDir(dir)
|
||||
}
|
||||
|
||||
if cfg == "" {
|
||||
return "", os.ErrNotExist
|
||||
}
|
||||
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func findCfgInDir(dir string) string {
|
||||
for _, cfgName := range cfgFilenames {
|
||||
path := filepath.Join(dir, cfgName)
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
return path
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (c *Config) normalize() error {
|
||||
if err := c.Model.normalize(); err != nil {
|
||||
return errors.Wrap(err, "model")
|
||||
}
|
||||
|
||||
if err := c.Exec.normalize(); err != nil {
|
||||
return errors.Wrap(err, "exec")
|
||||
}
|
||||
|
||||
if c.Resolver.IsDefined() {
|
||||
if err := c.Resolver.normalize(); err != nil {
|
||||
return errors.Wrap(err, "resolver")
|
||||
}
|
||||
}
|
||||
|
||||
if c.Models == nil {
|
||||
c.Models = TypeMap{}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) InjectBuiltins(s *ast.Schema) {
|
||||
builtins := TypeMap{
|
||||
"__Directive": {Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.Directive"}},
|
||||
"__DirectiveLocation": {Model: StringList{"github.com/99designs/gqlgen/graphql.String"}},
|
||||
"__Type": {Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.Type"}},
|
||||
"__TypeKind": {Model: StringList{"github.com/99designs/gqlgen/graphql.String"}},
|
||||
"__Field": {Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.Field"}},
|
||||
"__EnumValue": {Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.EnumValue"}},
|
||||
"__InputValue": {Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.InputValue"}},
|
||||
"__Schema": {Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.Schema"}},
|
||||
"Float": {Model: StringList{"github.com/99designs/gqlgen/graphql.Float"}},
|
||||
"String": {Model: StringList{"github.com/99designs/gqlgen/graphql.String"}},
|
||||
"Boolean": {Model: StringList{"github.com/99designs/gqlgen/graphql.Boolean"}},
|
||||
"Int": {Model: StringList{
|
||||
"github.com/99designs/gqlgen/graphql.Int",
|
||||
"github.com/99designs/gqlgen/graphql.Int32",
|
||||
"github.com/99designs/gqlgen/graphql.Int64",
|
||||
}},
|
||||
"ID": {
|
||||
Model: StringList{
|
||||
"github.com/99designs/gqlgen/graphql.ID",
|
||||
"github.com/99designs/gqlgen/graphql.IntID",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for typeName, entry := range builtins {
|
||||
if !c.Models.Exists(typeName) {
|
||||
c.Models[typeName] = entry
|
||||
}
|
||||
}
|
||||
|
||||
// These are additional types that are injected if defined in the schema as scalars.
|
||||
extraBuiltins := TypeMap{
|
||||
"Time": {Model: StringList{"github.com/99designs/gqlgen/graphql.Time"}},
|
||||
"Map": {Model: StringList{"github.com/99designs/gqlgen/graphql.Map"}},
|
||||
"Upload": {Model: StringList{"github.com/99designs/gqlgen/graphql.Upload"}},
|
||||
"Any": {Model: StringList{"github.com/99designs/gqlgen/graphql.Any"}},
|
||||
}
|
||||
|
||||
for typeName, entry := range extraBuiltins {
|
||||
if t, ok := s.Types[typeName]; !c.Models.Exists(typeName) && ok && t.Kind == ast.Scalar {
|
||||
c.Models[typeName] = entry
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Config) LoadSchema() (*ast.Schema, map[string]string, error) {
|
||||
schemaStrings := map[string]string{}
|
||||
|
||||
var sources []*ast.Source
|
||||
|
||||
for _, filename := range c.SchemaFilename {
|
||||
filename = filepath.ToSlash(filename)
|
||||
var err error
|
||||
var schemaRaw []byte
|
||||
schemaRaw, err = ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "unable to open schema: "+err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
schemaStrings[filename] = string(schemaRaw)
|
||||
sources = append(sources, &ast.Source{Name: filename, Input: schemaStrings[filename]})
|
||||
}
|
||||
|
||||
schema, err := gqlparser.LoadSchema(sources...)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return schema, schemaStrings, nil
|
||||
}
|
||||
|
||||
func abs(path string) string {
|
||||
absPath, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return filepath.ToSlash(absPath)
|
||||
}
|
||||
168
vendor/github.com/99designs/gqlgen/codegen/data.go
generated
vendored
168
vendor/github.com/99designs/gqlgen/codegen/data.go
generated
vendored
|
|
@ -1,168 +0,0 @@
|
|||
package codegen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/99designs/gqlgen/codegen/config"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/vektah/gqlparser/ast"
|
||||
)
|
||||
|
||||
// Data is a unified model of the code to be generated. Plugins may modify this structure to do things like implement
|
||||
// resolvers or directives automatically (eg grpc, validation)
|
||||
type Data struct {
|
||||
Config *config.Config
|
||||
Schema *ast.Schema
|
||||
SchemaStr map[string]string
|
||||
Directives map[string]*Directive
|
||||
Objects Objects
|
||||
Inputs Objects
|
||||
Interfaces map[string]*Interface
|
||||
ReferencedTypes map[string]*config.TypeReference
|
||||
ComplexityRoots map[string]*Object
|
||||
|
||||
QueryRoot *Object
|
||||
MutationRoot *Object
|
||||
SubscriptionRoot *Object
|
||||
}
|
||||
|
||||
type builder struct {
|
||||
Config *config.Config
|
||||
Schema *ast.Schema
|
||||
SchemaStr map[string]string
|
||||
Binder *config.Binder
|
||||
Directives map[string]*Directive
|
||||
}
|
||||
|
||||
func BuildData(cfg *config.Config) (*Data, error) {
|
||||
b := builder{
|
||||
Config: cfg,
|
||||
}
|
||||
|
||||
var err error
|
||||
b.Schema, b.SchemaStr, err = cfg.LoadSchema()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = cfg.Check()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cfg.InjectBuiltins(b.Schema)
|
||||
|
||||
b.Binder, err = b.Config.NewBinder(b.Schema)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b.Directives, err = b.buildDirectives()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dataDirectives := make(map[string]*Directive)
|
||||
for name, d := range b.Directives {
|
||||
if !d.Builtin {
|
||||
dataDirectives[name] = d
|
||||
}
|
||||
}
|
||||
|
||||
s := Data{
|
||||
Config: cfg,
|
||||
Directives: dataDirectives,
|
||||
Schema: b.Schema,
|
||||
SchemaStr: b.SchemaStr,
|
||||
Interfaces: map[string]*Interface{},
|
||||
}
|
||||
|
||||
for _, schemaType := range b.Schema.Types {
|
||||
switch schemaType.Kind {
|
||||
case ast.Object:
|
||||
obj, err := b.buildObject(schemaType)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to build object definition")
|
||||
}
|
||||
|
||||
s.Objects = append(s.Objects, obj)
|
||||
case ast.InputObject:
|
||||
input, err := b.buildObject(schemaType)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to build input definition")
|
||||
}
|
||||
|
||||
s.Inputs = append(s.Inputs, input)
|
||||
|
||||
case ast.Union, ast.Interface:
|
||||
s.Interfaces[schemaType.Name] = b.buildInterface(schemaType)
|
||||
}
|
||||
}
|
||||
|
||||
if s.Schema.Query != nil {
|
||||
s.QueryRoot = s.Objects.ByName(s.Schema.Query.Name)
|
||||
} else {
|
||||
return nil, fmt.Errorf("query entry point missing")
|
||||
}
|
||||
|
||||
if s.Schema.Mutation != nil {
|
||||
s.MutationRoot = s.Objects.ByName(s.Schema.Mutation.Name)
|
||||
}
|
||||
|
||||
if s.Schema.Subscription != nil {
|
||||
s.SubscriptionRoot = s.Objects.ByName(s.Schema.Subscription.Name)
|
||||
}
|
||||
|
||||
if err := b.injectIntrospectionRoots(&s); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.ReferencedTypes, err = b.buildTypes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sort.Slice(s.Objects, func(i, j int) bool {
|
||||
return s.Objects[i].Definition.Name < s.Objects[j].Definition.Name
|
||||
})
|
||||
|
||||
sort.Slice(s.Inputs, func(i, j int) bool {
|
||||
return s.Inputs[i].Definition.Name < s.Inputs[j].Definition.Name
|
||||
})
|
||||
|
||||
return &s, nil
|
||||
}
|
||||
|
||||
func (b *builder) injectIntrospectionRoots(s *Data) error {
|
||||
obj := s.Objects.ByName(b.Schema.Query.Name)
|
||||
if obj == nil {
|
||||
return fmt.Errorf("root query type must be defined")
|
||||
}
|
||||
|
||||
__type, err := b.buildField(obj, &ast.FieldDefinition{
|
||||
Name: "__type",
|
||||
Type: ast.NamedType("__Type", nil),
|
||||
Arguments: []*ast.ArgumentDefinition{
|
||||
{
|
||||
Name: "name",
|
||||
Type: ast.NonNullNamedType("String", nil),
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
__schema, err := b.buildField(obj, &ast.FieldDefinition{
|
||||
Name: "__schema",
|
||||
Type: ast.NamedType("__Schema", nil),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
obj.Fields = append(obj.Fields, __type, __schema)
|
||||
|
||||
return nil
|
||||
}
|
||||
152
vendor/github.com/99designs/gqlgen/codegen/directive.go
generated
vendored
152
vendor/github.com/99designs/gqlgen/codegen/directive.go
generated
vendored
|
|
@ -1,152 +0,0 @@
|
|||
package codegen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/99designs/gqlgen/codegen/templates"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/vektah/gqlparser/ast"
|
||||
)
|
||||
|
||||
type Directive struct {
|
||||
Name string
|
||||
Args []*FieldArgument
|
||||
Builtin bool
|
||||
}
|
||||
|
||||
func (b *builder) buildDirectives() (map[string]*Directive, error) {
|
||||
directives := make(map[string]*Directive, len(b.Schema.Directives))
|
||||
|
||||
for name, dir := range b.Schema.Directives {
|
||||
if _, ok := directives[name]; ok {
|
||||
return nil, errors.Errorf("directive with name %s already exists", name)
|
||||
}
|
||||
|
||||
var builtin bool
|
||||
if name == "skip" || name == "include" || name == "deprecated" {
|
||||
builtin = true
|
||||
}
|
||||
|
||||
var args []*FieldArgument
|
||||
for _, arg := range dir.Arguments {
|
||||
tr, err := b.Binder.TypeReference(arg.Type, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newArg := &FieldArgument{
|
||||
ArgumentDefinition: arg,
|
||||
TypeReference: tr,
|
||||
VarName: templates.ToGoPrivate(arg.Name),
|
||||
}
|
||||
|
||||
if arg.DefaultValue != nil {
|
||||
var err error
|
||||
newArg.Default, err = arg.DefaultValue.Value(nil)
|
||||
if err != nil {
|
||||
return nil, errors.Errorf("default value for directive argument %s(%s) is not valid: %s", dir.Name, arg.Name, err.Error())
|
||||
}
|
||||
}
|
||||
args = append(args, newArg)
|
||||
}
|
||||
|
||||
directives[name] = &Directive{
|
||||
Name: name,
|
||||
Args: args,
|
||||
Builtin: builtin,
|
||||
}
|
||||
}
|
||||
|
||||
return directives, nil
|
||||
}
|
||||
|
||||
func (b *builder) getDirectives(list ast.DirectiveList) ([]*Directive, error) {
|
||||
dirs := make([]*Directive, len(list))
|
||||
for i, d := range list {
|
||||
argValues := make(map[string]interface{}, len(d.Arguments))
|
||||
for _, da := range d.Arguments {
|
||||
val, err := da.Value.Value(nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
argValues[da.Name] = val
|
||||
}
|
||||
def, ok := b.Directives[d.Name]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("directive %s not found", d.Name)
|
||||
}
|
||||
|
||||
var args []*FieldArgument
|
||||
for _, a := range def.Args {
|
||||
value := a.Default
|
||||
if argValue, ok := argValues[a.Name]; ok {
|
||||
value = argValue
|
||||
}
|
||||
args = append(args, &FieldArgument{
|
||||
ArgumentDefinition: a.ArgumentDefinition,
|
||||
Value: value,
|
||||
VarName: a.VarName,
|
||||
TypeReference: a.TypeReference,
|
||||
})
|
||||
}
|
||||
dirs[i] = &Directive{
|
||||
Name: d.Name,
|
||||
Args: args,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return dirs, nil
|
||||
}
|
||||
|
||||
func (d *Directive) ArgsFunc() string {
|
||||
if len(d.Args) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
return "dir_" + d.Name + "_args"
|
||||
}
|
||||
|
||||
func (d *Directive) CallArgs() string {
|
||||
args := []string{"ctx", "obj", "n"}
|
||||
|
||||
for _, arg := range d.Args {
|
||||
args = append(args, "args["+strconv.Quote(arg.Name)+"].("+templates.CurrentImports.LookupType(arg.TypeReference.GO)+")")
|
||||
}
|
||||
|
||||
return strings.Join(args, ", ")
|
||||
}
|
||||
|
||||
func (d *Directive) ResolveArgs(obj string, next string) string {
|
||||
args := []string{"ctx", obj, next}
|
||||
|
||||
for _, arg := range d.Args {
|
||||
dArg := "&" + arg.VarName
|
||||
if !arg.TypeReference.IsPtr() {
|
||||
if arg.Value != nil {
|
||||
dArg = templates.Dump(arg.Value)
|
||||
} else {
|
||||
dArg = templates.Dump(arg.Default)
|
||||
}
|
||||
} else if arg.Value == nil && arg.Default == nil {
|
||||
dArg = "nil"
|
||||
}
|
||||
|
||||
args = append(args, dArg)
|
||||
}
|
||||
|
||||
return strings.Join(args, ", ")
|
||||
}
|
||||
|
||||
func (d *Directive) Declaration() string {
|
||||
res := ucFirst(d.Name) + " func(ctx context.Context, obj interface{}, next graphql.Resolver"
|
||||
|
||||
for _, arg := range d.Args {
|
||||
res += fmt.Sprintf(", %s %s", arg.Name, templates.CurrentImports.LookupType(arg.TypeReference.GO))
|
||||
}
|
||||
|
||||
res += ") (res interface{}, err error)"
|
||||
return res
|
||||
}
|
||||
394
vendor/github.com/99designs/gqlgen/codegen/field.go
generated
vendored
394
vendor/github.com/99designs/gqlgen/codegen/field.go
generated
vendored
|
|
@ -1,394 +0,0 @@
|
|||
package codegen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/types"
|
||||
"log"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/99designs/gqlgen/codegen/config"
|
||||
"github.com/99designs/gqlgen/codegen/templates"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/vektah/gqlparser/ast"
|
||||
)
|
||||
|
||||
type Field struct {
|
||||
*ast.FieldDefinition
|
||||
|
||||
TypeReference *config.TypeReference
|
||||
GoFieldType GoFieldType // The field type in go, if any
|
||||
GoReceiverName string // The name of method & var receiver in go, if any
|
||||
GoFieldName string // The name of the method or var in go, if any
|
||||
IsResolver bool // Does this field need a resolver
|
||||
Args []*FieldArgument // A list of arguments to be passed to this field
|
||||
MethodHasContext bool // If this is bound to a go method, does the method also take a context
|
||||
NoErr bool // If this is bound to a go method, does that method have an error as the second argument
|
||||
Object *Object // A link back to the parent object
|
||||
Default interface{} // The default value
|
||||
Directives []*Directive
|
||||
}
|
||||
|
||||
func (b *builder) buildField(obj *Object, field *ast.FieldDefinition) (*Field, error) {
|
||||
dirs, err := b.getDirectives(field.Directives)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
f := Field{
|
||||
FieldDefinition: field,
|
||||
Object: obj,
|
||||
Directives: dirs,
|
||||
GoFieldName: templates.ToGo(field.Name),
|
||||
GoFieldType: GoFieldVariable,
|
||||
GoReceiverName: "obj",
|
||||
}
|
||||
|
||||
if field.DefaultValue != nil {
|
||||
var err error
|
||||
f.Default, err = field.DefaultValue.Value(nil)
|
||||
if err != nil {
|
||||
return nil, errors.Errorf("default value %s is not valid: %s", field.Name, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
for _, arg := range field.Arguments {
|
||||
newArg, err := b.buildArg(obj, arg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
f.Args = append(f.Args, newArg)
|
||||
}
|
||||
|
||||
if err = b.bindField(obj, &f); err != nil {
|
||||
f.IsResolver = true
|
||||
log.Println(err.Error())
|
||||
}
|
||||
|
||||
if f.IsResolver && !f.TypeReference.IsPtr() && f.TypeReference.IsStruct() {
|
||||
f.TypeReference = b.Binder.PointerTo(f.TypeReference)
|
||||
}
|
||||
|
||||
return &f, nil
|
||||
}
|
||||
|
||||
func (b *builder) bindField(obj *Object, f *Field) error {
|
||||
defer func() {
|
||||
if f.TypeReference == nil {
|
||||
tr, err := b.Binder.TypeReference(f.Type, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
f.TypeReference = tr
|
||||
}
|
||||
}()
|
||||
|
||||
switch {
|
||||
case f.Name == "__schema":
|
||||
f.GoFieldType = GoFieldMethod
|
||||
f.GoReceiverName = "ec"
|
||||
f.GoFieldName = "introspectSchema"
|
||||
return nil
|
||||
case f.Name == "__type":
|
||||
f.GoFieldType = GoFieldMethod
|
||||
f.GoReceiverName = "ec"
|
||||
f.GoFieldName = "introspectType"
|
||||
return nil
|
||||
case obj.Root:
|
||||
f.IsResolver = true
|
||||
return nil
|
||||
case b.Config.Models[obj.Name].Fields[f.Name].Resolver:
|
||||
f.IsResolver = true
|
||||
return nil
|
||||
case obj.Type == config.MapType:
|
||||
f.GoFieldType = GoFieldMap
|
||||
return nil
|
||||
case b.Config.Models[obj.Name].Fields[f.Name].FieldName != "":
|
||||
f.GoFieldName = b.Config.Models[obj.Name].Fields[f.Name].FieldName
|
||||
}
|
||||
|
||||
target, err := b.findBindTarget(obj.Type.(*types.Named), f.GoFieldName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pos := b.Binder.ObjectPosition(target)
|
||||
|
||||
switch target := target.(type) {
|
||||
case nil:
|
||||
objPos := b.Binder.TypePosition(obj.Type)
|
||||
return fmt.Errorf(
|
||||
"%s:%d adding resolver method for %s.%s, nothing matched",
|
||||
objPos.Filename,
|
||||
objPos.Line,
|
||||
obj.Name,
|
||||
f.Name,
|
||||
)
|
||||
|
||||
case *types.Func:
|
||||
sig := target.Type().(*types.Signature)
|
||||
if sig.Results().Len() == 1 {
|
||||
f.NoErr = true
|
||||
} else if sig.Results().Len() != 2 {
|
||||
return fmt.Errorf("method has wrong number of args")
|
||||
}
|
||||
params := sig.Params()
|
||||
// If the first argument is the context, remove it from the comparison and set
|
||||
// the MethodHasContext flag so that the context will be passed to this model's method
|
||||
if params.Len() > 0 && params.At(0).Type().String() == "context.Context" {
|
||||
f.MethodHasContext = true
|
||||
vars := make([]*types.Var, params.Len()-1)
|
||||
for i := 1; i < params.Len(); i++ {
|
||||
vars[i-1] = params.At(i)
|
||||
}
|
||||
params = types.NewTuple(vars...)
|
||||
}
|
||||
|
||||
if err = b.bindArgs(f, params); err != nil {
|
||||
return errors.Wrapf(err, "%s:%d", pos.Filename, pos.Line)
|
||||
}
|
||||
|
||||
result := sig.Results().At(0)
|
||||
tr, err := b.Binder.TypeReference(f.Type, result.Type())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// success, args and return type match. Bind to method
|
||||
f.GoFieldType = GoFieldMethod
|
||||
f.GoReceiverName = "obj"
|
||||
f.GoFieldName = target.Name()
|
||||
f.TypeReference = tr
|
||||
|
||||
return nil
|
||||
|
||||
case *types.Var:
|
||||
tr, err := b.Binder.TypeReference(f.Type, target.Type())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// success, bind to var
|
||||
f.GoFieldType = GoFieldVariable
|
||||
f.GoReceiverName = "obj"
|
||||
f.GoFieldName = target.Name()
|
||||
f.TypeReference = tr
|
||||
|
||||
return nil
|
||||
default:
|
||||
panic(fmt.Errorf("unknown bind target %T for %s", target, f.Name))
|
||||
}
|
||||
}
|
||||
|
||||
// findField attempts to match the name to a struct field with the following
|
||||
// priorites:
|
||||
// 1. Any method with a matching name
|
||||
// 2. Any Fields with a struct tag (see config.StructTag)
|
||||
// 3. Any fields with a matching name
|
||||
// 4. Same logic again for embedded fields
|
||||
func (b *builder) findBindTarget(named *types.Named, name string) (types.Object, error) {
|
||||
for i := 0; i < named.NumMethods(); i++ {
|
||||
method := named.Method(i)
|
||||
if !method.Exported() {
|
||||
continue
|
||||
}
|
||||
|
||||
if !strings.EqualFold(method.Name(), name) {
|
||||
continue
|
||||
}
|
||||
|
||||
return method, nil
|
||||
}
|
||||
|
||||
strukt, ok := named.Underlying().(*types.Struct)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("not a struct")
|
||||
}
|
||||
return b.findBindStructTarget(strukt, name)
|
||||
}
|
||||
|
||||
func (b *builder) findBindStructTarget(strukt *types.Struct, name string) (types.Object, error) {
|
||||
// struct tags have the highest priority
|
||||
if b.Config.StructTag != "" {
|
||||
var foundField *types.Var
|
||||
for i := 0; i < strukt.NumFields(); i++ {
|
||||
field := strukt.Field(i)
|
||||
if !field.Exported() {
|
||||
continue
|
||||
}
|
||||
tags := reflect.StructTag(strukt.Tag(i))
|
||||
if val, ok := tags.Lookup(b.Config.StructTag); ok && equalFieldName(val, name) {
|
||||
if foundField != nil {
|
||||
return nil, errors.Errorf("tag %s is ambigious; multiple fields have the same tag value of %s", b.Config.StructTag, val)
|
||||
}
|
||||
|
||||
foundField = field
|
||||
}
|
||||
}
|
||||
if foundField != nil {
|
||||
return foundField, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Then matching field names
|
||||
for i := 0; i < strukt.NumFields(); i++ {
|
||||
field := strukt.Field(i)
|
||||
if !field.Exported() {
|
||||
continue
|
||||
}
|
||||
if equalFieldName(field.Name(), name) { // aqui!
|
||||
return field, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Then look in embedded structs
|
||||
for i := 0; i < strukt.NumFields(); i++ {
|
||||
field := strukt.Field(i)
|
||||
if !field.Exported() {
|
||||
continue
|
||||
}
|
||||
|
||||
if !field.Anonymous() {
|
||||
continue
|
||||
}
|
||||
|
||||
fieldType := field.Type()
|
||||
if ptr, ok := fieldType.(*types.Pointer); ok {
|
||||
fieldType = ptr.Elem()
|
||||
}
|
||||
|
||||
switch fieldType := fieldType.(type) {
|
||||
case *types.Named:
|
||||
f, err := b.findBindTarget(fieldType, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if f != nil {
|
||||
return f, nil
|
||||
}
|
||||
case *types.Struct:
|
||||
f, err := b.findBindStructTarget(fieldType, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if f != nil {
|
||||
return f, nil
|
||||
}
|
||||
default:
|
||||
panic(fmt.Errorf("unknown embedded field type %T", field.Type()))
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (f *Field) HasDirectives() bool {
|
||||
return len(f.Directives) > 0
|
||||
}
|
||||
|
||||
func (f *Field) IsReserved() bool {
|
||||
return strings.HasPrefix(f.Name, "__")
|
||||
}
|
||||
|
||||
func (f *Field) IsMethod() bool {
|
||||
return f.GoFieldType == GoFieldMethod
|
||||
}
|
||||
|
||||
func (f *Field) IsVariable() bool {
|
||||
return f.GoFieldType == GoFieldVariable
|
||||
}
|
||||
|
||||
func (f *Field) IsMap() bool {
|
||||
return f.GoFieldType == GoFieldMap
|
||||
}
|
||||
|
||||
func (f *Field) IsConcurrent() bool {
|
||||
if f.Object.DisableConcurrency {
|
||||
return false
|
||||
}
|
||||
return f.MethodHasContext || f.IsResolver
|
||||
}
|
||||
|
||||
func (f *Field) GoNameUnexported() string {
|
||||
return templates.ToGoPrivate(f.Name)
|
||||
}
|
||||
|
||||
func (f *Field) ShortInvocation() string {
|
||||
return fmt.Sprintf("%s().%s(%s)", f.Object.Definition.Name, f.GoFieldName, f.CallArgs())
|
||||
}
|
||||
|
||||
func (f *Field) ArgsFunc() string {
|
||||
if len(f.Args) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
return "field_" + f.Object.Definition.Name + "_" + f.Name + "_args"
|
||||
}
|
||||
|
||||
func (f *Field) ResolverType() string {
|
||||
if !f.IsResolver {
|
||||
return ""
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s().%s(%s)", f.Object.Definition.Name, f.GoFieldName, f.CallArgs())
|
||||
}
|
||||
|
||||
func (f *Field) ShortResolverDeclaration() string {
|
||||
res := "(ctx context.Context"
|
||||
|
||||
if !f.Object.Root {
|
||||
res += fmt.Sprintf(", obj *%s", templates.CurrentImports.LookupType(f.Object.Type))
|
||||
}
|
||||
for _, arg := range f.Args {
|
||||
res += fmt.Sprintf(", %s %s", arg.VarName, templates.CurrentImports.LookupType(arg.TypeReference.GO))
|
||||
}
|
||||
|
||||
result := templates.CurrentImports.LookupType(f.TypeReference.GO)
|
||||
if f.Object.Stream {
|
||||
result = "<-chan " + result
|
||||
}
|
||||
|
||||
res += fmt.Sprintf(") (%s, error)", result)
|
||||
return res
|
||||
}
|
||||
|
||||
func (f *Field) ComplexitySignature() string {
|
||||
res := fmt.Sprintf("func(childComplexity int")
|
||||
for _, arg := range f.Args {
|
||||
res += fmt.Sprintf(", %s %s", arg.VarName, templates.CurrentImports.LookupType(arg.TypeReference.GO))
|
||||
}
|
||||
res += ") int"
|
||||
return res
|
||||
}
|
||||
|
||||
func (f *Field) ComplexityArgs() string {
|
||||
var args []string
|
||||
for _, arg := range f.Args {
|
||||
args = append(args, "args["+strconv.Quote(arg.Name)+"].("+templates.CurrentImports.LookupType(arg.TypeReference.GO)+")")
|
||||
}
|
||||
|
||||
return strings.Join(args, ", ")
|
||||
}
|
||||
|
||||
func (f *Field) CallArgs() string {
|
||||
var args []string
|
||||
|
||||
if f.IsResolver {
|
||||
args = append(args, "rctx")
|
||||
|
||||
if !f.Object.Root {
|
||||
args = append(args, "obj")
|
||||
}
|
||||
} else {
|
||||
if f.MethodHasContext {
|
||||
args = append(args, "ctx")
|
||||
}
|
||||
}
|
||||
|
||||
for _, arg := range f.Args {
|
||||
args = append(args, "args["+strconv.Quote(arg.Name)+"].("+templates.CurrentImports.LookupType(arg.TypeReference.GO)+")")
|
||||
}
|
||||
|
||||
return strings.Join(args, ", ")
|
||||
}
|
||||
100
vendor/github.com/99designs/gqlgen/codegen/field.gotpl
generated
vendored
100
vendor/github.com/99designs/gqlgen/codegen/field.gotpl
generated
vendored
|
|
@ -1,100 +0,0 @@
|
|||
{{- range $object := .Objects }}{{- range $field := $object.Fields }}
|
||||
|
||||
{{- if $object.Stream }}
|
||||
func (ec *executionContext) _{{$object.Name}}_{{$field.Name}}(ctx context.Context, field graphql.CollectedField) func() graphql.Marshaler {
|
||||
ctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{
|
||||
Field: field,
|
||||
Args: nil,
|
||||
})
|
||||
{{- if $field.Args }}
|
||||
rawArgs := field.ArgumentMap(ec.Variables)
|
||||
args, err := ec.{{ $field.ArgsFunc }}(ctx,rawArgs)
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return nil
|
||||
}
|
||||
{{- end }}
|
||||
// FIXME: subscriptions are missing request middleware stack https://github.com/99designs/gqlgen/issues/259
|
||||
// and Tracer stack
|
||||
rctx := ctx
|
||||
results, err := ec.resolvers.{{ $field.ShortInvocation }}
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return nil
|
||||
}
|
||||
return func() graphql.Marshaler {
|
||||
res, ok := <-results
|
||||
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{'}'})
|
||||
})
|
||||
}
|
||||
}
|
||||
{{ else }}
|
||||
func (ec *executionContext) _{{$object.Name}}_{{$field.Name}}(ctx context.Context, field graphql.CollectedField{{ if not $object.Root }}, obj {{$object.Reference | ref}}{{end}}) graphql.Marshaler {
|
||||
ctx = ec.Tracer.StartFieldExecution(ctx, field)
|
||||
defer func () { ec.Tracer.EndFieldExecution(ctx) }()
|
||||
rctx := &graphql.ResolverContext{
|
||||
Object: {{$object.Name|quote}},
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: {{or $field.IsMethod $field.IsResolver}},
|
||||
}
|
||||
ctx = graphql.WithResolverContext(ctx, rctx)
|
||||
{{- if $field.Args }}
|
||||
rawArgs := field.ArgumentMap(ec.Variables)
|
||||
args, err := ec.{{ $field.ArgsFunc }}(ctx,rawArgs)
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
rctx.Args = args
|
||||
{{- end }}
|
||||
ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
|
||||
resTmp := ec.FieldMiddleware(ctx, {{if $object.Root}}nil{{else}}obj{{end}}, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
{{- if $field.IsResolver }}
|
||||
return ec.resolvers.{{ $field.ShortInvocation }}
|
||||
{{- else if $field.IsMap }}
|
||||
switch v := {{$field.GoReceiverName}}[{{$field.Name|quote}}].(type) {
|
||||
case {{$field.TypeReference.GO | ref}}:
|
||||
return v, nil
|
||||
case {{$field.TypeReference.Elem.GO | ref}}:
|
||||
return &v, nil
|
||||
case nil:
|
||||
return ({{$field.TypeReference.GO | ref}})(nil), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unexpected type %T for field %s", v, {{ $field.Name | quote}})
|
||||
}
|
||||
{{- else if $field.IsMethod }}
|
||||
{{- if $field.NoErr }}
|
||||
return {{$field.GoReceiverName}}.{{$field.GoFieldName}}({{ $field.CallArgs }}), nil
|
||||
{{- else }}
|
||||
return {{$field.GoReceiverName}}.{{$field.GoFieldName}}({{ $field.CallArgs }})
|
||||
{{- end }}
|
||||
{{- else if $field.IsVariable }}
|
||||
return {{$field.GoReceiverName}}.{{$field.GoFieldName}}, nil
|
||||
{{- end }}
|
||||
})
|
||||
if resTmp == nil {
|
||||
{{- if $field.TypeReference.GQL.NonNull }}
|
||||
if !ec.HasError(rctx) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
{{- end }}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.({{$field.TypeReference.GO | ref}})
|
||||
rctx.Result = res
|
||||
ctx = ec.Tracer.StartFieldChildExecution(ctx)
|
||||
return ec.{{ $field.TypeReference.MarshalFunc }}(ctx, field.Selections, res)
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
{{- end }}{{- end}}
|
||||
15
vendor/github.com/99designs/gqlgen/codegen/generate.go
generated
vendored
15
vendor/github.com/99designs/gqlgen/codegen/generate.go
generated
vendored
|
|
@ -1,15 +0,0 @@
|
|||
package codegen
|
||||
|
||||
import (
|
||||
"github.com/99designs/gqlgen/codegen/templates"
|
||||
)
|
||||
|
||||
func GenerateCode(data *Data) error {
|
||||
return templates.Render(templates.Options{
|
||||
PackageName: data.Config.Exec.Package,
|
||||
Filename: data.Config.Exec.Filename,
|
||||
Data: data,
|
||||
RegionTags: true,
|
||||
GeneratedHeader: true,
|
||||
})
|
||||
}
|
||||
256
vendor/github.com/99designs/gqlgen/codegen/generated!.gotpl
generated
vendored
256
vendor/github.com/99designs/gqlgen/codegen/generated!.gotpl
generated
vendored
|
|
@ -1,256 +0,0 @@
|
|||
{{ reserveImport "context" }}
|
||||
{{ reserveImport "fmt" }}
|
||||
{{ reserveImport "io" }}
|
||||
{{ reserveImport "strconv" }}
|
||||
{{ reserveImport "time" }}
|
||||
{{ reserveImport "sync" }}
|
||||
{{ reserveImport "sync/atomic" }}
|
||||
{{ reserveImport "errors" }}
|
||||
{{ reserveImport "bytes" }}
|
||||
|
||||
{{ reserveImport "github.com/vektah/gqlparser" }}
|
||||
{{ reserveImport "github.com/vektah/gqlparser/ast" }}
|
||||
{{ reserveImport "github.com/99designs/gqlgen/graphql" }}
|
||||
{{ reserveImport "github.com/99designs/gqlgen/graphql/introspection" }}
|
||||
|
||||
|
||||
// NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface.
|
||||
func NewExecutableSchema(cfg Config) graphql.ExecutableSchema {
|
||||
return &executableSchema{
|
||||
resolvers: cfg.Resolvers,
|
||||
directives: cfg.Directives,
|
||||
complexity: cfg.Complexity,
|
||||
}
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Resolvers ResolverRoot
|
||||
Directives DirectiveRoot
|
||||
Complexity ComplexityRoot
|
||||
}
|
||||
|
||||
type ResolverRoot interface {
|
||||
{{- range $object := .Objects -}}
|
||||
{{ if $object.HasResolvers -}}
|
||||
{{$object.Name}}() {{$object.Name}}Resolver
|
||||
{{ end }}
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
type DirectiveRoot struct {
|
||||
{{ range $directive := .Directives }}
|
||||
{{ $directive.Declaration }}
|
||||
{{ end }}
|
||||
}
|
||||
|
||||
type ComplexityRoot struct {
|
||||
{{ range $object := .Objects }}
|
||||
{{ if not $object.IsReserved -}}
|
||||
{{ $object.Name|go }} struct {
|
||||
{{ range $_, $fields := $object.UniqueFields }}
|
||||
{{- $field := index $fields 0 -}}
|
||||
{{ if not $field.IsReserved -}}
|
||||
{{ $field.GoFieldName }} {{ $field.ComplexitySignature }}
|
||||
{{ end }}
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
}
|
||||
|
||||
{{ range $object := .Objects -}}
|
||||
{{ if $object.HasResolvers }}
|
||||
type {{$object.Name}}Resolver interface {
|
||||
{{ range $field := $object.Fields -}}
|
||||
{{- if $field.IsResolver }}
|
||||
{{- $field.GoFieldName}}{{ $field.ShortResolverDeclaration }}
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
type executableSchema struct {
|
||||
resolvers ResolverRoot
|
||||
directives DirectiveRoot
|
||||
complexity ComplexityRoot
|
||||
}
|
||||
|
||||
func (e *executableSchema) Schema() *ast.Schema {
|
||||
return parsedSchema
|
||||
}
|
||||
|
||||
func (e *executableSchema) Complexity(typeName, field string, childComplexity int, rawArgs map[string]interface{}) (int, bool) {
|
||||
ec := executionContext{nil, e}
|
||||
_ = ec
|
||||
switch typeName + "." + field {
|
||||
{{ range $object := .Objects }}
|
||||
{{ if not $object.IsReserved }}
|
||||
{{ range $_, $fields := $object.UniqueFields }}
|
||||
{{- $len := len $fields }}
|
||||
{{- range $i, $field := $fields }}
|
||||
{{- $last := eq (add $i 1) $len }}
|
||||
{{- if not $field.IsReserved }}
|
||||
{{- if eq $i 0 }}case {{ end }}"{{$object.Name}}.{{$field.Name}}"{{ if not $last }},{{ else }}:
|
||||
if e.complexity.{{$object.Name|go}}.{{$field.GoFieldName}} == nil {
|
||||
break
|
||||
}
|
||||
{{ if $field.Args }}
|
||||
args, err := ec.{{ $field.ArgsFunc }}(context.TODO(),rawArgs)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
{{ end }}
|
||||
return e.complexity.{{$object.Name|go}}.{{$field.GoFieldName}}(childComplexity{{if $field.Args}}, {{$field.ComplexityArgs}} {{ end }}), true
|
||||
{{ end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
func (e *executableSchema) Query(ctx context.Context, op *ast.OperationDefinition) *graphql.Response {
|
||||
{{- if .QueryRoot }}
|
||||
ec := executionContext{graphql.GetRequestContext(ctx), e}
|
||||
|
||||
buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {
|
||||
data := ec._{{.QueryRoot.Name}}(ctx, op.SelectionSet)
|
||||
var buf bytes.Buffer
|
||||
data.MarshalGQL(&buf)
|
||||
return buf.Bytes()
|
||||
})
|
||||
|
||||
return &graphql.Response{
|
||||
Data: buf,
|
||||
Errors: ec.Errors,
|
||||
Extensions: ec.Extensions,
|
||||
}
|
||||
{{- else }}
|
||||
return graphql.ErrorResponse(ctx, "queries are not supported")
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
func (e *executableSchema) Mutation(ctx context.Context, op *ast.OperationDefinition) *graphql.Response {
|
||||
{{- if .MutationRoot }}
|
||||
ec := executionContext{graphql.GetRequestContext(ctx), e}
|
||||
|
||||
buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {
|
||||
data := ec._{{.MutationRoot.Name}}(ctx, op.SelectionSet)
|
||||
var buf bytes.Buffer
|
||||
data.MarshalGQL(&buf)
|
||||
return buf.Bytes()
|
||||
})
|
||||
|
||||
return &graphql.Response{
|
||||
Data: buf,
|
||||
Errors: ec.Errors,
|
||||
Extensions: ec.Extensions,
|
||||
}
|
||||
{{- else }}
|
||||
return graphql.ErrorResponse(ctx, "mutations are not supported")
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
func (e *executableSchema) Subscription(ctx context.Context, op *ast.OperationDefinition) func() *graphql.Response {
|
||||
{{- if .SubscriptionRoot }}
|
||||
ec := executionContext{graphql.GetRequestContext(ctx), e}
|
||||
|
||||
next := ec._{{.SubscriptionRoot.Name}}(ctx, op.SelectionSet)
|
||||
if ec.Errors != nil {
|
||||
return graphql.OneShot(&graphql.Response{Data: []byte("null"), Errors: ec.Errors})
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
return func() *graphql.Response {
|
||||
buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {
|
||||
buf.Reset()
|
||||
data := next()
|
||||
|
||||
if data == nil {
|
||||
return nil
|
||||
}
|
||||
data.MarshalGQL(&buf)
|
||||
return buf.Bytes()
|
||||
})
|
||||
|
||||
if buf == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &graphql.Response{
|
||||
Data: buf,
|
||||
Errors: ec.Errors,
|
||||
Extensions: ec.Extensions,
|
||||
}
|
||||
}
|
||||
{{- else }}
|
||||
return graphql.OneShot(graphql.ErrorResponse(ctx, "subscriptions are not supported"))
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
type executionContext struct {
|
||||
*graphql.RequestContext
|
||||
*executableSchema
|
||||
}
|
||||
|
||||
func (ec *executionContext) FieldMiddleware(ctx context.Context, obj interface{}, next graphql.Resolver) (ret interface{}) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = nil
|
||||
}
|
||||
}()
|
||||
{{- if .Directives }}
|
||||
rctx := graphql.GetResolverContext(ctx)
|
||||
for _, d := range rctx.Field.Definition.Directives {
|
||||
switch d.Name {
|
||||
{{- range $directive := .Directives }}
|
||||
case "{{$directive.Name}}":
|
||||
if ec.directives.{{$directive.Name|ucFirst}} != nil {
|
||||
{{- if $directive.Args }}
|
||||
rawArgs := d.ArgumentMap(ec.Variables)
|
||||
args, err := ec.{{ $directive.ArgsFunc }}(ctx,rawArgs)
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return nil
|
||||
}
|
||||
{{- end }}
|
||||
n := next
|
||||
next = func(ctx context.Context) (interface{}, error) {
|
||||
return ec.directives.{{$directive.Name|ucFirst}}({{$directive.CallArgs}})
|
||||
}
|
||||
}
|
||||
{{- end }}
|
||||
}
|
||||
}
|
||||
{{- end }}
|
||||
res, err := ec.ResolverMiddleware(ctx, next)
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return nil
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (ec *executionContext) introspectSchema() (*introspection.Schema, error) {
|
||||
if ec.DisableIntrospection {
|
||||
return nil, errors.New("introspection disabled")
|
||||
}
|
||||
return introspection.WrapSchema(parsedSchema), nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) introspectType(name string) (*introspection.Type, error) {
|
||||
if ec.DisableIntrospection {
|
||||
return nil, errors.New("introspection disabled")
|
||||
}
|
||||
return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil
|
||||
}
|
||||
|
||||
var parsedSchema = gqlparser.MustLoadSchema(
|
||||
{{- range $filename, $schema := .SchemaStr }}
|
||||
&ast.Source{Name: {{$filename|quote}}, Input: {{$schema|rawQuote}}},
|
||||
{{- end }}
|
||||
)
|
||||
56
vendor/github.com/99designs/gqlgen/codegen/input.gotpl
generated
vendored
56
vendor/github.com/99designs/gqlgen/codegen/input.gotpl
generated
vendored
|
|
@ -1,56 +0,0 @@
|
|||
{{- range $input := .Inputs }}
|
||||
{{- if not .HasUnmarshal }}
|
||||
func (ec *executionContext) unmarshalInput{{ .Name }}(ctx context.Context, v interface{}) ({{.Type | ref}}, error) {
|
||||
var it {{.Type | ref}}
|
||||
var asMap = v.(map[string]interface{})
|
||||
{{ range $field := .Fields}}
|
||||
{{- if $field.Default}}
|
||||
if _, present := asMap[{{$field.Name|quote}}] ; !present {
|
||||
asMap[{{$field.Name|quote}}] = {{ $field.Default | dump }}
|
||||
}
|
||||
{{- end}}
|
||||
{{- end }}
|
||||
|
||||
for k, v := range asMap {
|
||||
switch k {
|
||||
{{- range $field := .Fields }}
|
||||
case {{$field.Name|quote}}:
|
||||
var err error
|
||||
{{- if $field.Directives }}
|
||||
getField0 := func(ctx context.Context) (interface{}, error) { return ec.{{ $field.TypeReference.UnmarshalFunc }}(ctx, v) }
|
||||
|
||||
{{- range $i, $directive := $field.Directives }}
|
||||
getField{{add $i 1}} := func(ctx context.Context) (res interface{}, err error) {
|
||||
{{- range $dArg := $directive.Args }}
|
||||
{{- if and $dArg.TypeReference.IsPtr ( notNil "Value" $dArg ) }}
|
||||
{{ $dArg.VarName }} := {{ $dArg.Value | dump }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
n := getField{{$i}}
|
||||
return ec.directives.{{$directive.Name|ucFirst}}({{$directive.ResolveArgs "it" "n" }})
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
tmp, err := getField{{$field.Directives|len}}(ctx)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
if data, ok := tmp.({{ $field.TypeReference.GO | ref }}) ; ok {
|
||||
it.{{$field.GoFieldName}} = data
|
||||
} else {
|
||||
return it, fmt.Errorf(`unexpected type %T from directive, should be {{ $field.TypeReference.GO }}`, tmp)
|
||||
}
|
||||
{{- else }}
|
||||
it.{{$field.GoFieldName}}, err = ec.{{ $field.TypeReference.UnmarshalFunc }}(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
}
|
||||
}
|
||||
|
||||
return it, nil
|
||||
}
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
63
vendor/github.com/99designs/gqlgen/codegen/interface.go
generated
vendored
63
vendor/github.com/99designs/gqlgen/codegen/interface.go
generated
vendored
|
|
@ -1,63 +0,0 @@
|
|||
package codegen
|
||||
|
||||
import (
|
||||
"go/types"
|
||||
|
||||
"github.com/vektah/gqlparser/ast"
|
||||
)
|
||||
|
||||
type Interface struct {
|
||||
*ast.Definition
|
||||
Type types.Type
|
||||
Implementors []InterfaceImplementor
|
||||
InTypemap bool
|
||||
}
|
||||
|
||||
type InterfaceImplementor struct {
|
||||
*ast.Definition
|
||||
|
||||
Interface *Interface
|
||||
Type types.Type
|
||||
}
|
||||
|
||||
func (b *builder) buildInterface(typ *ast.Definition) *Interface {
|
||||
obj, err := b.Binder.DefaultUserObject(typ.Name)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
i := &Interface{
|
||||
Definition: typ,
|
||||
Type: obj,
|
||||
InTypemap: b.Config.Models.UserDefined(typ.Name),
|
||||
}
|
||||
|
||||
for _, implementor := range b.Schema.GetPossibleTypes(typ) {
|
||||
obj, err := b.Binder.DefaultUserObject(implementor.Name)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
i.Implementors = append(i.Implementors, InterfaceImplementor{
|
||||
Definition: implementor,
|
||||
Type: obj,
|
||||
Interface: i,
|
||||
})
|
||||
}
|
||||
|
||||
return i
|
||||
}
|
||||
|
||||
func (i *InterfaceImplementor) ValueReceiver() bool {
|
||||
interfaceType, err := findGoInterface(i.Interface.Type)
|
||||
if interfaceType == nil || err != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
implementorType, err := findGoNamedType(i.Type)
|
||||
if implementorType == nil || err != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
return types.Implements(implementorType, interfaceType)
|
||||
}
|
||||
20
vendor/github.com/99designs/gqlgen/codegen/interface.gotpl
generated
vendored
20
vendor/github.com/99designs/gqlgen/codegen/interface.gotpl
generated
vendored
|
|
@ -1,20 +0,0 @@
|
|||
{{- range $interface := .Interfaces }}
|
||||
|
||||
func (ec *executionContext) _{{$interface.Name}}(ctx context.Context, sel ast.SelectionSet, obj *{{$interface.Type | ref}}) graphql.Marshaler {
|
||||
switch obj := (*obj).(type) {
|
||||
case nil:
|
||||
return graphql.Null
|
||||
{{- range $implementor := $interface.Implementors }}
|
||||
{{- if $implementor.ValueReceiver }}
|
||||
case {{$implementor.Type | ref}}:
|
||||
return ec._{{$implementor.Name}}(ctx, sel, &obj)
|
||||
{{- end}}
|
||||
case *{{$implementor.Type | ref}}:
|
||||
return ec._{{$implementor.Name}}(ctx, sel, obj)
|
||||
{{- end }}
|
||||
default:
|
||||
panic(fmt.Errorf("unexpected type %T", obj))
|
||||
}
|
||||
}
|
||||
|
||||
{{- end }}
|
||||
172
vendor/github.com/99designs/gqlgen/codegen/object.go
generated
vendored
172
vendor/github.com/99designs/gqlgen/codegen/object.go
generated
vendored
|
|
@ -1,172 +0,0 @@
|
|||
package codegen
|
||||
|
||||
import (
|
||||
"go/types"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/99designs/gqlgen/codegen/config"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/vektah/gqlparser/ast"
|
||||
)
|
||||
|
||||
type GoFieldType int
|
||||
|
||||
const (
|
||||
GoFieldUndefined GoFieldType = iota
|
||||
GoFieldMethod
|
||||
GoFieldVariable
|
||||
GoFieldMap
|
||||
)
|
||||
|
||||
type Object struct {
|
||||
*ast.Definition
|
||||
|
||||
Type types.Type
|
||||
ResolverInterface types.Type
|
||||
Root bool
|
||||
Fields []*Field
|
||||
Implements []*ast.Definition
|
||||
DisableConcurrency bool
|
||||
Stream bool
|
||||
Directives []*Directive
|
||||
}
|
||||
|
||||
func (b *builder) buildObject(typ *ast.Definition) (*Object, error) {
|
||||
dirs, err := b.getDirectives(typ.Directives)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, typ.Name)
|
||||
}
|
||||
|
||||
obj := &Object{
|
||||
Definition: typ,
|
||||
Root: b.Schema.Query == typ || b.Schema.Mutation == typ || b.Schema.Subscription == typ,
|
||||
DisableConcurrency: typ == b.Schema.Mutation,
|
||||
Stream: typ == b.Schema.Subscription,
|
||||
Directives: dirs,
|
||||
ResolverInterface: types.NewNamed(
|
||||
types.NewTypeName(0, b.Config.Exec.Pkg(), typ.Name+"Resolver", nil),
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
}
|
||||
|
||||
if !obj.Root {
|
||||
goObject, err := b.Binder.DefaultUserObject(typ.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
obj.Type = goObject
|
||||
}
|
||||
|
||||
for _, intf := range b.Schema.GetImplements(typ) {
|
||||
obj.Implements = append(obj.Implements, b.Schema.Types[intf.Name])
|
||||
}
|
||||
|
||||
for _, field := range typ.Fields {
|
||||
if strings.HasPrefix(field.Name, "__") {
|
||||
continue
|
||||
}
|
||||
|
||||
var f *Field
|
||||
f, err = b.buildField(obj, field)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
obj.Fields = append(obj.Fields, f)
|
||||
}
|
||||
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
func (o *Object) Reference() types.Type {
|
||||
switch o.Type.(type) {
|
||||
case *types.Pointer, *types.Slice, *types.Map:
|
||||
return o.Type
|
||||
}
|
||||
|
||||
return types.NewPointer(o.Type)
|
||||
}
|
||||
|
||||
type Objects []*Object
|
||||
|
||||
func (o *Object) Implementors() string {
|
||||
satisfiedBy := strconv.Quote(o.Name)
|
||||
for _, s := range o.Implements {
|
||||
satisfiedBy += ", " + strconv.Quote(s.Name)
|
||||
}
|
||||
return "[]string{" + satisfiedBy + "}"
|
||||
}
|
||||
|
||||
func (o *Object) HasResolvers() bool {
|
||||
for _, f := range o.Fields {
|
||||
if f.IsResolver {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *Object) HasUnmarshal() bool {
|
||||
if o.Type == config.MapType {
|
||||
return true
|
||||
}
|
||||
for i := 0; i < o.Type.(*types.Named).NumMethods(); i++ {
|
||||
switch o.Type.(*types.Named).Method(i).Name() {
|
||||
case "UnmarshalGQL":
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *Object) HasDirectives() bool {
|
||||
if len(o.Directives) > 0 {
|
||||
return true
|
||||
}
|
||||
for _, f := range o.Fields {
|
||||
if f.HasDirectives() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *Object) IsConcurrent() bool {
|
||||
for _, f := range o.Fields {
|
||||
if f.IsConcurrent() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *Object) IsReserved() bool {
|
||||
return strings.HasPrefix(o.Definition.Name, "__")
|
||||
}
|
||||
|
||||
func (o *Object) Description() string {
|
||||
return o.Definition.Description
|
||||
}
|
||||
|
||||
func (os Objects) ByName(name string) *Object {
|
||||
for i, o := range os {
|
||||
if strings.EqualFold(o.Definition.Name, name) {
|
||||
return os[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ucFirst(s string) string {
|
||||
if s == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
r := []rune(s)
|
||||
r[0] = unicode.ToUpper(r[0])
|
||||
return string(r)
|
||||
}
|
||||
85
vendor/github.com/99designs/gqlgen/codegen/object.gotpl
generated
vendored
85
vendor/github.com/99designs/gqlgen/codegen/object.gotpl
generated
vendored
|
|
@ -1,85 +0,0 @@
|
|||
{{- range $object := .Objects }}
|
||||
|
||||
var {{ $object.Name|lcFirst}}Implementors = {{$object.Implementors}}
|
||||
|
||||
{{- if .Stream }}
|
||||
func (ec *executionContext) _{{$object.Name}}(ctx context.Context, sel ast.SelectionSet) func() graphql.Marshaler {
|
||||
fields := graphql.CollectFields(ec.RequestContext, sel, {{$object.Name|lcFirst}}Implementors)
|
||||
ctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{
|
||||
Object: {{$object.Name|quote}},
|
||||
})
|
||||
if len(fields) != 1 {
|
||||
ec.Errorf(ctx, "must subscribe to exactly one stream")
|
||||
return nil
|
||||
}
|
||||
|
||||
switch fields[0].Name {
|
||||
{{- range $field := $object.Fields }}
|
||||
case "{{$field.Name}}":
|
||||
return ec._{{$object.Name}}_{{$field.Name}}(ctx, fields[0])
|
||||
{{- end }}
|
||||
default:
|
||||
panic("unknown field " + strconv.Quote(fields[0].Name))
|
||||
}
|
||||
}
|
||||
{{- else }}
|
||||
func (ec *executionContext) _{{$object.Name}}(ctx context.Context, sel ast.SelectionSet{{ if not $object.Root }},obj {{$object.Reference | ref }}{{ end }}) graphql.Marshaler {
|
||||
fields := graphql.CollectFields(ec.RequestContext, sel, {{$object.Name|lcFirst}}Implementors)
|
||||
{{if $object.Root}}
|
||||
ctx = graphql.WithResolverContext(ctx, &graphql.ResolverContext{
|
||||
Object: {{$object.Name|quote}},
|
||||
})
|
||||
{{end}}
|
||||
|
||||
out := graphql.NewFieldSet(fields)
|
||||
var invalids uint32
|
||||
for i, field := range fields {
|
||||
switch field.Name {
|
||||
case "__typename":
|
||||
out.Values[i] = graphql.MarshalString({{$object.Name|quote}})
|
||||
{{- range $field := $object.Fields }}
|
||||
case "{{$field.Name}}":
|
||||
{{- if $field.IsConcurrent }}
|
||||
field := field
|
||||
out.Concurrently(i, func() (res graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
}
|
||||
}()
|
||||
res = ec._{{$object.Name}}_{{$field.Name}}(ctx, field{{if not $object.Root}}, obj{{end}})
|
||||
{{- if $field.TypeReference.GQL.NonNull }}
|
||||
if res == graphql.Null {
|
||||
{{- if $object.IsConcurrent }}
|
||||
atomic.AddUint32(&invalids, 1)
|
||||
{{- else }}
|
||||
invalids++
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}
|
||||
return res
|
||||
})
|
||||
{{- else }}
|
||||
out.Values[i] = ec._{{$object.Name}}_{{$field.Name}}(ctx, field{{if not $object.Root}}, obj{{end}})
|
||||
{{- if $field.TypeReference.GQL.NonNull }}
|
||||
if out.Values[i] == graphql.Null {
|
||||
{{- if $object.IsConcurrent }}
|
||||
atomic.AddUint32(&invalids, 1)
|
||||
{{- else }}
|
||||
invalids++
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
default:
|
||||
panic("unknown field " + strconv.Quote(field.Name))
|
||||
}
|
||||
}
|
||||
out.Dispatch()
|
||||
if invalids > 0 { return graphql.Null }
|
||||
return out
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
{{- end }}
|
||||
137
vendor/github.com/99designs/gqlgen/codegen/templates/import.go
generated
vendored
137
vendor/github.com/99designs/gqlgen/codegen/templates/import.go
generated
vendored
|
|
@ -1,137 +0,0 @@
|
|||
package templates
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/types"
|
||||
"strconv"
|
||||
|
||||
"github.com/99designs/gqlgen/internal/code"
|
||||
)
|
||||
|
||||
type Import struct {
|
||||
Name string
|
||||
Path string
|
||||
Alias string
|
||||
}
|
||||
|
||||
type Imports struct {
|
||||
imports []*Import
|
||||
destDir string
|
||||
}
|
||||
|
||||
func (i *Import) String() string {
|
||||
if i.Alias == i.Name {
|
||||
return strconv.Quote(i.Path)
|
||||
}
|
||||
|
||||
return i.Alias + " " + strconv.Quote(i.Path)
|
||||
}
|
||||
|
||||
func (s *Imports) String() string {
|
||||
res := ""
|
||||
for i, imp := range s.imports {
|
||||
if i != 0 {
|
||||
res += "\n"
|
||||
}
|
||||
res += imp.String()
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (s *Imports) Reserve(path string, aliases ...string) (string, error) {
|
||||
if path == "" {
|
||||
panic("empty ambient import")
|
||||
}
|
||||
|
||||
// if we are referencing our own package we dont need an import
|
||||
if code.ImportPathForDir(s.destDir) == path {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
name := code.NameForPackage(path)
|
||||
var alias string
|
||||
if len(aliases) != 1 {
|
||||
alias = name
|
||||
} else {
|
||||
alias = aliases[0]
|
||||
}
|
||||
|
||||
if existing := s.findByPath(path); existing != nil {
|
||||
if existing.Alias == alias {
|
||||
return "", nil
|
||||
}
|
||||
return "", fmt.Errorf("ambient import already exists")
|
||||
}
|
||||
|
||||
if alias := s.findByAlias(alias); alias != nil {
|
||||
return "", fmt.Errorf("ambient import collides on an alias")
|
||||
}
|
||||
|
||||
s.imports = append(s.imports, &Import{
|
||||
Name: name,
|
||||
Path: path,
|
||||
Alias: alias,
|
||||
})
|
||||
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (s *Imports) Lookup(path string) string {
|
||||
if path == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
path = code.NormalizeVendor(path)
|
||||
|
||||
// if we are referencing our own package we dont need an import
|
||||
if code.ImportPathForDir(s.destDir) == path {
|
||||
return ""
|
||||
}
|
||||
|
||||
if existing := s.findByPath(path); existing != nil {
|
||||
return existing.Alias
|
||||
}
|
||||
|
||||
imp := &Import{
|
||||
Name: code.NameForPackage(path),
|
||||
Path: path,
|
||||
}
|
||||
s.imports = append(s.imports, imp)
|
||||
|
||||
alias := imp.Name
|
||||
i := 1
|
||||
for s.findByAlias(alias) != nil {
|
||||
alias = imp.Name + strconv.Itoa(i)
|
||||
i++
|
||||
if i > 10 {
|
||||
panic(fmt.Errorf("too many collisions, last attempt was %s", alias))
|
||||
}
|
||||
}
|
||||
imp.Alias = alias
|
||||
|
||||
return imp.Alias
|
||||
}
|
||||
|
||||
func (s *Imports) LookupType(t types.Type) string {
|
||||
return types.TypeString(t, func(i *types.Package) string {
|
||||
return s.Lookup(i.Path())
|
||||
})
|
||||
}
|
||||
|
||||
func (s Imports) findByPath(importPath string) *Import {
|
||||
for _, imp := range s.imports {
|
||||
if imp.Path == importPath {
|
||||
return imp
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s Imports) findByAlias(alias string) *Import {
|
||||
for _, imp := range s.imports {
|
||||
if imp.Alias == alias {
|
||||
return imp
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
570
vendor/github.com/99designs/gqlgen/codegen/templates/templates.go
generated
vendored
570
vendor/github.com/99designs/gqlgen/codegen/templates/templates.go
generated
vendored
|
|
@ -1,570 +0,0 @@
|
|||
package templates
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/types"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/template"
|
||||
"unicode"
|
||||
|
||||
"github.com/99designs/gqlgen/internal/imports"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// CurrentImports keeps track of all the import declarations that are needed during the execution of a plugin.
|
||||
// this is done with a global because subtemplates currently get called in functions. Lets aim to remove this eventually.
|
||||
var CurrentImports *Imports
|
||||
|
||||
// Options specify various parameters to rendering a template.
|
||||
type Options struct {
|
||||
// PackageName is a helper that specifies the package header declaration.
|
||||
// In other words, when you write the template you don't need to specify `package X`
|
||||
// at the top of the file. By providing PackageName in the Options, the Render
|
||||
// function will do that for you.
|
||||
PackageName string
|
||||
// Template is a string of the entire template that
|
||||
// will be parsed and rendered. If it's empty,
|
||||
// the plugin processor will look for .gotpl files
|
||||
// in the same directory of where you wrote the plugin.
|
||||
Template string
|
||||
// Filename is the name of the file that will be
|
||||
// written to the system disk once the template is rendered.
|
||||
Filename string
|
||||
RegionTags bool
|
||||
GeneratedHeader bool
|
||||
// Data will be passed to the template execution.
|
||||
Data interface{}
|
||||
Funcs template.FuncMap
|
||||
}
|
||||
|
||||
// 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`
|
||||
// files inside the directory where you wrote the plugin.
|
||||
func Render(cfg Options) error {
|
||||
if CurrentImports != nil {
|
||||
panic(fmt.Errorf("recursive or concurrent call to RenderToFile detected"))
|
||||
}
|
||||
CurrentImports = &Imports{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)
|
||||
|
||||
var roots []string
|
||||
if cfg.Template != "" {
|
||||
var err error
|
||||
t, err = t.New("template.gotpl").Parse(cfg.Template)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error with provided template")
|
||||
}
|
||||
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
|
||||
}
|
||||
b, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
t, err = t.New(name).Parse(string(b))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, cfg.Filename)
|
||||
}
|
||||
|
||||
roots = append(roots, name)
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "locating templates")
|
||||
}
|
||||
}
|
||||
|
||||
// then execute all the important looking ones in order, adding them to the same file
|
||||
sort.Slice(roots, func(i, j int) bool {
|
||||
// important files go first
|
||||
if strings.HasSuffix(roots[i], "!.gotpl") {
|
||||
return true
|
||||
}
|
||||
if strings.HasSuffix(roots[j], "!.gotpl") {
|
||||
return false
|
||||
}
|
||||
return roots[i] < roots[j]
|
||||
})
|
||||
var buf bytes.Buffer
|
||||
for _, root := range roots {
|
||||
if cfg.RegionTags {
|
||||
buf.WriteString("\n// region " + center(70, "*", " "+root+" ") + "\n")
|
||||
}
|
||||
err := t.Lookup(root).Execute(&buf, cfg.Data)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, root)
|
||||
}
|
||||
if cfg.RegionTags {
|
||||
buf.WriteString("\n// endregion " + center(70, "*", " "+root+" ") + "\n")
|
||||
}
|
||||
}
|
||||
|
||||
var result bytes.Buffer
|
||||
if cfg.GeneratedHeader {
|
||||
result.WriteString("// Code generated by github.com/99designs/gqlgen, DO NOT EDIT.\n\n")
|
||||
}
|
||||
result.WriteString("package ")
|
||||
result.WriteString(cfg.PackageName)
|
||||
result.WriteString("\n\n")
|
||||
result.WriteString("import (\n")
|
||||
result.WriteString(CurrentImports.String())
|
||||
result.WriteString(")\n")
|
||||
_, err := buf.WriteTo(&result)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
CurrentImports = nil
|
||||
|
||||
return write(cfg.Filename, result.Bytes())
|
||||
}
|
||||
|
||||
func center(width int, pad string, s string) string {
|
||||
if len(s)+2 > width {
|
||||
return s
|
||||
}
|
||||
lpad := (width - len(s)) / 2
|
||||
rpad := width - (lpad + len(s))
|
||||
return strings.Repeat(pad, lpad) + s + strings.Repeat(pad, rpad)
|
||||
}
|
||||
|
||||
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,
|
||||
"add": func(a, b int) int {
|
||||
return a + b
|
||||
},
|
||||
"render": func(filename string, tpldata interface{}) (*bytes.Buffer, error) {
|
||||
return render(resolveName(filename, 0), tpldata)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func ucFirst(s string) string {
|
||||
if s == "" {
|
||||
return ""
|
||||
}
|
||||
r := []rune(s)
|
||||
r[0] = unicode.ToUpper(r[0])
|
||||
return string(r)
|
||||
}
|
||||
|
||||
func lcFirst(s string) string {
|
||||
if s == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
r := []rune(s)
|
||||
r[0] = unicode.ToLower(r[0])
|
||||
return string(r)
|
||||
}
|
||||
|
||||
func isDelimiter(c rune) bool {
|
||||
return c == '-' || c == '_' || unicode.IsSpace(c)
|
||||
}
|
||||
|
||||
func ref(p types.Type) string {
|
||||
return CurrentImports.LookupType(p)
|
||||
}
|
||||
|
||||
var pkgReplacer = strings.NewReplacer(
|
||||
"/", "ᚋ",
|
||||
".", "ᚗ",
|
||||
"-", "ᚑ",
|
||||
)
|
||||
|
||||
func TypeIdentifier(t types.Type) string {
|
||||
res := ""
|
||||
for {
|
||||
switch it := t.(type) {
|
||||
case *types.Pointer:
|
||||
t.Underlying()
|
||||
res += "ᚖ"
|
||||
t = it.Elem()
|
||||
case *types.Slice:
|
||||
res += "ᚕ"
|
||||
t = it.Elem()
|
||||
case *types.Named:
|
||||
res += pkgReplacer.Replace(it.Obj().Pkg().Path())
|
||||
res += "ᚐ"
|
||||
res += it.Obj().Name()
|
||||
return res
|
||||
case *types.Basic:
|
||||
res += it.Name()
|
||||
return res
|
||||
case *types.Map:
|
||||
res += "map"
|
||||
return res
|
||||
case *types.Interface:
|
||||
res += "interface"
|
||||
return res
|
||||
default:
|
||||
panic(fmt.Errorf("unexpected type %T", it))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Call(p *types.Func) string {
|
||||
pkg := CurrentImports.Lookup(p.Pkg().Path())
|
||||
|
||||
if pkg != "" {
|
||||
pkg += "."
|
||||
}
|
||||
|
||||
if p.Type() != nil {
|
||||
// make sure the returned type is listed in our imports.
|
||||
ref(p.Type().(*types.Signature).Results().At(0).Type())
|
||||
}
|
||||
|
||||
return pkg + p.Name()
|
||||
}
|
||||
|
||||
func ToGo(name string) string {
|
||||
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)...)
|
||||
})
|
||||
|
||||
return string(runes)
|
||||
}
|
||||
|
||||
func ToGoPrivate(name string) string {
|
||||
runes := make([]rune, 0, len(name))
|
||||
|
||||
first := true
|
||||
wordWalker(name, func(info *wordInfo) {
|
||||
word := info.Word
|
||||
if 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
|
||||
} else if info.MatchCommonInitial {
|
||||
word = strings.ToUpper(word)
|
||||
} else if !info.HasCommonInitial {
|
||||
word = ucFirst(strings.ToLower(word))
|
||||
}
|
||||
runes = append(runes, []rune(word)...)
|
||||
})
|
||||
|
||||
return sanitizeKeywords(string(runes))
|
||||
}
|
||||
|
||||
type wordInfo struct {
|
||||
Word string
|
||||
MatchCommonInitial bool
|
||||
HasCommonInitial bool
|
||||
}
|
||||
|
||||
// This function is based on the following code.
|
||||
// https://github.com/golang/lint/blob/06c8688daad7faa9da5a0c2f163a3d14aac986ca/lint.go#L679
|
||||
func wordWalker(str string, f func(*wordInfo)) {
|
||||
runes := []rune(str)
|
||||
w, i := 0, 0 // index of start of word, scan
|
||||
hasCommonInitial := false
|
||||
for i+1 <= len(runes) {
|
||||
eow := false // whether we hit the end of a word
|
||||
if i+1 == len(runes) {
|
||||
eow = true
|
||||
} else if isDelimiter(runes[i+1]) {
|
||||
// underscore; shift the remainder forward over any run of underscores
|
||||
eow = true
|
||||
n := 1
|
||||
for i+n+1 < len(runes) && isDelimiter(runes[i+n+1]) {
|
||||
n++
|
||||
}
|
||||
|
||||
// Leave at most one underscore if the underscore is between two digits
|
||||
if i+n+1 < len(runes) && unicode.IsDigit(runes[i]) && unicode.IsDigit(runes[i+n+1]) {
|
||||
n--
|
||||
}
|
||||
|
||||
copy(runes[i+1:], runes[i+n+1:])
|
||||
runes = runes[:len(runes)-n]
|
||||
} else if unicode.IsLower(runes[i]) && !unicode.IsLower(runes[i+1]) {
|
||||
// lower->non-lower
|
||||
eow = true
|
||||
}
|
||||
i++
|
||||
|
||||
// [w,i) is a word.
|
||||
word := string(runes[w:i])
|
||||
if !eow && commonInitialisms[word] && !unicode.IsLower(runes[i]) {
|
||||
// through
|
||||
// split IDFoo → ID, Foo
|
||||
// but URLs → URLs
|
||||
} else if !eow {
|
||||
if commonInitialisms[word] {
|
||||
hasCommonInitial = true
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
matchCommonInitial := false
|
||||
if commonInitialisms[strings.ToUpper(word)] {
|
||||
hasCommonInitial = true
|
||||
matchCommonInitial = true
|
||||
}
|
||||
|
||||
f(&wordInfo{
|
||||
Word: word,
|
||||
MatchCommonInitial: matchCommonInitial,
|
||||
HasCommonInitial: hasCommonInitial,
|
||||
})
|
||||
hasCommonInitial = false
|
||||
w = i
|
||||
}
|
||||
}
|
||||
|
||||
var keywords = []string{
|
||||
"break",
|
||||
"default",
|
||||
"func",
|
||||
"interface",
|
||||
"select",
|
||||
"case",
|
||||
"defer",
|
||||
"go",
|
||||
"map",
|
||||
"struct",
|
||||
"chan",
|
||||
"else",
|
||||
"goto",
|
||||
"package",
|
||||
"switch",
|
||||
"const",
|
||||
"fallthrough",
|
||||
"if",
|
||||
"range",
|
||||
"type",
|
||||
"continue",
|
||||
"for",
|
||||
"import",
|
||||
"return",
|
||||
"var",
|
||||
"_",
|
||||
}
|
||||
|
||||
// sanitizeKeywords prevents collisions with go keywords for arguments to resolver functions
|
||||
func sanitizeKeywords(name string) string {
|
||||
for _, k := range keywords {
|
||||
if name == k {
|
||||
return name + "Arg"
|
||||
}
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
// commonInitialisms is a set of common initialisms.
|
||||
// Only add entries that are highly unlikely to be non-initialisms.
|
||||
// For instance, "ID" is fine (Freudian code is rare), but "AND" is not.
|
||||
var commonInitialisms = map[string]bool{
|
||||
"ACL": true,
|
||||
"API": true,
|
||||
"ASCII": true,
|
||||
"CPU": true,
|
||||
"CSS": true,
|
||||
"DNS": true,
|
||||
"EOF": true,
|
||||
"GUID": true,
|
||||
"HTML": true,
|
||||
"HTTP": true,
|
||||
"HTTPS": true,
|
||||
"ID": true,
|
||||
"IP": true,
|
||||
"JSON": true,
|
||||
"LHS": true,
|
||||
"QPS": true,
|
||||
"RAM": true,
|
||||
"RHS": true,
|
||||
"RPC": true,
|
||||
"SLA": true,
|
||||
"SMTP": true,
|
||||
"SQL": true,
|
||||
"SSH": true,
|
||||
"TCP": true,
|
||||
"TLS": true,
|
||||
"TTL": true,
|
||||
"UDP": true,
|
||||
"UI": true,
|
||||
"UID": true,
|
||||
"UUID": true,
|
||||
"URI": true,
|
||||
"URL": true,
|
||||
"UTF8": true,
|
||||
"VM": true,
|
||||
"XML": true,
|
||||
"XMPP": true,
|
||||
"XSRF": true,
|
||||
"XSS": true,
|
||||
}
|
||||
|
||||
func rawQuote(s string) string {
|
||||
return "`" + strings.Replace(s, "`", "`+\"`\"+`", -1) + "`"
|
||||
}
|
||||
|
||||
func notNil(field string, data interface{}) bool {
|
||||
v := reflect.ValueOf(data)
|
||||
|
||||
if v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
if v.Kind() != reflect.Struct {
|
||||
return false
|
||||
}
|
||||
val := v.FieldByName(field)
|
||||
|
||||
return val.IsValid() && !val.IsNil()
|
||||
}
|
||||
|
||||
func Dump(val interface{}) string {
|
||||
switch val := val.(type) {
|
||||
case int:
|
||||
return strconv.Itoa(val)
|
||||
case int64:
|
||||
return fmt.Sprintf("%d", val)
|
||||
case float64:
|
||||
return fmt.Sprintf("%f", val)
|
||||
case string:
|
||||
return strconv.Quote(val)
|
||||
case bool:
|
||||
return strconv.FormatBool(val)
|
||||
case nil:
|
||||
return "nil"
|
||||
case []interface{}:
|
||||
var parts []string
|
||||
for _, part := range val {
|
||||
parts = append(parts, Dump(part))
|
||||
}
|
||||
return "[]interface{}{" + strings.Join(parts, ",") + "}"
|
||||
case map[string]interface{}:
|
||||
buf := bytes.Buffer{}
|
||||
buf.WriteString("map[string]interface{}{")
|
||||
var keys []string
|
||||
for key := range val {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
for _, key := range keys {
|
||||
data := val[key]
|
||||
|
||||
buf.WriteString(strconv.Quote(key))
|
||||
buf.WriteString(":")
|
||||
buf.WriteString(Dump(data))
|
||||
buf.WriteString(",")
|
||||
}
|
||||
buf.WriteString("}")
|
||||
return buf.String()
|
||||
default:
|
||||
panic(fmt.Errorf("unsupported type %T", val))
|
||||
}
|
||||
}
|
||||
|
||||
func prefixLines(prefix, s string) string {
|
||||
return prefix + strings.Replace(s, "\n", "\n"+prefix, -1)
|
||||
}
|
||||
|
||||
func resolveName(name string, skip int) string {
|
||||
if name[0] == '.' {
|
||||
// load path relative to calling source file
|
||||
_, callerFile, _, _ := runtime.Caller(skip + 1)
|
||||
return filepath.Join(filepath.Dir(callerFile), name[1:])
|
||||
}
|
||||
|
||||
// load path relative to this directory
|
||||
_, callerFile, _, _ := runtime.Caller(0)
|
||||
return filepath.Join(filepath.Dir(callerFile), name)
|
||||
}
|
||||
|
||||
func render(filename string, tpldata interface{}) (*bytes.Buffer, error) {
|
||||
t := template.New("").Funcs(Funcs())
|
||||
|
||||
b, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t, err = t.New(filepath.Base(filename)).Parse(string(b))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
return buf, t.Execute(buf, tpldata)
|
||||
}
|
||||
|
||||
func write(filename string, b []byte) error {
|
||||
err := os.MkdirAll(filepath.Dir(filename), 0755)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to create directory")
|
||||
}
|
||||
|
||||
formatted, err := imports.Prune(filename, b)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "gofmt failed on %s: %s\n", filepath.Base(filename), err.Error())
|
||||
formatted = b
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(filename, formatted, 0644)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to write %s", filename)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
18
vendor/github.com/99designs/gqlgen/codegen/type.go
generated
vendored
18
vendor/github.com/99designs/gqlgen/codegen/type.go
generated
vendored
|
|
@ -1,18 +0,0 @@
|
|||
package codegen
|
||||
|
||||
import (
|
||||
"github.com/99designs/gqlgen/codegen/config"
|
||||
)
|
||||
|
||||
func (b *builder) buildTypes() (map[string]*config.TypeReference, error) {
|
||||
ret := map[string]*config.TypeReference{}
|
||||
|
||||
for _, ref := range b.Binder.References {
|
||||
for ref != nil {
|
||||
ret[ref.UniquenessKey()] = ref
|
||||
|
||||
ref = ref.Elem()
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
130
vendor/github.com/99designs/gqlgen/codegen/type.gotpl
generated
vendored
130
vendor/github.com/99designs/gqlgen/codegen/type.gotpl
generated
vendored
|
|
@ -1,130 +0,0 @@
|
|||
{{- range $type := .ReferencedTypes }}
|
||||
{{ with $type.UnmarshalFunc }}
|
||||
func (ec *executionContext) {{ . }}(ctx context.Context, v interface{}) ({{ $type.GO | ref }}, error) {
|
||||
{{- if $type.IsNilable }}
|
||||
if v == nil { return nil, nil }
|
||||
{{- end }}
|
||||
{{- if $type.IsPtr }}
|
||||
res, err := ec.{{ $type.Elem.UnmarshalFunc }}(ctx, v)
|
||||
return &res, err
|
||||
{{- else if $type.IsSlice }}
|
||||
var vSlice []interface{}
|
||||
if v != nil {
|
||||
if tmp1, ok := v.([]interface{}); ok {
|
||||
vSlice = tmp1
|
||||
} else {
|
||||
vSlice = []interface{}{ v }
|
||||
}
|
||||
}
|
||||
var err error
|
||||
res := make([]{{$type.GO.Elem | ref}}, len(vSlice))
|
||||
for i := range vSlice {
|
||||
res[i], err = ec.{{ $type.Elem.UnmarshalFunc }}(ctx, vSlice[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
{{- else }}
|
||||
{{- if $type.Unmarshaler }}
|
||||
{{- if $type.CastType }}
|
||||
tmp, err := {{ $type.Unmarshaler | call }}(v)
|
||||
return {{ $type.GO | ref }}(tmp), err
|
||||
{{- else}}
|
||||
return {{ $type.Unmarshaler | call }}(v)
|
||||
{{- end }}
|
||||
{{- else if eq ($type.GO | ref) "map[string]interface{}" }}
|
||||
return v.(map[string]interface{}), nil
|
||||
{{- else if $type.IsMarshaler -}}
|
||||
var res {{ $type.GO | ref }}
|
||||
return res, res.UnmarshalGQL(v)
|
||||
{{- else }}
|
||||
return ec.unmarshalInput{{ $type.GQL.Name }}(ctx, v)
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
{{ with $type.MarshalFunc }}
|
||||
func (ec *executionContext) {{ . }}(ctx context.Context, sel ast.SelectionSet, v {{ $type.GO | ref }}) graphql.Marshaler {
|
||||
{{- if $type.IsNilable }}
|
||||
if v == nil {
|
||||
{{- if $type.GQL.NonNull }}
|
||||
if !ec.HasError(graphql.GetResolverContext(ctx)) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
{{- end }}
|
||||
return graphql.Null
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
{{- if $type.IsSlice }}
|
||||
{{- if not $type.GQL.NonNull }}
|
||||
if v == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
{{- end }}
|
||||
ret := make(graphql.Array, len(v))
|
||||
{{- if not $type.IsScalar }}
|
||||
var wg sync.WaitGroup
|
||||
isLen1 := len(v) == 1
|
||||
if !isLen1 {
|
||||
wg.Add(len(v))
|
||||
}
|
||||
{{- end }}
|
||||
for i := range v {
|
||||
{{- if not $type.IsScalar }}
|
||||
i := i
|
||||
rctx := &graphql.ResolverContext{
|
||||
Index: &i,
|
||||
Result: &v[i],
|
||||
}
|
||||
ctx := graphql.WithResolverContext(ctx, rctx)
|
||||
f := func(i int) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = nil
|
||||
}
|
||||
}()
|
||||
if !isLen1 {
|
||||
defer wg.Done()
|
||||
}
|
||||
ret[i] = ec.{{ $type.Elem.MarshalFunc }}(ctx, sel, v[i])
|
||||
}
|
||||
if isLen1 {
|
||||
f(i)
|
||||
} else {
|
||||
go f(i)
|
||||
}
|
||||
{{ else }}
|
||||
ret[i] = ec.{{ $type.Elem.MarshalFunc }}(ctx, sel, v[i])
|
||||
{{- end}}
|
||||
}
|
||||
{{ if not $type.IsScalar }} wg.Wait() {{ end }}
|
||||
return ret
|
||||
{{- else }}
|
||||
|
||||
{{- if $type.IsMarshaler }}
|
||||
return v
|
||||
{{- else if $type.Marshaler }}
|
||||
{{- if $type.IsPtr }}
|
||||
return ec.{{ $type.Elem.MarshalFunc }}(ctx, sel, *v)
|
||||
{{- else if $type.GQL.NonNull }}
|
||||
res := {{ $type.Marshaler | call }}({{- if $type.CastType }}{{ $type.CastType | ref }}(v){{else}}v{{- end }})
|
||||
if res == graphql.Null {
|
||||
if !ec.HasError(graphql.GetResolverContext(ctx)) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
}
|
||||
return res
|
||||
{{- else }}
|
||||
return {{ $type.Marshaler | call }}({{- if $type.CastType }}{{ $type.CastType | ref }}(v){{else}}v{{- end }})
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
return ec._{{$type.Definition.Name}}(ctx, sel, {{ if not $type.IsNilable}}&{{end}} v)
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
47
vendor/github.com/99designs/gqlgen/codegen/util.go
generated
vendored
47
vendor/github.com/99designs/gqlgen/codegen/util.go
generated
vendored
|
|
@ -1,47 +0,0 @@
|
|||
package codegen
|
||||
|
||||
import (
|
||||
"go/types"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func findGoNamedType(def types.Type) (*types.Named, error) {
|
||||
if def == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
namedType, ok := def.(*types.Named)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("expected %s to be a named type, instead found %T\n", def.String(), def)
|
||||
}
|
||||
|
||||
return namedType, nil
|
||||
}
|
||||
|
||||
func findGoInterface(def types.Type) (*types.Interface, error) {
|
||||
if def == nil {
|
||||
return nil, nil
|
||||
}
|
||||
namedType, err := findGoNamedType(def)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if namedType == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
underlying, ok := namedType.Underlying().(*types.Interface)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("expected %s to be a named interface, instead found %s", def.String(), namedType.String())
|
||||
}
|
||||
|
||||
return underlying, nil
|
||||
}
|
||||
|
||||
func equalFieldName(source, target string) bool {
|
||||
source = strings.Replace(source, "_", "", -1)
|
||||
target = strings.Replace(target, "_", "", -1)
|
||||
return strings.EqualFold(source, target)
|
||||
}
|
||||
104
vendor/github.com/99designs/gqlgen/complexity/complexity.go
generated
vendored
104
vendor/github.com/99designs/gqlgen/complexity/complexity.go
generated
vendored
|
|
@ -1,104 +0,0 @@
|
|||
package complexity
|
||||
|
||||
import (
|
||||
"github.com/99designs/gqlgen/graphql"
|
||||
"github.com/vektah/gqlparser/ast"
|
||||
)
|
||||
|
||||
func Calculate(es graphql.ExecutableSchema, op *ast.OperationDefinition, vars map[string]interface{}) int {
|
||||
walker := complexityWalker{
|
||||
es: es,
|
||||
schema: es.Schema(),
|
||||
vars: vars,
|
||||
}
|
||||
return walker.selectionSetComplexity(op.SelectionSet)
|
||||
}
|
||||
|
||||
type complexityWalker struct {
|
||||
es graphql.ExecutableSchema
|
||||
schema *ast.Schema
|
||||
vars map[string]interface{}
|
||||
}
|
||||
|
||||
func (cw complexityWalker) selectionSetComplexity(selectionSet ast.SelectionSet) int {
|
||||
var complexity int
|
||||
for _, selection := range selectionSet {
|
||||
switch s := selection.(type) {
|
||||
case *ast.Field:
|
||||
fieldDefinition := cw.schema.Types[s.Definition.Type.Name()]
|
||||
var childComplexity int
|
||||
switch fieldDefinition.Kind {
|
||||
case ast.Object, ast.Interface, ast.Union:
|
||||
childComplexity = cw.selectionSetComplexity(s.SelectionSet)
|
||||
}
|
||||
|
||||
args := s.ArgumentMap(cw.vars)
|
||||
var fieldComplexity int
|
||||
if s.ObjectDefinition.Kind == ast.Interface {
|
||||
fieldComplexity = cw.interfaceFieldComplexity(s.ObjectDefinition, s.Name, childComplexity, args)
|
||||
} else {
|
||||
fieldComplexity = cw.fieldComplexity(s.ObjectDefinition.Name, s.Name, childComplexity, args)
|
||||
}
|
||||
complexity = safeAdd(complexity, fieldComplexity)
|
||||
|
||||
case *ast.FragmentSpread:
|
||||
complexity = safeAdd(complexity, cw.selectionSetComplexity(s.Definition.SelectionSet))
|
||||
|
||||
case *ast.InlineFragment:
|
||||
complexity = safeAdd(complexity, cw.selectionSetComplexity(s.SelectionSet))
|
||||
}
|
||||
}
|
||||
return complexity
|
||||
}
|
||||
|
||||
func (cw complexityWalker) interfaceFieldComplexity(def *ast.Definition, field string, childComplexity int, args map[string]interface{}) int {
|
||||
// Interfaces don't have their own separate field costs, so they have to assume the worst case.
|
||||
// We iterate over all implementors and choose the most expensive one.
|
||||
maxComplexity := 0
|
||||
implementors := cw.schema.GetPossibleTypes(def)
|
||||
for _, t := range implementors {
|
||||
fieldComplexity := cw.fieldComplexity(t.Name, field, childComplexity, args)
|
||||
if fieldComplexity > maxComplexity {
|
||||
maxComplexity = fieldComplexity
|
||||
}
|
||||
}
|
||||
return maxComplexity
|
||||
}
|
||||
|
||||
func (cw complexityWalker) fieldComplexity(object, field string, childComplexity int, args map[string]interface{}) int {
|
||||
if customComplexity, ok := cw.es.Complexity(object, field, childComplexity, args); ok && customComplexity >= childComplexity {
|
||||
return customComplexity
|
||||
}
|
||||
// default complexity calculation
|
||||
return safeAdd(1, childComplexity)
|
||||
}
|
||||
|
||||
const maxInt = int(^uint(0) >> 1)
|
||||
|
||||
// safeAdd is a saturating add of a and b that ignores negative operands.
|
||||
// If a + b would overflow through normal Go addition,
|
||||
// it returns the maximum integer value instead.
|
||||
//
|
||||
// Adding complexities with this function prevents attackers from intentionally
|
||||
// overflowing the complexity calculation to allow overly-complex queries.
|
||||
//
|
||||
// It also helps mitigate the impact of custom complexities that accidentally
|
||||
// return negative values.
|
||||
func safeAdd(a, b int) int {
|
||||
// Ignore negative operands.
|
||||
if a < 0 {
|
||||
if b < 0 {
|
||||
return 1
|
||||
}
|
||||
return b
|
||||
} else if b < 0 {
|
||||
return a
|
||||
}
|
||||
|
||||
c := a + b
|
||||
if c < a {
|
||||
// Set c to maximum integer instead of overflowing.
|
||||
c = maxInt
|
||||
}
|
||||
return c
|
||||
}
|
||||
28
vendor/github.com/99designs/gqlgen/go.mod
generated
vendored
28
vendor/github.com/99designs/gqlgen/go.mod
generated
vendored
|
|
@ -1,28 +0,0 @@
|
|||
module github.com/99designs/gqlgen
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/go-chi/chi v3.3.2+incompatible
|
||||
github.com/gogo/protobuf v1.0.0 // indirect
|
||||
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f // indirect
|
||||
github.com/gorilla/mux v1.6.1 // indirect
|
||||
github.com/gorilla/websocket v1.2.0
|
||||
github.com/hashicorp/golang-lru v0.5.0
|
||||
github.com/kr/pretty v0.1.0 // indirect
|
||||
github.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047
|
||||
github.com/opentracing/basictracer-go v1.0.0 // indirect
|
||||
github.com/opentracing/opentracing-go v1.0.2
|
||||
github.com/pkg/errors v0.8.1
|
||||
github.com/rs/cors v1.6.0
|
||||
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371 // indirect
|
||||
github.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0 // indirect
|
||||
github.com/stretchr/testify v1.3.0
|
||||
github.com/urfave/cli v1.20.0
|
||||
github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e
|
||||
github.com/vektah/gqlparser v1.1.2
|
||||
golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
|
||||
gopkg.in/yaml.v2 v2.2.2
|
||||
sourcegraph.com/sourcegraph/appdash v0.0.0-20180110180208-2cc67fd64755
|
||||
sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67 // indirect
|
||||
)
|
||||
81
vendor/github.com/99designs/gqlgen/go.sum
generated
vendored
81
vendor/github.com/99designs/gqlgen/go.sum
generated
vendored
|
|
@ -1,81 +0,0 @@
|
|||
github.com/agnivade/levenshtein v1.0.1 h1:3oJU7J3FGFmyhn8KHjmVaZCN5hxTr7GxgRue+sxIXdQ=
|
||||
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-chi/chi v3.3.2+incompatible h1:uQNcQN3NsV1j4ANsPh42P4ew4t6rnRbJb8frvpp31qQ=
|
||||
github.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
||||
github.com/gogo/protobuf v1.0.0 h1:2jyBKDKU/8v3v2xVR2PtiWQviFUyiaGk2rpfyFT8rTM=
|
||||
github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f h1:9oNbS1z4rVpbnkHBdPZU4jo9bSmrLpII768arSyMFgk=
|
||||
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/mux v1.6.1 h1:KOwqsTYZdeuMacU7CxjMNYEKeBvLbxW+psodrbcEa3A=
|
||||
github.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/websocket v1.2.0 h1:VJtLvh6VQym50czpZzx07z/kw9EgAxI3x1ZB8taTMQQ=
|
||||
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047 h1:zCoDWFD5nrJJVjbXiDZcVhOBSzKn3o9LgRLLMRNuru8=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/opentracing/basictracer-go v1.0.0 h1:YyUAhaEfjoWXclZVJ9sGoNct7j4TVk7lZWlQw5UXuoo=
|
||||
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
|
||||
github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg=
|
||||
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rs/cors v1.6.0 h1:G9tHG9lebljV9mfp9SNPDL36nCDxmo3zTlAf1YgvzmI=
|
||||
github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371 h1:SWV2fHctRpRrp49VXJ6UZja7gU9QLHwRpIPBN89SKEo=
|
||||
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
|
||||
github.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0 h1:JJV9CsgM9EC9w2iVkwuz+sMx8yRFe89PJRUrv6hPCIA=
|
||||
github.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.1 h1:52QO5WkIUcHGIR7EnGagH88x1bUzqGXTC5/1bDTUQ7U=
|
||||
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/vektah/dataloaden v0.2.0 h1:lhynDrG7c8mNLahboCo0Wq82tMjmu5yOUv2ds/tBmss=
|
||||
github.com/vektah/dataloaden v0.2.0/go.mod h1:vxM6NuRlgiR0M6wbVTJeKp9vQIs81ZMfCYO+4yq/jbE=
|
||||
github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e h1:+w0Zm/9gaWpEAyDlU1eKOuk5twTjAjuevXqcJJw8hrg=
|
||||
github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U=
|
||||
github.com/vektah/gqlparser v1.1.2 h1:ZsyLGn7/7jDNI+y4SEhI4yAxRChlv15pUHMjijT+e68=
|
||||
github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/net v0.0.0-20180404174746-b3c676e531a6 h1:mge3qS/eMvcfyIAzTMOAy0XUzWG6Lk0N4M8zjuSmdco=
|
||||
golang.org/x/net v0.0.0-20180404174746-b3c676e531a6/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6 h1:iZgcI2DDp6zW5v9Z/5+f0NuqoxNdmzg4hivjk2WLXpY=
|
||||
golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190125232054-dbeab5af4b8d3204d444b78cafaba18a9a062a50/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190511041617-99f201b6807e h1:wTxRxdzKt8fn3IQa3+kVlPJMxK2hJj2Orm+M2Mzw9eg=
|
||||
golang.org/x/tools v0.0.0-20190511041617-99f201b6807e/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd h1:oMEQDWVXVNpceQoVd1JN3CQ7LYJJzs5qWqZIUcxXHHw=
|
||||
golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
sourcegraph.com/sourcegraph/appdash v0.0.0-20180110180208-2cc67fd64755 h1:d2maSb13hr/ArmfK3rW+wNUKKfytCol7W1/vDHxMPiE=
|
||||
sourcegraph.com/sourcegraph/appdash v0.0.0-20180110180208-2cc67fd64755/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
|
||||
sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67 h1:e1sMhtVq9AfcEy8AXNb8eSg6gbzfdpYhoNqnPJa+GzI=
|
||||
sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67/go.mod h1:L5q+DGLGOQFpo1snNEkLOJT2d1YTW66rWNzatr3He1k=
|
||||
19
vendor/github.com/99designs/gqlgen/graphql/any.go
generated
vendored
19
vendor/github.com/99designs/gqlgen/graphql/any.go
generated
vendored
|
|
@ -1,19 +0,0 @@
|
|||
package graphql
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
func MarshalAny(v interface{}) Marshaler {
|
||||
return WriterFunc(func(w io.Writer) {
|
||||
err := json.NewEncoder(w).Encode(v)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func UnmarshalAny(v interface{}) (interface{}, error) {
|
||||
return v, nil
|
||||
}
|
||||
30
vendor/github.com/99designs/gqlgen/graphql/bool.go
generated
vendored
30
vendor/github.com/99designs/gqlgen/graphql/bool.go
generated
vendored
|
|
@ -1,30 +0,0 @@
|
|||
package graphql
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func MarshalBoolean(b bool) Marshaler {
|
||||
return WriterFunc(func(w io.Writer) {
|
||||
if b {
|
||||
w.Write(trueLit)
|
||||
} else {
|
||||
w.Write(falseLit)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func UnmarshalBoolean(v interface{}) (bool, error) {
|
||||
switch v := v.(type) {
|
||||
case string:
|
||||
return strings.ToLower(v) == "true", nil
|
||||
case int:
|
||||
return v != 0, nil
|
||||
case bool:
|
||||
return v, nil
|
||||
default:
|
||||
return false, fmt.Errorf("%T is not a bool", v)
|
||||
}
|
||||
}
|
||||
274
vendor/github.com/99designs/gqlgen/graphql/context.go
generated
vendored
274
vendor/github.com/99designs/gqlgen/graphql/context.go
generated
vendored
|
|
@ -1,274 +0,0 @@
|
|||
package graphql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/vektah/gqlparser/ast"
|
||||
"github.com/vektah/gqlparser/gqlerror"
|
||||
)
|
||||
|
||||
type Resolver func(ctx context.Context) (res interface{}, err error)
|
||||
type FieldMiddleware func(ctx context.Context, next Resolver) (res interface{}, err error)
|
||||
type RequestMiddleware func(ctx context.Context, next func(ctx context.Context) []byte) []byte
|
||||
type ComplexityLimitFunc func(ctx context.Context) int
|
||||
|
||||
type RequestContext struct {
|
||||
RawQuery string
|
||||
Variables map[string]interface{}
|
||||
Doc *ast.QueryDocument
|
||||
|
||||
ComplexityLimit int
|
||||
OperationComplexity int
|
||||
DisableIntrospection bool
|
||||
|
||||
// ErrorPresenter will be used to generate the error
|
||||
// message from errors given to Error().
|
||||
ErrorPresenter ErrorPresenterFunc
|
||||
Recover RecoverFunc
|
||||
ResolverMiddleware FieldMiddleware
|
||||
DirectiveMiddleware FieldMiddleware
|
||||
RequestMiddleware RequestMiddleware
|
||||
Tracer Tracer
|
||||
|
||||
errorsMu sync.Mutex
|
||||
Errors gqlerror.List
|
||||
extensionsMu sync.Mutex
|
||||
Extensions map[string]interface{}
|
||||
}
|
||||
|
||||
func DefaultResolverMiddleware(ctx context.Context, next Resolver) (res interface{}, err error) {
|
||||
return next(ctx)
|
||||
}
|
||||
|
||||
func DefaultDirectiveMiddleware(ctx context.Context, next Resolver) (res interface{}, err error) {
|
||||
return next(ctx)
|
||||
}
|
||||
|
||||
func DefaultRequestMiddleware(ctx context.Context, next func(ctx context.Context) []byte) []byte {
|
||||
return next(ctx)
|
||||
}
|
||||
|
||||
func NewRequestContext(doc *ast.QueryDocument, query string, variables map[string]interface{}) *RequestContext {
|
||||
return &RequestContext{
|
||||
Doc: doc,
|
||||
RawQuery: query,
|
||||
Variables: variables,
|
||||
ResolverMiddleware: DefaultResolverMiddleware,
|
||||
DirectiveMiddleware: DefaultDirectiveMiddleware,
|
||||
RequestMiddleware: DefaultRequestMiddleware,
|
||||
Recover: DefaultRecover,
|
||||
ErrorPresenter: DefaultErrorPresenter,
|
||||
Tracer: &NopTracer{},
|
||||
}
|
||||
}
|
||||
|
||||
type key string
|
||||
|
||||
const (
|
||||
request key = "request_context"
|
||||
resolver key = "resolver_context"
|
||||
)
|
||||
|
||||
func GetRequestContext(ctx context.Context) *RequestContext {
|
||||
if val, ok := ctx.Value(request).(*RequestContext); ok {
|
||||
return val
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func WithRequestContext(ctx context.Context, rc *RequestContext) context.Context {
|
||||
return context.WithValue(ctx, request, rc)
|
||||
}
|
||||
|
||||
type ResolverContext struct {
|
||||
Parent *ResolverContext
|
||||
// The name of the type this field belongs to
|
||||
Object string
|
||||
// These are the args after processing, they can be mutated in middleware to change what the resolver will get.
|
||||
Args map[string]interface{}
|
||||
// The raw field
|
||||
Field CollectedField
|
||||
// The index of array in path.
|
||||
Index *int
|
||||
// The result object of resolver
|
||||
Result interface{}
|
||||
// IsMethod indicates if the resolver is a method
|
||||
IsMethod bool
|
||||
}
|
||||
|
||||
func (r *ResolverContext) Path() []interface{} {
|
||||
var path []interface{}
|
||||
for it := r; it != nil; it = it.Parent {
|
||||
if it.Index != nil {
|
||||
path = append(path, *it.Index)
|
||||
} else if it.Field.Field != nil {
|
||||
path = append(path, it.Field.Alias)
|
||||
}
|
||||
}
|
||||
|
||||
// because we are walking up the chain, all the elements are backwards, do an inplace flip.
|
||||
for i := len(path)/2 - 1; i >= 0; i-- {
|
||||
opp := len(path) - 1 - i
|
||||
path[i], path[opp] = path[opp], path[i]
|
||||
}
|
||||
|
||||
return path
|
||||
}
|
||||
|
||||
func GetResolverContext(ctx context.Context) *ResolverContext {
|
||||
if val, ok := ctx.Value(resolver).(*ResolverContext); ok {
|
||||
return val
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func WithResolverContext(ctx context.Context, rc *ResolverContext) context.Context {
|
||||
rc.Parent = GetResolverContext(ctx)
|
||||
return context.WithValue(ctx, resolver, rc)
|
||||
}
|
||||
|
||||
// This is just a convenient wrapper method for CollectFields
|
||||
func CollectFieldsCtx(ctx context.Context, satisfies []string) []CollectedField {
|
||||
resctx := GetResolverContext(ctx)
|
||||
return CollectFields(GetRequestContext(ctx), resctx.Field.Selections, satisfies)
|
||||
}
|
||||
|
||||
// CollectAllFields returns a slice of all GraphQL field names that were selected for the current resolver context.
|
||||
// The slice will contain the unique set of all field names requested regardless of fragment type conditions.
|
||||
func CollectAllFields(ctx context.Context) []string {
|
||||
resctx := GetResolverContext(ctx)
|
||||
collected := CollectFields(GetRequestContext(ctx), resctx.Field.Selections, nil)
|
||||
uniq := make([]string, 0, len(collected))
|
||||
Next:
|
||||
for _, f := range collected {
|
||||
for _, name := range uniq {
|
||||
if name == f.Name {
|
||||
continue Next
|
||||
}
|
||||
}
|
||||
uniq = append(uniq, f.Name)
|
||||
}
|
||||
return uniq
|
||||
}
|
||||
|
||||
// Errorf sends an error string to the client, passing it through the formatter.
|
||||
func (c *RequestContext) Errorf(ctx context.Context, format string, args ...interface{}) {
|
||||
c.errorsMu.Lock()
|
||||
defer c.errorsMu.Unlock()
|
||||
|
||||
c.Errors = append(c.Errors, c.ErrorPresenter(ctx, fmt.Errorf(format, args...)))
|
||||
}
|
||||
|
||||
// Error sends an error to the client, passing it through the formatter.
|
||||
func (c *RequestContext) Error(ctx context.Context, err error) {
|
||||
c.errorsMu.Lock()
|
||||
defer c.errorsMu.Unlock()
|
||||
|
||||
c.Errors = append(c.Errors, c.ErrorPresenter(ctx, err))
|
||||
}
|
||||
|
||||
// HasError returns true if the current field has already errored
|
||||
func (c *RequestContext) HasError(rctx *ResolverContext) bool {
|
||||
c.errorsMu.Lock()
|
||||
defer c.errorsMu.Unlock()
|
||||
path := rctx.Path()
|
||||
|
||||
for _, err := range c.Errors {
|
||||
if equalPath(err.Path, path) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GetErrors returns a list of errors that occurred in the current field
|
||||
func (c *RequestContext) GetErrors(rctx *ResolverContext) gqlerror.List {
|
||||
c.errorsMu.Lock()
|
||||
defer c.errorsMu.Unlock()
|
||||
path := rctx.Path()
|
||||
|
||||
var errs gqlerror.List
|
||||
for _, err := range c.Errors {
|
||||
if equalPath(err.Path, path) {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
return errs
|
||||
}
|
||||
|
||||
func equalPath(a []interface{}, b []interface{}) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := 0; i < len(a); i++ {
|
||||
if a[i] != b[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// AddError is a convenience method for adding an error to the current response
|
||||
func AddError(ctx context.Context, err error) {
|
||||
GetRequestContext(ctx).Error(ctx, err)
|
||||
}
|
||||
|
||||
// AddErrorf is a convenience method for adding an error to the current response
|
||||
func AddErrorf(ctx context.Context, format string, args ...interface{}) {
|
||||
GetRequestContext(ctx).Errorf(ctx, format, args...)
|
||||
}
|
||||
|
||||
// RegisterExtension registers an extension, returns error if extension has already been registered
|
||||
func (c *RequestContext) RegisterExtension(key string, value interface{}) error {
|
||||
c.extensionsMu.Lock()
|
||||
defer c.extensionsMu.Unlock()
|
||||
|
||||
if c.Extensions == nil {
|
||||
c.Extensions = make(map[string]interface{})
|
||||
}
|
||||
|
||||
if _, ok := c.Extensions[key]; ok {
|
||||
return fmt.Errorf("extension already registered for key %s", key)
|
||||
}
|
||||
|
||||
c.Extensions[key] = value
|
||||
return nil
|
||||
}
|
||||
|
||||
// ChainFieldMiddleware add chain by FieldMiddleware
|
||||
func ChainFieldMiddleware(handleFunc ...FieldMiddleware) FieldMiddleware {
|
||||
n := len(handleFunc)
|
||||
|
||||
if n > 1 {
|
||||
lastI := n - 1
|
||||
return func(ctx context.Context, next Resolver) (interface{}, error) {
|
||||
var (
|
||||
chainHandler Resolver
|
||||
curI int
|
||||
)
|
||||
chainHandler = func(currentCtx context.Context) (interface{}, error) {
|
||||
if curI == lastI {
|
||||
return next(currentCtx)
|
||||
}
|
||||
curI++
|
||||
res, err := handleFunc[curI](currentCtx, chainHandler)
|
||||
curI--
|
||||
return res, err
|
||||
|
||||
}
|
||||
return handleFunc[0](ctx, chainHandler)
|
||||
}
|
||||
}
|
||||
|
||||
if n == 1 {
|
||||
return handleFunc[0]
|
||||
}
|
||||
|
||||
return func(ctx context.Context, next Resolver) (interface{}, error) {
|
||||
return next(ctx)
|
||||
}
|
||||
}
|
||||
33
vendor/github.com/99designs/gqlgen/graphql/error.go
generated
vendored
33
vendor/github.com/99designs/gqlgen/graphql/error.go
generated
vendored
|
|
@ -1,33 +0,0 @@
|
|||
package graphql
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/vektah/gqlparser/gqlerror"
|
||||
)
|
||||
|
||||
type ErrorPresenterFunc func(context.Context, error) *gqlerror.Error
|
||||
|
||||
type ExtendedError interface {
|
||||
Extensions() map[string]interface{}
|
||||
}
|
||||
|
||||
func DefaultErrorPresenter(ctx context.Context, err error) *gqlerror.Error {
|
||||
if gqlerr, ok := err.(*gqlerror.Error); ok {
|
||||
if gqlerr.Path == nil {
|
||||
gqlerr.Path = GetResolverContext(ctx).Path()
|
||||
}
|
||||
return gqlerr
|
||||
}
|
||||
|
||||
var extensions map[string]interface{}
|
||||
if ee, ok := err.(ExtendedError); ok {
|
||||
extensions = ee.Extensions()
|
||||
}
|
||||
|
||||
return &gqlerror.Error{
|
||||
Message: err.Error(),
|
||||
Path: GetResolverContext(ctx).Path(),
|
||||
Extensions: extensions,
|
||||
}
|
||||
}
|
||||
144
vendor/github.com/99designs/gqlgen/graphql/exec.go
generated
vendored
144
vendor/github.com/99designs/gqlgen/graphql/exec.go
generated
vendored
|
|
@ -1,144 +0,0 @@
|
|||
package graphql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/vektah/gqlparser/ast"
|
||||
)
|
||||
|
||||
type ExecutableSchema interface {
|
||||
Schema() *ast.Schema
|
||||
|
||||
Complexity(typeName, fieldName string, childComplexity int, args map[string]interface{}) (int, bool)
|
||||
Query(ctx context.Context, op *ast.OperationDefinition) *Response
|
||||
Mutation(ctx context.Context, op *ast.OperationDefinition) *Response
|
||||
Subscription(ctx context.Context, op *ast.OperationDefinition) func() *Response
|
||||
}
|
||||
|
||||
// CollectFields returns the set of fields from an ast.SelectionSet where all collected fields satisfy at least one of the GraphQL types
|
||||
// passed through satisfies. Providing an empty or nil slice for satisfies will return collect all fields regardless of fragment
|
||||
// type conditions.
|
||||
func CollectFields(reqCtx *RequestContext, selSet ast.SelectionSet, satisfies []string) []CollectedField {
|
||||
return collectFields(reqCtx, selSet, satisfies, map[string]bool{})
|
||||
}
|
||||
|
||||
func collectFields(reqCtx *RequestContext, selSet ast.SelectionSet, satisfies []string, visited map[string]bool) []CollectedField {
|
||||
groupedFields := make([]CollectedField, 0, len(selSet))
|
||||
|
||||
for _, sel := range selSet {
|
||||
switch sel := sel.(type) {
|
||||
case *ast.Field:
|
||||
if !shouldIncludeNode(sel.Directives, reqCtx.Variables) {
|
||||
continue
|
||||
}
|
||||
f := getOrCreateAndAppendField(&groupedFields, sel.Alias, func() CollectedField {
|
||||
return CollectedField{Field: sel}
|
||||
})
|
||||
|
||||
f.Selections = append(f.Selections, sel.SelectionSet...)
|
||||
case *ast.InlineFragment:
|
||||
if !shouldIncludeNode(sel.Directives, reqCtx.Variables) {
|
||||
continue
|
||||
}
|
||||
if len(satisfies) > 0 && !instanceOf(sel.TypeCondition, satisfies) {
|
||||
continue
|
||||
}
|
||||
for _, childField := range collectFields(reqCtx, sel.SelectionSet, satisfies, visited) {
|
||||
f := getOrCreateAndAppendField(&groupedFields, childField.Name, func() CollectedField { return childField })
|
||||
f.Selections = append(f.Selections, childField.Selections...)
|
||||
}
|
||||
|
||||
case *ast.FragmentSpread:
|
||||
if !shouldIncludeNode(sel.Directives, reqCtx.Variables) {
|
||||
continue
|
||||
}
|
||||
fragmentName := sel.Name
|
||||
if _, seen := visited[fragmentName]; seen {
|
||||
continue
|
||||
}
|
||||
visited[fragmentName] = true
|
||||
|
||||
fragment := reqCtx.Doc.Fragments.ForName(fragmentName)
|
||||
if fragment == nil {
|
||||
// should never happen, validator has already run
|
||||
panic(fmt.Errorf("missing fragment %s", fragmentName))
|
||||
}
|
||||
|
||||
if len(satisfies) > 0 && !instanceOf(fragment.TypeCondition, satisfies) {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, childField := range collectFields(reqCtx, fragment.SelectionSet, satisfies, visited) {
|
||||
f := getOrCreateAndAppendField(&groupedFields, childField.Name, func() CollectedField { return childField })
|
||||
f.Selections = append(f.Selections, childField.Selections...)
|
||||
}
|
||||
default:
|
||||
panic(fmt.Errorf("unsupported %T", sel))
|
||||
}
|
||||
}
|
||||
|
||||
return groupedFields
|
||||
}
|
||||
|
||||
type CollectedField struct {
|
||||
*ast.Field
|
||||
|
||||
Selections ast.SelectionSet
|
||||
}
|
||||
|
||||
func instanceOf(val string, satisfies []string) bool {
|
||||
for _, s := range satisfies {
|
||||
if val == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func getOrCreateAndAppendField(c *[]CollectedField, name string, creator func() CollectedField) *CollectedField {
|
||||
for i, cf := range *c {
|
||||
if cf.Alias == name {
|
||||
return &(*c)[i]
|
||||
}
|
||||
}
|
||||
|
||||
f := creator()
|
||||
|
||||
*c = append(*c, f)
|
||||
return &(*c)[len(*c)-1]
|
||||
}
|
||||
|
||||
func shouldIncludeNode(directives ast.DirectiveList, variables map[string]interface{}) bool {
|
||||
if len(directives) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
skip, include := false, true
|
||||
|
||||
if d := directives.ForName("skip"); d != nil {
|
||||
skip = resolveIfArgument(d, variables)
|
||||
}
|
||||
|
||||
if d := directives.ForName("include"); d != nil {
|
||||
include = resolveIfArgument(d, variables)
|
||||
}
|
||||
|
||||
return !skip && include
|
||||
}
|
||||
|
||||
func resolveIfArgument(d *ast.Directive, variables map[string]interface{}) bool {
|
||||
arg := d.Arguments.ForName("if")
|
||||
if arg == nil {
|
||||
panic(fmt.Sprintf("%s: argument 'if' not defined", d.Name))
|
||||
}
|
||||
value, err := arg.Value.Value(variables)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ret, ok := value.(bool)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("%s: argument 'if' is not a boolean", d.Name))
|
||||
}
|
||||
return ret
|
||||
}
|
||||
63
vendor/github.com/99designs/gqlgen/graphql/fieldset.go
generated
vendored
63
vendor/github.com/99designs/gqlgen/graphql/fieldset.go
generated
vendored
|
|
@ -1,63 +0,0 @@
|
|||
package graphql
|
||||
|
||||
import (
|
||||
"io"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type FieldSet struct {
|
||||
fields []CollectedField
|
||||
Values []Marshaler
|
||||
delayed []delayedResult
|
||||
}
|
||||
|
||||
type delayedResult struct {
|
||||
i int
|
||||
f func() Marshaler
|
||||
}
|
||||
|
||||
func NewFieldSet(fields []CollectedField) *FieldSet {
|
||||
return &FieldSet{
|
||||
fields: fields,
|
||||
Values: make([]Marshaler, len(fields)),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *FieldSet) Concurrently(i int, f func() Marshaler) {
|
||||
m.delayed = append(m.delayed, delayedResult{i: i, f: f})
|
||||
}
|
||||
|
||||
func (m *FieldSet) Dispatch() {
|
||||
if len(m.delayed) == 1 {
|
||||
// only one concurrent task, no need to spawn a goroutine or deal create waitgroups
|
||||
d := m.delayed[0]
|
||||
m.Values[d.i] = d.f()
|
||||
} else if len(m.delayed) > 1 {
|
||||
// more than one concurrent task, use the main goroutine to do one, only spawn goroutines for the others
|
||||
|
||||
var wg sync.WaitGroup
|
||||
for _, d := range m.delayed[1:] {
|
||||
wg.Add(1)
|
||||
go func(d delayedResult) {
|
||||
m.Values[d.i] = d.f()
|
||||
wg.Done()
|
||||
}(d)
|
||||
}
|
||||
|
||||
m.Values[m.delayed[0].i] = m.delayed[0].f()
|
||||
wg.Wait()
|
||||
}
|
||||
}
|
||||
|
||||
func (m *FieldSet) MarshalGQL(writer io.Writer) {
|
||||
writer.Write(openBrace)
|
||||
for i, field := range m.fields {
|
||||
if i != 0 {
|
||||
writer.Write(comma)
|
||||
}
|
||||
writeQuotedString(writer, field.Alias)
|
||||
writer.Write(colon)
|
||||
m.Values[i].MarshalGQL(writer)
|
||||
}
|
||||
writer.Write(closeBrace)
|
||||
}
|
||||
31
vendor/github.com/99designs/gqlgen/graphql/float.go
generated
vendored
31
vendor/github.com/99designs/gqlgen/graphql/float.go
generated
vendored
|
|
@ -1,31 +0,0 @@
|
|||
package graphql
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func MarshalFloat(f float64) Marshaler {
|
||||
return WriterFunc(func(w io.Writer) {
|
||||
io.WriteString(w, fmt.Sprintf("%g", f))
|
||||
})
|
||||
}
|
||||
|
||||
func UnmarshalFloat(v interface{}) (float64, error) {
|
||||
switch v := v.(type) {
|
||||
case string:
|
||||
return strconv.ParseFloat(v, 64)
|
||||
case int:
|
||||
return float64(v), nil
|
||||
case int64:
|
||||
return float64(v), nil
|
||||
case float64:
|
||||
return v, nil
|
||||
case json.Number:
|
||||
return strconv.ParseFloat(string(v), 64)
|
||||
default:
|
||||
return 0, fmt.Errorf("%T is not an float", v)
|
||||
}
|
||||
}
|
||||
57
vendor/github.com/99designs/gqlgen/graphql/id.go
generated
vendored
57
vendor/github.com/99designs/gqlgen/graphql/id.go
generated
vendored
|
|
@ -1,57 +0,0 @@
|
|||
package graphql
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func MarshalID(s string) Marshaler {
|
||||
return WriterFunc(func(w io.Writer) {
|
||||
io.WriteString(w, strconv.Quote(s))
|
||||
})
|
||||
}
|
||||
func UnmarshalID(v interface{}) (string, error) {
|
||||
switch v := v.(type) {
|
||||
case string:
|
||||
return v, nil
|
||||
case json.Number:
|
||||
return string(v), nil
|
||||
case int:
|
||||
return strconv.Itoa(v), nil
|
||||
case float64:
|
||||
return fmt.Sprintf("%f", v), nil
|
||||
case bool:
|
||||
if v {
|
||||
return "true", nil
|
||||
} else {
|
||||
return "false", nil
|
||||
}
|
||||
case nil:
|
||||
return "null", nil
|
||||
default:
|
||||
return "", fmt.Errorf("%T is not a string", v)
|
||||
}
|
||||
}
|
||||
|
||||
func MarshalIntID(i int) Marshaler {
|
||||
return WriterFunc(func(w io.Writer) {
|
||||
writeQuotedString(w, strconv.Itoa(i))
|
||||
})
|
||||
}
|
||||
|
||||
func UnmarshalIntID(v interface{}) (int, error) {
|
||||
switch v := v.(type) {
|
||||
case string:
|
||||
return strconv.Atoi(v)
|
||||
case int:
|
||||
return v, nil
|
||||
case int64:
|
||||
return int(v), nil
|
||||
case json.Number:
|
||||
return strconv.Atoi(string(v))
|
||||
default:
|
||||
return 0, fmt.Errorf("%T is not an int", v)
|
||||
}
|
||||
}
|
||||
79
vendor/github.com/99designs/gqlgen/graphql/int.go
generated
vendored
79
vendor/github.com/99designs/gqlgen/graphql/int.go
generated
vendored
|
|
@ -1,79 +0,0 @@
|
|||
package graphql
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func MarshalInt(i int) Marshaler {
|
||||
return WriterFunc(func(w io.Writer) {
|
||||
io.WriteString(w, strconv.Itoa(i))
|
||||
})
|
||||
}
|
||||
|
||||
func UnmarshalInt(v interface{}) (int, error) {
|
||||
switch v := v.(type) {
|
||||
case string:
|
||||
return strconv.Atoi(v)
|
||||
case int:
|
||||
return v, nil
|
||||
case int64:
|
||||
return int(v), nil
|
||||
case json.Number:
|
||||
return strconv.Atoi(string(v))
|
||||
default:
|
||||
return 0, fmt.Errorf("%T is not an int", v)
|
||||
}
|
||||
}
|
||||
|
||||
func MarshalInt64(i int64) Marshaler {
|
||||
return WriterFunc(func(w io.Writer) {
|
||||
io.WriteString(w, strconv.FormatInt(i, 10))
|
||||
})
|
||||
}
|
||||
|
||||
func UnmarshalInt64(v interface{}) (int64, error) {
|
||||
switch v := v.(type) {
|
||||
case string:
|
||||
return strconv.ParseInt(v, 10, 64)
|
||||
case int:
|
||||
return int64(v), nil
|
||||
case int64:
|
||||
return v, nil
|
||||
case json.Number:
|
||||
return strconv.ParseInt(string(v), 10, 64)
|
||||
default:
|
||||
return 0, fmt.Errorf("%T is not an int", v)
|
||||
}
|
||||
}
|
||||
|
||||
func MarshalInt32(i int32) Marshaler {
|
||||
return WriterFunc(func(w io.Writer) {
|
||||
io.WriteString(w, strconv.FormatInt(int64(i), 10))
|
||||
})
|
||||
}
|
||||
|
||||
func UnmarshalInt32(v interface{}) (int32, error) {
|
||||
switch v := v.(type) {
|
||||
case string:
|
||||
iv, err := strconv.ParseInt(v, 10, 32)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int32(iv), nil
|
||||
case int:
|
||||
return int32(v), nil
|
||||
case int64:
|
||||
return int32(v), nil
|
||||
case json.Number:
|
||||
iv, err := strconv.ParseInt(string(v), 10, 32)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int32(iv), nil
|
||||
default:
|
||||
return 0, fmt.Errorf("%T is not an int", v)
|
||||
}
|
||||
}
|
||||
72
vendor/github.com/99designs/gqlgen/graphql/introspection/introspection.go
generated
vendored
72
vendor/github.com/99designs/gqlgen/graphql/introspection/introspection.go
generated
vendored
|
|
@ -1,72 +0,0 @@
|
|||
// introspection implements the spec defined in https://github.com/facebook/graphql/blob/master/spec/Section%204%20--%20Introspection.md#schema-introspection
|
||||
package introspection
|
||||
|
||||
import "github.com/vektah/gqlparser/ast"
|
||||
|
||||
type (
|
||||
Directive struct {
|
||||
Name string
|
||||
Description string
|
||||
Locations []string
|
||||
Args []InputValue
|
||||
}
|
||||
|
||||
EnumValue struct {
|
||||
Name string
|
||||
Description string
|
||||
deprecation *ast.Directive
|
||||
}
|
||||
|
||||
Field struct {
|
||||
Name string
|
||||
Description string
|
||||
Type *Type
|
||||
Args []InputValue
|
||||
deprecation *ast.Directive
|
||||
}
|
||||
|
||||
InputValue struct {
|
||||
Name string
|
||||
Description string
|
||||
DefaultValue *string
|
||||
Type *Type
|
||||
}
|
||||
)
|
||||
|
||||
func WrapSchema(schema *ast.Schema) *Schema {
|
||||
return &Schema{schema: schema}
|
||||
}
|
||||
|
||||
func (f *EnumValue) IsDeprecated() bool {
|
||||
return f.deprecation != nil
|
||||
}
|
||||
|
||||
func (f *EnumValue) DeprecationReason() *string {
|
||||
if f.deprecation == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
reason := f.deprecation.Arguments.ForName("reason")
|
||||
if reason == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &reason.Value.Raw
|
||||
}
|
||||
|
||||
func (f *Field) IsDeprecated() bool {
|
||||
return f.deprecation != nil
|
||||
}
|
||||
|
||||
func (f *Field) DeprecationReason() *string {
|
||||
if f.deprecation == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
reason := f.deprecation.Arguments.ForName("reason")
|
||||
if reason == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &reason.Value.Raw
|
||||
}
|
||||
104
vendor/github.com/99designs/gqlgen/graphql/introspection/query.go
generated
vendored
104
vendor/github.com/99designs/gqlgen/graphql/introspection/query.go
generated
vendored
|
|
@ -1,104 +0,0 @@
|
|||
package introspection
|
||||
|
||||
// Query is the query generated by graphiql to determine type information
|
||||
const Query = `
|
||||
query IntrospectionQuery {
|
||||
__schema {
|
||||
queryType {
|
||||
name
|
||||
}
|
||||
mutationType {
|
||||
name
|
||||
}
|
||||
subscriptionType {
|
||||
name
|
||||
}
|
||||
types {
|
||||
...FullType
|
||||
}
|
||||
directives {
|
||||
name
|
||||
description
|
||||
locations
|
||||
args {
|
||||
...InputValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fragment FullType on __Type {
|
||||
kind
|
||||
name
|
||||
description
|
||||
fields(includeDeprecated: true) {
|
||||
name
|
||||
description
|
||||
args {
|
||||
...InputValue
|
||||
}
|
||||
type {
|
||||
...TypeRef
|
||||
}
|
||||
isDeprecated
|
||||
deprecationReason
|
||||
}
|
||||
inputFields {
|
||||
...InputValue
|
||||
}
|
||||
interfaces {
|
||||
...TypeRef
|
||||
}
|
||||
enumValues(includeDeprecated: true) {
|
||||
name
|
||||
description
|
||||
isDeprecated
|
||||
deprecationReason
|
||||
}
|
||||
possibleTypes {
|
||||
...TypeRef
|
||||
}
|
||||
}
|
||||
|
||||
fragment InputValue on __InputValue {
|
||||
name
|
||||
description
|
||||
type {
|
||||
...TypeRef
|
||||
}
|
||||
defaultValue
|
||||
}
|
||||
|
||||
fragment TypeRef on __Type {
|
||||
kind
|
||||
name
|
||||
ofType {
|
||||
kind
|
||||
name
|
||||
ofType {
|
||||
kind
|
||||
name
|
||||
ofType {
|
||||
kind
|
||||
name
|
||||
ofType {
|
||||
kind
|
||||
name
|
||||
ofType {
|
||||
kind
|
||||
name
|
||||
ofType {
|
||||
kind
|
||||
name
|
||||
ofType {
|
||||
kind
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
68
vendor/github.com/99designs/gqlgen/graphql/introspection/schema.go
generated
vendored
68
vendor/github.com/99designs/gqlgen/graphql/introspection/schema.go
generated
vendored
|
|
@ -1,68 +0,0 @@
|
|||
package introspection
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/vektah/gqlparser/ast"
|
||||
)
|
||||
|
||||
type Schema struct {
|
||||
schema *ast.Schema
|
||||
}
|
||||
|
||||
func (s *Schema) Types() []Type {
|
||||
var types []Type
|
||||
for _, typ := range s.schema.Types {
|
||||
if strings.HasPrefix(typ.Name, "__") {
|
||||
continue
|
||||
}
|
||||
types = append(types, *WrapTypeFromDef(s.schema, typ))
|
||||
}
|
||||
return types
|
||||
}
|
||||
|
||||
func (s *Schema) QueryType() *Type {
|
||||
return WrapTypeFromDef(s.schema, s.schema.Query)
|
||||
}
|
||||
|
||||
func (s *Schema) MutationType() *Type {
|
||||
return WrapTypeFromDef(s.schema, s.schema.Mutation)
|
||||
}
|
||||
|
||||
func (s *Schema) SubscriptionType() *Type {
|
||||
return WrapTypeFromDef(s.schema, s.schema.Subscription)
|
||||
}
|
||||
|
||||
func (s *Schema) Directives() []Directive {
|
||||
var res []Directive
|
||||
|
||||
for _, d := range s.schema.Directives {
|
||||
res = append(res, s.directiveFromDef(d))
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func (s *Schema) directiveFromDef(d *ast.DirectiveDefinition) Directive {
|
||||
var locs []string
|
||||
for _, loc := range d.Locations {
|
||||
locs = append(locs, string(loc))
|
||||
}
|
||||
|
||||
var args []InputValue
|
||||
for _, arg := range d.Arguments {
|
||||
args = append(args, InputValue{
|
||||
Name: arg.Name,
|
||||
Description: arg.Description,
|
||||
DefaultValue: defaultValue(arg.DefaultValue),
|
||||
Type: WrapTypeFromType(s.schema, arg.Type),
|
||||
})
|
||||
}
|
||||
|
||||
return Directive{
|
||||
Name: d.Name,
|
||||
Description: d.Description,
|
||||
Locations: locs,
|
||||
Args: args,
|
||||
}
|
||||
}
|
||||
176
vendor/github.com/99designs/gqlgen/graphql/introspection/type.go
generated
vendored
176
vendor/github.com/99designs/gqlgen/graphql/introspection/type.go
generated
vendored
|
|
@ -1,176 +0,0 @@
|
|||
package introspection
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/vektah/gqlparser/ast"
|
||||
)
|
||||
|
||||
type Type struct {
|
||||
schema *ast.Schema
|
||||
def *ast.Definition
|
||||
typ *ast.Type
|
||||
}
|
||||
|
||||
func WrapTypeFromDef(s *ast.Schema, def *ast.Definition) *Type {
|
||||
if def == nil {
|
||||
return nil
|
||||
}
|
||||
return &Type{schema: s, def: def}
|
||||
}
|
||||
|
||||
func WrapTypeFromType(s *ast.Schema, typ *ast.Type) *Type {
|
||||
if typ == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if !typ.NonNull && typ.NamedType != "" {
|
||||
return &Type{schema: s, def: s.Types[typ.NamedType]}
|
||||
}
|
||||
return &Type{schema: s, typ: typ}
|
||||
}
|
||||
|
||||
func (t *Type) Kind() string {
|
||||
if t.typ != nil {
|
||||
if t.typ.NonNull {
|
||||
return "NON_NULL"
|
||||
}
|
||||
|
||||
if t.typ.Elem != nil {
|
||||
return "LIST"
|
||||
}
|
||||
} else {
|
||||
return string(t.def.Kind)
|
||||
}
|
||||
|
||||
panic("UNKNOWN")
|
||||
}
|
||||
|
||||
func (t *Type) Name() *string {
|
||||
if t.def == nil {
|
||||
return nil
|
||||
}
|
||||
return &t.def.Name
|
||||
}
|
||||
|
||||
func (t *Type) Description() string {
|
||||
if t.def == nil {
|
||||
return ""
|
||||
}
|
||||
return t.def.Description
|
||||
}
|
||||
|
||||
func (t *Type) Fields(includeDeprecated bool) []Field {
|
||||
if t.def == nil || (t.def.Kind != ast.Object && t.def.Kind != ast.Interface) {
|
||||
return []Field{}
|
||||
}
|
||||
fields := []Field{}
|
||||
for _, f := range t.def.Fields {
|
||||
if strings.HasPrefix(f.Name, "__") {
|
||||
continue
|
||||
}
|
||||
|
||||
if !includeDeprecated && f.Directives.ForName("deprecated") != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
var args []InputValue
|
||||
for _, arg := range f.Arguments {
|
||||
args = append(args, InputValue{
|
||||
Type: WrapTypeFromType(t.schema, arg.Type),
|
||||
Name: arg.Name,
|
||||
Description: arg.Description,
|
||||
DefaultValue: defaultValue(arg.DefaultValue),
|
||||
})
|
||||
}
|
||||
|
||||
fields = append(fields, Field{
|
||||
Name: f.Name,
|
||||
Description: f.Description,
|
||||
Args: args,
|
||||
Type: WrapTypeFromType(t.schema, f.Type),
|
||||
deprecation: f.Directives.ForName("deprecated"),
|
||||
})
|
||||
}
|
||||
return fields
|
||||
}
|
||||
|
||||
func (t *Type) InputFields() []InputValue {
|
||||
if t.def == nil || t.def.Kind != ast.InputObject {
|
||||
return []InputValue{}
|
||||
}
|
||||
|
||||
res := []InputValue{}
|
||||
for _, f := range t.def.Fields {
|
||||
res = append(res, InputValue{
|
||||
Name: f.Name,
|
||||
Description: f.Description,
|
||||
Type: WrapTypeFromType(t.schema, f.Type),
|
||||
DefaultValue: defaultValue(f.DefaultValue),
|
||||
})
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func defaultValue(value *ast.Value) *string {
|
||||
if value == nil {
|
||||
return nil
|
||||
}
|
||||
val := value.String()
|
||||
return &val
|
||||
}
|
||||
|
||||
func (t *Type) Interfaces() []Type {
|
||||
if t.def == nil || t.def.Kind != ast.Object {
|
||||
return []Type{}
|
||||
}
|
||||
|
||||
res := []Type{}
|
||||
for _, intf := range t.def.Interfaces {
|
||||
res = append(res, *WrapTypeFromDef(t.schema, t.schema.Types[intf]))
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func (t *Type) PossibleTypes() []Type {
|
||||
if t.def == nil || (t.def.Kind != ast.Interface && t.def.Kind != ast.Union) {
|
||||
return []Type{}
|
||||
}
|
||||
|
||||
res := []Type{}
|
||||
for _, pt := range t.schema.GetPossibleTypes(t.def) {
|
||||
res = append(res, *WrapTypeFromDef(t.schema, pt))
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (t *Type) EnumValues(includeDeprecated bool) []EnumValue {
|
||||
if t.def == nil || t.def.Kind != ast.Enum {
|
||||
return []EnumValue{}
|
||||
}
|
||||
|
||||
res := []EnumValue{}
|
||||
for _, val := range t.def.EnumValues {
|
||||
res = append(res, EnumValue{
|
||||
Name: val.Name,
|
||||
Description: val.Description,
|
||||
deprecation: val.Directives.ForName("deprecated"),
|
||||
})
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (t *Type) OfType() *Type {
|
||||
if t.typ == nil {
|
||||
return nil
|
||||
}
|
||||
if t.typ.NonNull {
|
||||
// fake non null nodes
|
||||
cpy := *t.typ
|
||||
cpy.NonNull = false
|
||||
|
||||
return WrapTypeFromType(t.schema, &cpy)
|
||||
}
|
||||
return WrapTypeFromType(t.schema, t.typ.Elem)
|
||||
}
|
||||
52
vendor/github.com/99designs/gqlgen/graphql/jsonw.go
generated
vendored
52
vendor/github.com/99designs/gqlgen/graphql/jsonw.go
generated
vendored
|
|
@ -1,52 +0,0 @@
|
|||
package graphql
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
var nullLit = []byte(`null`)
|
||||
var trueLit = []byte(`true`)
|
||||
var falseLit = []byte(`false`)
|
||||
var openBrace = []byte(`{`)
|
||||
var closeBrace = []byte(`}`)
|
||||
var openBracket = []byte(`[`)
|
||||
var closeBracket = []byte(`]`)
|
||||
var colon = []byte(`:`)
|
||||
var comma = []byte(`,`)
|
||||
|
||||
var Null = &lit{nullLit}
|
||||
var True = &lit{trueLit}
|
||||
var False = &lit{falseLit}
|
||||
|
||||
type Marshaler interface {
|
||||
MarshalGQL(w io.Writer)
|
||||
}
|
||||
|
||||
type Unmarshaler interface {
|
||||
UnmarshalGQL(v interface{}) error
|
||||
}
|
||||
|
||||
type WriterFunc func(writer io.Writer)
|
||||
|
||||
func (f WriterFunc) MarshalGQL(w io.Writer) {
|
||||
f(w)
|
||||
}
|
||||
|
||||
type Array []Marshaler
|
||||
|
||||
func (a Array) MarshalGQL(writer io.Writer) {
|
||||
writer.Write(openBracket)
|
||||
for i, val := range a {
|
||||
if i != 0 {
|
||||
writer.Write(comma)
|
||||
}
|
||||
val.MarshalGQL(writer)
|
||||
}
|
||||
writer.Write(closeBracket)
|
||||
}
|
||||
|
||||
type lit struct{ b []byte }
|
||||
|
||||
func (l lit) MarshalGQL(w io.Writer) {
|
||||
w.Write(l.b)
|
||||
}
|
||||
24
vendor/github.com/99designs/gqlgen/graphql/map.go
generated
vendored
24
vendor/github.com/99designs/gqlgen/graphql/map.go
generated
vendored
|
|
@ -1,24 +0,0 @@
|
|||
package graphql
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
func MarshalMap(val map[string]interface{}) Marshaler {
|
||||
return WriterFunc(func(w io.Writer) {
|
||||
err := json.NewEncoder(w).Encode(val)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func UnmarshalMap(v interface{}) (map[string]interface{}, error) {
|
||||
if m, ok := v.(map[string]interface{}); ok {
|
||||
return m, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("%T is not a map", v)
|
||||
}
|
||||
14
vendor/github.com/99designs/gqlgen/graphql/oneshot.go
generated
vendored
14
vendor/github.com/99designs/gqlgen/graphql/oneshot.go
generated
vendored
|
|
@ -1,14 +0,0 @@
|
|||
package graphql
|
||||
|
||||
func OneShot(resp *Response) func() *Response {
|
||||
var oneshot bool
|
||||
|
||||
return func() *Response {
|
||||
if oneshot {
|
||||
return nil
|
||||
}
|
||||
oneshot = true
|
||||
|
||||
return resp
|
||||
}
|
||||
}
|
||||
19
vendor/github.com/99designs/gqlgen/graphql/recovery.go
generated
vendored
19
vendor/github.com/99designs/gqlgen/graphql/recovery.go
generated
vendored
|
|
@ -1,19 +0,0 @@
|
|||
package graphql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime/debug"
|
||||
)
|
||||
|
||||
type RecoverFunc func(ctx context.Context, err interface{}) (userMessage error)
|
||||
|
||||
func DefaultRecover(ctx context.Context, err interface{}) error {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
fmt.Fprintln(os.Stderr)
|
||||
debug.PrintStack()
|
||||
|
||||
return errors.New("internal system error")
|
||||
}
|
||||
24
vendor/github.com/99designs/gqlgen/graphql/response.go
generated
vendored
24
vendor/github.com/99designs/gqlgen/graphql/response.go
generated
vendored
|
|
@ -1,24 +0,0 @@
|
|||
package graphql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/vektah/gqlparser/gqlerror"
|
||||
)
|
||||
|
||||
// Errors are intentionally serialized first based on the advice in
|
||||
// https://github.com/facebook/graphql/commit/7b40390d48680b15cb93e02d46ac5eb249689876#diff-757cea6edf0288677a9eea4cfc801d87R107
|
||||
// and https://github.com/facebook/graphql/pull/384
|
||||
type Response struct {
|
||||
Errors gqlerror.List `json:"errors,omitempty"`
|
||||
Data json.RawMessage `json:"data"`
|
||||
Extensions map[string]interface{} `json:"extensions,omitempty"`
|
||||
}
|
||||
|
||||
func ErrorResponse(ctx context.Context, messagef string, args ...interface{}) *Response {
|
||||
return &Response{
|
||||
Errors: gqlerror.List{{Message: fmt.Sprintf(messagef, args...)}},
|
||||
}
|
||||
}
|
||||
7
vendor/github.com/99designs/gqlgen/graphql/root.go
generated
vendored
7
vendor/github.com/99designs/gqlgen/graphql/root.go
generated
vendored
|
|
@ -1,7 +0,0 @@
|
|||
package graphql
|
||||
|
||||
type Query struct{}
|
||||
|
||||
type Mutation struct{}
|
||||
|
||||
type Subscription struct{}
|
||||
68
vendor/github.com/99designs/gqlgen/graphql/string.go
generated
vendored
68
vendor/github.com/99designs/gqlgen/graphql/string.go
generated
vendored
|
|
@ -1,68 +0,0 @@
|
|||
package graphql
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const encodeHex = "0123456789ABCDEF"
|
||||
|
||||
func MarshalString(s string) Marshaler {
|
||||
return WriterFunc(func(w io.Writer) {
|
||||
writeQuotedString(w, s)
|
||||
})
|
||||
}
|
||||
|
||||
func writeQuotedString(w io.Writer, s string) {
|
||||
start := 0
|
||||
io.WriteString(w, `"`)
|
||||
|
||||
for i, c := range s {
|
||||
if c < 0x20 || c == '\\' || c == '"' {
|
||||
io.WriteString(w, s[start:i])
|
||||
|
||||
switch c {
|
||||
case '\t':
|
||||
io.WriteString(w, `\t`)
|
||||
case '\r':
|
||||
io.WriteString(w, `\r`)
|
||||
case '\n':
|
||||
io.WriteString(w, `\n`)
|
||||
case '\\':
|
||||
io.WriteString(w, `\\`)
|
||||
case '"':
|
||||
io.WriteString(w, `\"`)
|
||||
default:
|
||||
io.WriteString(w, `\u00`)
|
||||
w.Write([]byte{encodeHex[c>>4], encodeHex[c&0xf]})
|
||||
}
|
||||
|
||||
start = i + 1
|
||||
}
|
||||
}
|
||||
|
||||
io.WriteString(w, s[start:])
|
||||
io.WriteString(w, `"`)
|
||||
}
|
||||
|
||||
func UnmarshalString(v interface{}) (string, error) {
|
||||
switch v := v.(type) {
|
||||
case string:
|
||||
return v, nil
|
||||
case int:
|
||||
return strconv.Itoa(v), nil
|
||||
case float64:
|
||||
return fmt.Sprintf("%f", v), nil
|
||||
case bool:
|
||||
if v {
|
||||
return "true", nil
|
||||
} else {
|
||||
return "false", nil
|
||||
}
|
||||
case nil:
|
||||
return "null", nil
|
||||
default:
|
||||
return "", fmt.Errorf("%T is not a string", v)
|
||||
}
|
||||
}
|
||||
25
vendor/github.com/99designs/gqlgen/graphql/time.go
generated
vendored
25
vendor/github.com/99designs/gqlgen/graphql/time.go
generated
vendored
|
|
@ -1,25 +0,0 @@
|
|||
package graphql
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
func MarshalTime(t time.Time) Marshaler {
|
||||
if t.IsZero() {
|
||||
return Null
|
||||
}
|
||||
|
||||
return WriterFunc(func(w io.Writer) {
|
||||
io.WriteString(w, strconv.Quote(t.Format(time.RFC3339)))
|
||||
})
|
||||
}
|
||||
|
||||
func UnmarshalTime(v interface{}) (time.Time, error) {
|
||||
if tmpStr, ok := v.(string); ok {
|
||||
return time.Parse(time.RFC3339, tmpStr)
|
||||
}
|
||||
return time.Time{}, errors.New("time should be RFC3339 formatted string")
|
||||
}
|
||||
58
vendor/github.com/99designs/gqlgen/graphql/tracer.go
generated
vendored
58
vendor/github.com/99designs/gqlgen/graphql/tracer.go
generated
vendored
|
|
@ -1,58 +0,0 @@
|
|||
package graphql
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
var _ Tracer = (*NopTracer)(nil)
|
||||
|
||||
type Tracer interface {
|
||||
StartOperationParsing(ctx context.Context) context.Context
|
||||
EndOperationParsing(ctx context.Context)
|
||||
StartOperationValidation(ctx context.Context) context.Context
|
||||
EndOperationValidation(ctx context.Context)
|
||||
StartOperationExecution(ctx context.Context) context.Context
|
||||
StartFieldExecution(ctx context.Context, field CollectedField) context.Context
|
||||
StartFieldResolverExecution(ctx context.Context, rc *ResolverContext) context.Context
|
||||
StartFieldChildExecution(ctx context.Context) context.Context
|
||||
EndFieldExecution(ctx context.Context)
|
||||
EndOperationExecution(ctx context.Context)
|
||||
}
|
||||
|
||||
type NopTracer struct{}
|
||||
|
||||
func (NopTracer) StartOperationParsing(ctx context.Context) context.Context {
|
||||
return ctx
|
||||
}
|
||||
|
||||
func (NopTracer) EndOperationParsing(ctx context.Context) {
|
||||
}
|
||||
|
||||
func (NopTracer) StartOperationValidation(ctx context.Context) context.Context {
|
||||
return ctx
|
||||
}
|
||||
|
||||
func (NopTracer) EndOperationValidation(ctx context.Context) {
|
||||
}
|
||||
|
||||
func (NopTracer) StartOperationExecution(ctx context.Context) context.Context {
|
||||
return ctx
|
||||
}
|
||||
|
||||
func (NopTracer) StartFieldExecution(ctx context.Context, field CollectedField) context.Context {
|
||||
return ctx
|
||||
}
|
||||
|
||||
func (NopTracer) StartFieldResolverExecution(ctx context.Context, rc *ResolverContext) context.Context {
|
||||
return ctx
|
||||
}
|
||||
|
||||
func (NopTracer) StartFieldChildExecution(ctx context.Context) context.Context {
|
||||
return ctx
|
||||
}
|
||||
|
||||
func (NopTracer) EndFieldExecution(ctx context.Context) {
|
||||
}
|
||||
|
||||
func (NopTracer) EndOperationExecution(ctx context.Context) {
|
||||
}
|
||||
26
vendor/github.com/99designs/gqlgen/graphql/upload.go
generated
vendored
26
vendor/github.com/99designs/gqlgen/graphql/upload.go
generated
vendored
|
|
@ -1,26 +0,0 @@
|
|||
package graphql
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
type Upload struct {
|
||||
File io.Reader
|
||||
Filename string
|
||||
Size int64
|
||||
}
|
||||
|
||||
func MarshalUpload(f Upload) Marshaler {
|
||||
return WriterFunc(func(w io.Writer) {
|
||||
io.Copy(w, f.File)
|
||||
})
|
||||
}
|
||||
|
||||
func UnmarshalUpload(v interface{}) (Upload, error) {
|
||||
upload, ok := v.(Upload)
|
||||
if !ok {
|
||||
return Upload{}, fmt.Errorf("%T is not an Upload", v)
|
||||
}
|
||||
return upload, nil
|
||||
}
|
||||
3
vendor/github.com/99designs/gqlgen/graphql/version.go
generated
vendored
3
vendor/github.com/99designs/gqlgen/graphql/version.go
generated
vendored
|
|
@ -1,3 +0,0 @@
|
|||
package graphql
|
||||
|
||||
const Version = "v0.9.0"
|
||||
57
vendor/github.com/99designs/gqlgen/handler/context.go
generated
vendored
57
vendor/github.com/99designs/gqlgen/handler/context.go
generated
vendored
|
|
@ -1,57 +0,0 @@
|
|||
package handler
|
||||
|
||||
import "context"
|
||||
|
||||
type key string
|
||||
|
||||
const (
|
||||
initpayload key = "ws_initpayload_context"
|
||||
)
|
||||
|
||||
// InitPayload is a structure that is parsed from the websocket init message payload. TO use
|
||||
// request headers for non-websocket, instead wrap the graphql handler in a middleware.
|
||||
type InitPayload map[string]interface{}
|
||||
|
||||
// GetString safely gets a string value from the payload. It returns an empty string if the
|
||||
// payload is nil or the value isn't set.
|
||||
func (payload InitPayload) GetString(key string) string {
|
||||
if payload == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
if value, ok := payload[key]; ok {
|
||||
res, _ := value.(string)
|
||||
return res
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// Authorization is a short hand for getting the Authorization header from the
|
||||
// payload.
|
||||
func (payload InitPayload) Authorization() string {
|
||||
if value := payload.GetString("Authorization"); value != "" {
|
||||
return value
|
||||
}
|
||||
|
||||
if value := payload.GetString("authorization"); value != "" {
|
||||
return value
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func withInitPayload(ctx context.Context, payload InitPayload) context.Context {
|
||||
return context.WithValue(ctx, initpayload, payload)
|
||||
}
|
||||
|
||||
// GetInitPayload gets a map of the data sent with the connection_init message, which is used by
|
||||
// graphql clients as a stand-in for HTTP headers.
|
||||
func GetInitPayload(ctx context.Context) InitPayload {
|
||||
payload, ok := ctx.Value(initpayload).(InitPayload)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
return payload
|
||||
}
|
||||
709
vendor/github.com/99designs/gqlgen/handler/graphql.go
generated
vendored
709
vendor/github.com/99designs/gqlgen/handler/graphql.go
generated
vendored
|
|
@ -1,709 +0,0 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"mime"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/99designs/gqlgen/complexity"
|
||||
"github.com/99designs/gqlgen/graphql"
|
||||
"github.com/gorilla/websocket"
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
"github.com/vektah/gqlparser/ast"
|
||||
"github.com/vektah/gqlparser/gqlerror"
|
||||
"github.com/vektah/gqlparser/parser"
|
||||
"github.com/vektah/gqlparser/validator"
|
||||
)
|
||||
|
||||
type params struct {
|
||||
Query string `json:"query"`
|
||||
OperationName string `json:"operationName"`
|
||||
Variables map[string]interface{} `json:"variables"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
cacheSize int
|
||||
upgrader websocket.Upgrader
|
||||
recover graphql.RecoverFunc
|
||||
errorPresenter graphql.ErrorPresenterFunc
|
||||
resolverHook graphql.FieldMiddleware
|
||||
requestHook graphql.RequestMiddleware
|
||||
tracer graphql.Tracer
|
||||
complexityLimit int
|
||||
complexityLimitFunc graphql.ComplexityLimitFunc
|
||||
disableIntrospection bool
|
||||
connectionKeepAlivePingInterval time.Duration
|
||||
uploadMaxMemory int64
|
||||
uploadMaxSize int64
|
||||
}
|
||||
|
||||
func (c *Config) newRequestContext(es graphql.ExecutableSchema, doc *ast.QueryDocument, op *ast.OperationDefinition, query string, variables map[string]interface{}) *graphql.RequestContext {
|
||||
reqCtx := graphql.NewRequestContext(doc, query, variables)
|
||||
reqCtx.DisableIntrospection = c.disableIntrospection
|
||||
|
||||
if hook := c.recover; hook != nil {
|
||||
reqCtx.Recover = hook
|
||||
}
|
||||
|
||||
if hook := c.errorPresenter; hook != nil {
|
||||
reqCtx.ErrorPresenter = hook
|
||||
}
|
||||
|
||||
if hook := c.resolverHook; hook != nil {
|
||||
reqCtx.ResolverMiddleware = hook
|
||||
}
|
||||
|
||||
if hook := c.requestHook; hook != nil {
|
||||
reqCtx.RequestMiddleware = hook
|
||||
}
|
||||
|
||||
if hook := c.tracer; hook != nil {
|
||||
reqCtx.Tracer = hook
|
||||
}
|
||||
|
||||
if c.complexityLimit > 0 || c.complexityLimitFunc != nil {
|
||||
reqCtx.ComplexityLimit = c.complexityLimit
|
||||
operationComplexity := complexity.Calculate(es, op, variables)
|
||||
reqCtx.OperationComplexity = operationComplexity
|
||||
}
|
||||
|
||||
return reqCtx
|
||||
}
|
||||
|
||||
type Option func(cfg *Config)
|
||||
|
||||
func WebsocketUpgrader(upgrader websocket.Upgrader) Option {
|
||||
return func(cfg *Config) {
|
||||
cfg.upgrader = upgrader
|
||||
}
|
||||
}
|
||||
|
||||
func RecoverFunc(recover graphql.RecoverFunc) Option {
|
||||
return func(cfg *Config) {
|
||||
cfg.recover = recover
|
||||
}
|
||||
}
|
||||
|
||||
// ErrorPresenter transforms errors found while resolving into errors that will be returned to the user. It provides
|
||||
// a good place to add any extra fields, like error.type, that might be desired by your frontend. Check the default
|
||||
// implementation in graphql.DefaultErrorPresenter for an example.
|
||||
func ErrorPresenter(f graphql.ErrorPresenterFunc) Option {
|
||||
return func(cfg *Config) {
|
||||
cfg.errorPresenter = f
|
||||
}
|
||||
}
|
||||
|
||||
// IntrospectionEnabled = false will forbid clients from calling introspection endpoints. Can be useful in prod when you dont
|
||||
// want clients introspecting the full schema.
|
||||
func IntrospectionEnabled(enabled bool) Option {
|
||||
return func(cfg *Config) {
|
||||
cfg.disableIntrospection = !enabled
|
||||
}
|
||||
}
|
||||
|
||||
// ComplexityLimit sets a maximum query complexity that is allowed to be executed.
|
||||
// If a query is submitted that exceeds the limit, a 422 status code will be returned.
|
||||
func ComplexityLimit(limit int) Option {
|
||||
return func(cfg *Config) {
|
||||
cfg.complexityLimit = limit
|
||||
}
|
||||
}
|
||||
|
||||
// ComplexityLimitFunc allows you to define a function to dynamically set the maximum query complexity that is allowed
|
||||
// to be executed.
|
||||
// If a query is submitted that exceeds the limit, a 422 status code will be returned.
|
||||
func ComplexityLimitFunc(complexityLimitFunc graphql.ComplexityLimitFunc) Option {
|
||||
return func(cfg *Config) {
|
||||
cfg.complexityLimitFunc = complexityLimitFunc
|
||||
}
|
||||
}
|
||||
|
||||
// ResolverMiddleware allows you to define a function that will be called around every resolver,
|
||||
// useful for logging.
|
||||
func ResolverMiddleware(middleware graphql.FieldMiddleware) Option {
|
||||
return func(cfg *Config) {
|
||||
if cfg.resolverHook == nil {
|
||||
cfg.resolverHook = middleware
|
||||
return
|
||||
}
|
||||
|
||||
lastResolve := cfg.resolverHook
|
||||
cfg.resolverHook = func(ctx context.Context, next graphql.Resolver) (res interface{}, err error) {
|
||||
return lastResolve(ctx, func(ctx context.Context) (res interface{}, err error) {
|
||||
return middleware(ctx, next)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// RequestMiddleware allows you to define a function that will be called around the root request,
|
||||
// after the query has been parsed. This is useful for logging
|
||||
func RequestMiddleware(middleware graphql.RequestMiddleware) Option {
|
||||
return func(cfg *Config) {
|
||||
if cfg.requestHook == nil {
|
||||
cfg.requestHook = middleware
|
||||
return
|
||||
}
|
||||
|
||||
lastResolve := cfg.requestHook
|
||||
cfg.requestHook = func(ctx context.Context, next func(ctx context.Context) []byte) []byte {
|
||||
return lastResolve(ctx, func(ctx context.Context) []byte {
|
||||
return middleware(ctx, next)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tracer allows you to add a request/resolver tracer that will be called around the root request,
|
||||
// calling resolver. This is useful for tracing
|
||||
func Tracer(tracer graphql.Tracer) Option {
|
||||
return func(cfg *Config) {
|
||||
if cfg.tracer == nil {
|
||||
cfg.tracer = tracer
|
||||
|
||||
} else {
|
||||
lastResolve := cfg.tracer
|
||||
cfg.tracer = &tracerWrapper{
|
||||
tracer1: lastResolve,
|
||||
tracer2: tracer,
|
||||
}
|
||||
}
|
||||
|
||||
opt := RequestMiddleware(func(ctx context.Context, next func(ctx context.Context) []byte) []byte {
|
||||
ctx = tracer.StartOperationExecution(ctx)
|
||||
resp := next(ctx)
|
||||
tracer.EndOperationExecution(ctx)
|
||||
|
||||
return resp
|
||||
})
|
||||
opt(cfg)
|
||||
}
|
||||
}
|
||||
|
||||
type tracerWrapper struct {
|
||||
tracer1 graphql.Tracer
|
||||
tracer2 graphql.Tracer
|
||||
}
|
||||
|
||||
func (tw *tracerWrapper) StartOperationParsing(ctx context.Context) context.Context {
|
||||
ctx = tw.tracer1.StartOperationParsing(ctx)
|
||||
ctx = tw.tracer2.StartOperationParsing(ctx)
|
||||
return ctx
|
||||
}
|
||||
|
||||
func (tw *tracerWrapper) EndOperationParsing(ctx context.Context) {
|
||||
tw.tracer2.EndOperationParsing(ctx)
|
||||
tw.tracer1.EndOperationParsing(ctx)
|
||||
}
|
||||
|
||||
func (tw *tracerWrapper) StartOperationValidation(ctx context.Context) context.Context {
|
||||
ctx = tw.tracer1.StartOperationValidation(ctx)
|
||||
ctx = tw.tracer2.StartOperationValidation(ctx)
|
||||
return ctx
|
||||
}
|
||||
|
||||
func (tw *tracerWrapper) EndOperationValidation(ctx context.Context) {
|
||||
tw.tracer2.EndOperationValidation(ctx)
|
||||
tw.tracer1.EndOperationValidation(ctx)
|
||||
}
|
||||
|
||||
func (tw *tracerWrapper) StartOperationExecution(ctx context.Context) context.Context {
|
||||
ctx = tw.tracer1.StartOperationExecution(ctx)
|
||||
ctx = tw.tracer2.StartOperationExecution(ctx)
|
||||
return ctx
|
||||
}
|
||||
|
||||
func (tw *tracerWrapper) StartFieldExecution(ctx context.Context, field graphql.CollectedField) context.Context {
|
||||
ctx = tw.tracer1.StartFieldExecution(ctx, field)
|
||||
ctx = tw.tracer2.StartFieldExecution(ctx, field)
|
||||
return ctx
|
||||
}
|
||||
|
||||
func (tw *tracerWrapper) StartFieldResolverExecution(ctx context.Context, rc *graphql.ResolverContext) context.Context {
|
||||
ctx = tw.tracer1.StartFieldResolverExecution(ctx, rc)
|
||||
ctx = tw.tracer2.StartFieldResolverExecution(ctx, rc)
|
||||
return ctx
|
||||
}
|
||||
|
||||
func (tw *tracerWrapper) StartFieldChildExecution(ctx context.Context) context.Context {
|
||||
ctx = tw.tracer1.StartFieldChildExecution(ctx)
|
||||
ctx = tw.tracer2.StartFieldChildExecution(ctx)
|
||||
return ctx
|
||||
}
|
||||
|
||||
func (tw *tracerWrapper) EndFieldExecution(ctx context.Context) {
|
||||
tw.tracer2.EndFieldExecution(ctx)
|
||||
tw.tracer1.EndFieldExecution(ctx)
|
||||
}
|
||||
|
||||
func (tw *tracerWrapper) EndOperationExecution(ctx context.Context) {
|
||||
tw.tracer2.EndOperationExecution(ctx)
|
||||
tw.tracer1.EndOperationExecution(ctx)
|
||||
}
|
||||
|
||||
// CacheSize sets the maximum size of the query cache.
|
||||
// If size is less than or equal to 0, the cache is disabled.
|
||||
func CacheSize(size int) Option {
|
||||
return func(cfg *Config) {
|
||||
cfg.cacheSize = size
|
||||
}
|
||||
}
|
||||
|
||||
// UploadMaxSize sets the maximum number of bytes used to parse a request body
|
||||
// as multipart/form-data.
|
||||
func UploadMaxSize(size int64) Option {
|
||||
return func(cfg *Config) {
|
||||
cfg.uploadMaxSize = size
|
||||
}
|
||||
}
|
||||
|
||||
// UploadMaxMemory sets the maximum number of bytes used to parse a request body
|
||||
// as multipart/form-data in memory, with the remainder stored on disk in
|
||||
// temporary files.
|
||||
func UploadMaxMemory(size int64) Option {
|
||||
return func(cfg *Config) {
|
||||
cfg.uploadMaxMemory = size
|
||||
}
|
||||
}
|
||||
|
||||
// WebsocketKeepAliveDuration allows you to reconfigure the keepalive behavior.
|
||||
// By default, keepalive is enabled with a DefaultConnectionKeepAlivePingInterval
|
||||
// duration. Set handler.connectionKeepAlivePingInterval = 0 to disable keepalive
|
||||
// altogether.
|
||||
func WebsocketKeepAliveDuration(duration time.Duration) Option {
|
||||
return func(cfg *Config) {
|
||||
cfg.connectionKeepAlivePingInterval = duration
|
||||
}
|
||||
}
|
||||
|
||||
const DefaultCacheSize = 1000
|
||||
const DefaultConnectionKeepAlivePingInterval = 25 * time.Second
|
||||
|
||||
// DefaultUploadMaxMemory is the maximum number of bytes used to parse a request body
|
||||
// as multipart/form-data in memory, with the remainder stored on disk in
|
||||
// temporary files.
|
||||
const DefaultUploadMaxMemory = 32 << 20
|
||||
|
||||
// DefaultUploadMaxSize is maximum number of bytes used to parse a request body
|
||||
// as multipart/form-data.
|
||||
const DefaultUploadMaxSize = 32 << 20
|
||||
|
||||
func GraphQL(exec graphql.ExecutableSchema, options ...Option) http.HandlerFunc {
|
||||
cfg := &Config{
|
||||
cacheSize: DefaultCacheSize,
|
||||
uploadMaxMemory: DefaultUploadMaxMemory,
|
||||
uploadMaxSize: DefaultUploadMaxSize,
|
||||
connectionKeepAlivePingInterval: DefaultConnectionKeepAlivePingInterval,
|
||||
upgrader: websocket.Upgrader{
|
||||
ReadBufferSize: 1024,
|
||||
WriteBufferSize: 1024,
|
||||
},
|
||||
}
|
||||
|
||||
for _, option := range options {
|
||||
option(cfg)
|
||||
}
|
||||
|
||||
var cache *lru.Cache
|
||||
if cfg.cacheSize > 0 {
|
||||
var err error
|
||||
cache, err = lru.New(cfg.cacheSize)
|
||||
if err != nil {
|
||||
// An error is only returned for non-positive cache size
|
||||
// and we already checked for that.
|
||||
panic("unexpected error creating cache: " + err.Error())
|
||||
}
|
||||
}
|
||||
if cfg.tracer == nil {
|
||||
cfg.tracer = &graphql.NopTracer{}
|
||||
}
|
||||
|
||||
handler := &graphqlHandler{
|
||||
cfg: cfg,
|
||||
cache: cache,
|
||||
exec: exec,
|
||||
}
|
||||
|
||||
return handler.ServeHTTP
|
||||
}
|
||||
|
||||
var _ http.Handler = (*graphqlHandler)(nil)
|
||||
|
||||
type graphqlHandler struct {
|
||||
cfg *Config
|
||||
cache *lru.Cache
|
||||
exec graphql.ExecutableSchema
|
||||
}
|
||||
|
||||
func (gh *graphqlHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == http.MethodOptions {
|
||||
w.Header().Set("Allow", "OPTIONS, GET, POST")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
return
|
||||
}
|
||||
|
||||
if strings.Contains(r.Header.Get("Upgrade"), "websocket") {
|
||||
connectWs(gh.exec, w, r, gh.cfg, gh.cache)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
var reqParams params
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
reqParams.Query = r.URL.Query().Get("query")
|
||||
reqParams.OperationName = r.URL.Query().Get("operationName")
|
||||
|
||||
if variables := r.URL.Query().Get("variables"); variables != "" {
|
||||
if err := jsonDecode(strings.NewReader(variables), &reqParams.Variables); err != nil {
|
||||
sendErrorf(w, http.StatusBadRequest, "variables could not be decoded")
|
||||
return
|
||||
}
|
||||
}
|
||||
case http.MethodPost:
|
||||
mediaType, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
|
||||
if err != nil {
|
||||
sendErrorf(w, http.StatusBadRequest, "error parsing request Content-Type")
|
||||
return
|
||||
}
|
||||
|
||||
switch mediaType {
|
||||
case "application/json":
|
||||
if err := jsonDecode(r.Body, &reqParams); err != nil {
|
||||
sendErrorf(w, http.StatusBadRequest, "json body could not be decoded: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
case "multipart/form-data":
|
||||
var closers []io.Closer
|
||||
var tmpFiles []string
|
||||
defer func() {
|
||||
for i := len(closers) - 1; 0 <= i; i-- {
|
||||
_ = closers[i].Close()
|
||||
}
|
||||
for _, tmpFile := range tmpFiles {
|
||||
_ = os.Remove(tmpFile)
|
||||
}
|
||||
}()
|
||||
if err := processMultipart(w, r, &reqParams, &closers, &tmpFiles, gh.cfg.uploadMaxSize, gh.cfg.uploadMaxMemory); err != nil {
|
||||
sendErrorf(w, http.StatusBadRequest, "multipart body could not be decoded: "+err.Error())
|
||||
return
|
||||
}
|
||||
default:
|
||||
sendErrorf(w, http.StatusBadRequest, "unsupported Content-Type: "+mediaType)
|
||||
return
|
||||
}
|
||||
default:
|
||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
ctx := r.Context()
|
||||
|
||||
var doc *ast.QueryDocument
|
||||
var cacheHit bool
|
||||
if gh.cache != nil {
|
||||
val, ok := gh.cache.Get(reqParams.Query)
|
||||
if ok {
|
||||
doc = val.(*ast.QueryDocument)
|
||||
cacheHit = true
|
||||
}
|
||||
}
|
||||
|
||||
ctx, doc, gqlErr := gh.parseOperation(ctx, &parseOperationArgs{
|
||||
Query: reqParams.Query,
|
||||
CachedDoc: doc,
|
||||
})
|
||||
if gqlErr != nil {
|
||||
sendError(w, http.StatusUnprocessableEntity, gqlErr)
|
||||
return
|
||||
}
|
||||
|
||||
ctx, op, vars, listErr := gh.validateOperation(ctx, &validateOperationArgs{
|
||||
Doc: doc,
|
||||
OperationName: reqParams.OperationName,
|
||||
CacheHit: cacheHit,
|
||||
R: r,
|
||||
Variables: reqParams.Variables,
|
||||
})
|
||||
if len(listErr) != 0 {
|
||||
sendError(w, http.StatusUnprocessableEntity, listErr...)
|
||||
return
|
||||
}
|
||||
|
||||
if gh.cache != nil && !cacheHit {
|
||||
gh.cache.Add(reqParams.Query, doc)
|
||||
}
|
||||
|
||||
reqCtx := gh.cfg.newRequestContext(gh.exec, doc, op, reqParams.Query, vars)
|
||||
ctx = graphql.WithRequestContext(ctx, reqCtx)
|
||||
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
userErr := reqCtx.Recover(ctx, err)
|
||||
sendErrorf(w, http.StatusUnprocessableEntity, userErr.Error())
|
||||
}
|
||||
}()
|
||||
|
||||
if gh.cfg.complexityLimitFunc != nil {
|
||||
reqCtx.ComplexityLimit = gh.cfg.complexityLimitFunc(ctx)
|
||||
}
|
||||
|
||||
if reqCtx.ComplexityLimit > 0 && reqCtx.OperationComplexity > reqCtx.ComplexityLimit {
|
||||
sendErrorf(w, http.StatusUnprocessableEntity, "operation has complexity %d, which exceeds the limit of %d", reqCtx.OperationComplexity, reqCtx.ComplexityLimit)
|
||||
return
|
||||
}
|
||||
|
||||
switch op.Operation {
|
||||
case ast.Query:
|
||||
b, err := json.Marshal(gh.exec.Query(ctx, op))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
w.Write(b)
|
||||
case ast.Mutation:
|
||||
b, err := json.Marshal(gh.exec.Mutation(ctx, op))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
w.Write(b)
|
||||
default:
|
||||
sendErrorf(w, http.StatusBadRequest, "unsupported operation type")
|
||||
}
|
||||
}
|
||||
|
||||
type parseOperationArgs struct {
|
||||
Query string
|
||||
CachedDoc *ast.QueryDocument
|
||||
}
|
||||
|
||||
func (gh *graphqlHandler) parseOperation(ctx context.Context, args *parseOperationArgs) (context.Context, *ast.QueryDocument, *gqlerror.Error) {
|
||||
ctx = gh.cfg.tracer.StartOperationParsing(ctx)
|
||||
defer func() { gh.cfg.tracer.EndOperationParsing(ctx) }()
|
||||
|
||||
if args.CachedDoc != nil {
|
||||
return ctx, args.CachedDoc, nil
|
||||
}
|
||||
|
||||
doc, gqlErr := parser.ParseQuery(&ast.Source{Input: args.Query})
|
||||
if gqlErr != nil {
|
||||
return ctx, nil, gqlErr
|
||||
}
|
||||
|
||||
return ctx, doc, nil
|
||||
}
|
||||
|
||||
type validateOperationArgs struct {
|
||||
Doc *ast.QueryDocument
|
||||
OperationName string
|
||||
CacheHit bool
|
||||
R *http.Request
|
||||
Variables map[string]interface{}
|
||||
}
|
||||
|
||||
func (gh *graphqlHandler) validateOperation(ctx context.Context, args *validateOperationArgs) (context.Context, *ast.OperationDefinition, map[string]interface{}, gqlerror.List) {
|
||||
ctx = gh.cfg.tracer.StartOperationValidation(ctx)
|
||||
defer func() { gh.cfg.tracer.EndOperationValidation(ctx) }()
|
||||
|
||||
if !args.CacheHit {
|
||||
listErr := validator.Validate(gh.exec.Schema(), args.Doc)
|
||||
if len(listErr) != 0 {
|
||||
return ctx, nil, nil, listErr
|
||||
}
|
||||
}
|
||||
|
||||
op := args.Doc.Operations.ForName(args.OperationName)
|
||||
if op == nil {
|
||||
return ctx, nil, nil, gqlerror.List{gqlerror.Errorf("operation %s not found", args.OperationName)}
|
||||
}
|
||||
|
||||
if op.Operation != ast.Query && args.R.Method == http.MethodGet {
|
||||
return ctx, nil, nil, gqlerror.List{gqlerror.Errorf("GET requests only allow query operations")}
|
||||
}
|
||||
|
||||
vars, err := validator.VariableValues(gh.exec.Schema(), op, args.Variables)
|
||||
if err != nil {
|
||||
return ctx, nil, nil, gqlerror.List{err}
|
||||
}
|
||||
|
||||
return ctx, op, vars, nil
|
||||
}
|
||||
|
||||
func jsonDecode(r io.Reader, val interface{}) error {
|
||||
dec := json.NewDecoder(r)
|
||||
dec.UseNumber()
|
||||
return dec.Decode(val)
|
||||
}
|
||||
|
||||
func sendError(w http.ResponseWriter, code int, errors ...*gqlerror.Error) {
|
||||
w.WriteHeader(code)
|
||||
b, err := json.Marshal(&graphql.Response{Errors: errors})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
w.Write(b)
|
||||
}
|
||||
|
||||
func sendErrorf(w http.ResponseWriter, code int, format string, args ...interface{}) {
|
||||
sendError(w, code, &gqlerror.Error{Message: fmt.Sprintf(format, args...)})
|
||||
}
|
||||
|
||||
type bytesReader struct {
|
||||
s *[]byte
|
||||
i int64 // current reading index
|
||||
prevRune int // index of previous rune; or < 0
|
||||
}
|
||||
|
||||
func (r *bytesReader) Read(b []byte) (n int, err error) {
|
||||
if r.s == nil {
|
||||
return 0, errors.New("byte slice pointer is nil")
|
||||
}
|
||||
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 processMultipart(w http.ResponseWriter, r *http.Request, request *params, closers *[]io.Closer, tmpFiles *[]string, uploadMaxSize, uploadMaxMemory int64) error {
|
||||
var err error
|
||||
if r.ContentLength > uploadMaxSize {
|
||||
return errors.New("failed to parse multipart form, request body too large")
|
||||
}
|
||||
r.Body = http.MaxBytesReader(w, r.Body, uploadMaxSize)
|
||||
if err = r.ParseMultipartForm(uploadMaxMemory); err != nil {
|
||||
if strings.Contains(err.Error(), "request body too large") {
|
||||
return errors.New("failed to parse multipart form, request body too large")
|
||||
}
|
||||
return errors.New("failed to parse multipart form")
|
||||
}
|
||||
*closers = append(*closers, r.Body)
|
||||
|
||||
if err = jsonDecode(strings.NewReader(r.Form.Get("operations")), &request); err != nil {
|
||||
return errors.New("operations form field could not be decoded")
|
||||
}
|
||||
|
||||
var uploadsMap = map[string][]string{}
|
||||
if err = json.Unmarshal([]byte(r.Form.Get("map")), &uploadsMap); err != nil {
|
||||
return errors.New("map form field could not be decoded")
|
||||
}
|
||||
|
||||
var upload graphql.Upload
|
||||
for key, paths := range uploadsMap {
|
||||
if len(paths) == 0 {
|
||||
return fmt.Errorf("invalid empty operations paths list for key %s", key)
|
||||
}
|
||||
file, header, err := r.FormFile(key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get key %s from form", key)
|
||||
}
|
||||
*closers = append(*closers, file)
|
||||
|
||||
if len(paths) == 1 {
|
||||
upload = graphql.Upload{
|
||||
File: file,
|
||||
Size: header.Size,
|
||||
Filename: header.Filename,
|
||||
}
|
||||
err = addUploadToOperations(request, upload, key, paths[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if r.ContentLength < uploadMaxMemory {
|
||||
fileBytes, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read file for key %s", key)
|
||||
}
|
||||
for _, path := range paths {
|
||||
upload = graphql.Upload{
|
||||
File: &bytesReader{s: &fileBytes, i: 0, prevRune: -1},
|
||||
Size: header.Size,
|
||||
Filename: header.Filename,
|
||||
}
|
||||
err = addUploadToOperations(request, upload, key, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tmpFile, err := ioutil.TempFile(os.TempDir(), "gqlgen-")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create temp file for key %s", key)
|
||||
}
|
||||
tmpName := tmpFile.Name()
|
||||
*tmpFiles = append(*tmpFiles, tmpName)
|
||||
_, err = io.Copy(tmpFile, file)
|
||||
if err != nil {
|
||||
if err := tmpFile.Close(); err != nil {
|
||||
return fmt.Errorf("failed to copy to temp file and close temp file for key %s", key)
|
||||
}
|
||||
return fmt.Errorf("failed to copy to temp file for key %s", key)
|
||||
}
|
||||
if err := tmpFile.Close(); err != nil {
|
||||
return fmt.Errorf("failed to close temp file for key %s", key)
|
||||
}
|
||||
for _, path := range paths {
|
||||
pathTmpFile, err := os.Open(tmpName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open temp file for key %s", key)
|
||||
}
|
||||
*closers = append(*closers, pathTmpFile)
|
||||
upload = graphql.Upload{
|
||||
File: pathTmpFile,
|
||||
Size: header.Size,
|
||||
Filename: header.Filename,
|
||||
}
|
||||
err = addUploadToOperations(request, upload, key, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func addUploadToOperations(request *params, upload graphql.Upload, key, path string) error {
|
||||
if !strings.HasPrefix(path, "variables.") {
|
||||
return fmt.Errorf("invalid operations paths for key %s", key)
|
||||
}
|
||||
|
||||
var ptr interface{} = request.Variables
|
||||
parts := strings.Split(path, ".")
|
||||
|
||||
// skip the first part (variables) because we started there
|
||||
for i, p := range parts[1:] {
|
||||
last := i == len(parts)-2
|
||||
if ptr == nil {
|
||||
return fmt.Errorf("path is missing \"variables.\" prefix, key: %s, path: %s", key, path)
|
||||
}
|
||||
if index, parseNbrErr := strconv.Atoi(p); parseNbrErr == nil {
|
||||
if last {
|
||||
ptr.([]interface{})[index] = upload
|
||||
} else {
|
||||
ptr = ptr.([]interface{})[index]
|
||||
}
|
||||
} else {
|
||||
if last {
|
||||
ptr.(map[string]interface{})[p] = upload
|
||||
} else {
|
||||
ptr = ptr.(map[string]interface{})[p]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
57
vendor/github.com/99designs/gqlgen/handler/mock.go
generated
vendored
57
vendor/github.com/99designs/gqlgen/handler/mock.go
generated
vendored
|
|
@ -1,57 +0,0 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/99designs/gqlgen/graphql"
|
||||
"github.com/vektah/gqlparser"
|
||||
"github.com/vektah/gqlparser/ast"
|
||||
)
|
||||
|
||||
type executableSchemaMock struct {
|
||||
MutationFunc func(ctx context.Context, op *ast.OperationDefinition) *graphql.Response
|
||||
}
|
||||
|
||||
var _ graphql.ExecutableSchema = &executableSchemaMock{}
|
||||
|
||||
func (e *executableSchemaMock) Schema() *ast.Schema {
|
||||
return gqlparser.MustLoadSchema(&ast.Source{Input: `
|
||||
schema { query: Query, mutation: Mutation }
|
||||
type Query {
|
||||
empty: String!
|
||||
}
|
||||
scalar Upload
|
||||
type File {
|
||||
id: Int!
|
||||
}
|
||||
input UploadFile {
|
||||
id: Int!
|
||||
file: Upload!
|
||||
}
|
||||
type Mutation {
|
||||
singleUpload(file: Upload!): File!
|
||||
singleUploadWithPayload(req: UploadFile!): File!
|
||||
multipleUpload(files: [Upload!]!): [File!]!
|
||||
multipleUploadWithPayload(req: [UploadFile!]!): [File!]!
|
||||
}
|
||||
`})
|
||||
}
|
||||
|
||||
func (e *executableSchemaMock) Complexity(typeName, field string, childComplexity int, args map[string]interface{}) (int, bool) {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
func (e *executableSchemaMock) Query(ctx context.Context, op *ast.OperationDefinition) *graphql.Response {
|
||||
return graphql.ErrorResponse(ctx, "queries are not supported")
|
||||
}
|
||||
|
||||
func (e *executableSchemaMock) Mutation(ctx context.Context, op *ast.OperationDefinition) *graphql.Response {
|
||||
return e.MutationFunc(ctx, op)
|
||||
}
|
||||
|
||||
func (e *executableSchemaMock) Subscription(ctx context.Context, op *ast.OperationDefinition) func() *graphql.Response {
|
||||
return func() *graphql.Response {
|
||||
<-ctx.Done()
|
||||
return nil
|
||||
}
|
||||
}
|
||||
61
vendor/github.com/99designs/gqlgen/handler/playground.go
generated
vendored
61
vendor/github.com/99designs/gqlgen/handler/playground.go
generated
vendored
|
|
@ -1,61 +0,0 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
var page = template.Must(template.New("graphiql").Parse(`<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8/>
|
||||
<meta name="viewport" content="user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, minimal-ui">
|
||||
<link rel="shortcut icon" href="https://graphcool-playground.netlify.com/favicon.png">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/graphql-playground-react@{{ .version }}/build/static/css/index.css"
|
||||
integrity="{{ .cssSRI }}" crossorigin="anonymous"/>
|
||||
<link rel="shortcut icon" href="https://cdn.jsdelivr.net/npm/graphql-playground-react@{{ .version }}/build/favicon.png"
|
||||
integrity="{{ .faviconSRI }}" crossorigin="anonymous"/>
|
||||
<script src="https://cdn.jsdelivr.net/npm/graphql-playground-react@{{ .version }}/build/static/js/middleware.js"
|
||||
integrity="{{ .jsSRI }}" crossorigin="anonymous"></script>
|
||||
<title>{{.title}}</title>
|
||||
</head>
|
||||
<body>
|
||||
<style type="text/css">
|
||||
html { font-family: "Open Sans", sans-serif; overflow: hidden; }
|
||||
body { margin: 0; background: #172a3a; }
|
||||
</style>
|
||||
<div id="root"/>
|
||||
<script type="text/javascript">
|
||||
window.addEventListener('load', function (event) {
|
||||
const root = document.getElementById('root');
|
||||
root.classList.add('playgroundIn');
|
||||
const wsProto = location.protocol == 'https:' ? 'wss:' : 'ws:'
|
||||
GraphQLPlayground.init(root, {
|
||||
endpoint: location.protocol + '//' + location.host + '{{.endpoint}}',
|
||||
subscriptionsEndpoint: wsProto + '//' + location.host + '{{.endpoint }}',
|
||||
settings: {
|
||||
'request.credentials': 'same-origin'
|
||||
}
|
||||
})
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
`))
|
||||
|
||||
func Playground(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.7.20",
|
||||
"cssSRI": "sha256-cS9Vc2OBt9eUf4sykRWukeFYaInL29+myBmFDSa7F/U=",
|
||||
"faviconSRI": "sha256-GhTyE+McTU79R4+pRO6ih+4TfsTOrpPwD8ReKFzb3PM=",
|
||||
"jsSRI": "sha256-4QG1Uza2GgGdlBL3RCBCGtGeZB6bDbsw8OltCMGeJsA=",
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
51
vendor/github.com/99designs/gqlgen/handler/stub.go
generated
vendored
51
vendor/github.com/99designs/gqlgen/handler/stub.go
generated
vendored
|
|
@ -1,51 +0,0 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/99designs/gqlgen/graphql"
|
||||
"github.com/vektah/gqlparser"
|
||||
"github.com/vektah/gqlparser/ast"
|
||||
)
|
||||
|
||||
type executableSchemaStub struct {
|
||||
NextResp chan struct{}
|
||||
}
|
||||
|
||||
var _ graphql.ExecutableSchema = &executableSchemaStub{}
|
||||
|
||||
func (e *executableSchemaStub) Schema() *ast.Schema {
|
||||
return gqlparser.MustLoadSchema(&ast.Source{Input: `
|
||||
schema { query: Query }
|
||||
type Query {
|
||||
me: User!
|
||||
user(id: Int): User!
|
||||
}
|
||||
type User { name: String! }
|
||||
`})
|
||||
}
|
||||
|
||||
func (e *executableSchemaStub) Complexity(typeName, field string, childComplexity int, args map[string]interface{}) (int, bool) {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
func (e *executableSchemaStub) Query(ctx context.Context, op *ast.OperationDefinition) *graphql.Response {
|
||||
return &graphql.Response{Data: []byte(`{"name":"test"}`)}
|
||||
}
|
||||
|
||||
func (e *executableSchemaStub) Mutation(ctx context.Context, op *ast.OperationDefinition) *graphql.Response {
|
||||
return graphql.ErrorResponse(ctx, "mutations are not supported")
|
||||
}
|
||||
|
||||
func (e *executableSchemaStub) Subscription(ctx context.Context, op *ast.OperationDefinition) func() *graphql.Response {
|
||||
return func() *graphql.Response {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil
|
||||
case <-e.NextResp:
|
||||
return &graphql.Response{
|
||||
Data: []byte(`{"name":"test"}`),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
314
vendor/github.com/99designs/gqlgen/handler/websocket.go
generated
vendored
314
vendor/github.com/99designs/gqlgen/handler/websocket.go
generated
vendored
|
|
@ -1,314 +0,0 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/99designs/gqlgen/graphql"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/hashicorp/golang-lru"
|
||||
"github.com/vektah/gqlparser"
|
||||
"github.com/vektah/gqlparser/ast"
|
||||
"github.com/vektah/gqlparser/gqlerror"
|
||||
"github.com/vektah/gqlparser/validator"
|
||||
)
|
||||
|
||||
const (
|
||||
connectionInitMsg = "connection_init" // Client -> Server
|
||||
connectionTerminateMsg = "connection_terminate" // Client -> Server
|
||||
startMsg = "start" // Client -> Server
|
||||
stopMsg = "stop" // Client -> Server
|
||||
connectionAckMsg = "connection_ack" // Server -> Client
|
||||
connectionErrorMsg = "connection_error" // Server -> Client
|
||||
dataMsg = "data" // Server -> Client
|
||||
errorMsg = "error" // Server -> Client
|
||||
completeMsg = "complete" // Server -> Client
|
||||
connectionKeepAliveMsg = "ka" // Server -> Client
|
||||
)
|
||||
|
||||
type operationMessage struct {
|
||||
Payload json.RawMessage `json:"payload,omitempty"`
|
||||
ID string `json:"id,omitempty"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
type wsConnection struct {
|
||||
ctx context.Context
|
||||
conn *websocket.Conn
|
||||
exec graphql.ExecutableSchema
|
||||
active map[string]context.CancelFunc
|
||||
mu sync.Mutex
|
||||
cfg *Config
|
||||
cache *lru.Cache
|
||||
keepAliveTicker *time.Ticker
|
||||
|
||||
initPayload InitPayload
|
||||
}
|
||||
|
||||
func connectWs(exec graphql.ExecutableSchema, w http.ResponseWriter, r *http.Request, cfg *Config, cache *lru.Cache) {
|
||||
ws, err := cfg.upgrader.Upgrade(w, r, http.Header{
|
||||
"Sec-Websocket-Protocol": []string{"graphql-ws"},
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("unable to upgrade %T to websocket %s: ", w, err.Error())
|
||||
sendErrorf(w, http.StatusBadRequest, "unable to upgrade")
|
||||
return
|
||||
}
|
||||
|
||||
conn := wsConnection{
|
||||
active: map[string]context.CancelFunc{},
|
||||
exec: exec,
|
||||
conn: ws,
|
||||
ctx: r.Context(),
|
||||
cfg: cfg,
|
||||
cache: cache,
|
||||
}
|
||||
|
||||
if !conn.init() {
|
||||
return
|
||||
}
|
||||
|
||||
conn.run()
|
||||
}
|
||||
|
||||
func (c *wsConnection) init() bool {
|
||||
message := c.readOp()
|
||||
if message == nil {
|
||||
c.close(websocket.CloseProtocolError, "decoding error")
|
||||
return false
|
||||
}
|
||||
|
||||
switch message.Type {
|
||||
case connectionInitMsg:
|
||||
if len(message.Payload) > 0 {
|
||||
c.initPayload = make(InitPayload)
|
||||
err := json.Unmarshal(message.Payload, &c.initPayload)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
c.write(&operationMessage{Type: connectionAckMsg})
|
||||
case connectionTerminateMsg:
|
||||
c.close(websocket.CloseNormalClosure, "terminated")
|
||||
return false
|
||||
default:
|
||||
c.sendConnectionError("unexpected message %s", message.Type)
|
||||
c.close(websocket.CloseProtocolError, "unexpected message")
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *wsConnection) write(msg *operationMessage) {
|
||||
c.mu.Lock()
|
||||
c.conn.WriteJSON(msg)
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
func (c *wsConnection) run() {
|
||||
// We create a cancellation that will shutdown the keep-alive when we leave
|
||||
// this function.
|
||||
ctx, cancel := context.WithCancel(c.ctx)
|
||||
defer cancel()
|
||||
|
||||
// Create a timer that will fire every interval to keep the connection alive.
|
||||
if c.cfg.connectionKeepAlivePingInterval != 0 {
|
||||
c.mu.Lock()
|
||||
c.keepAliveTicker = time.NewTicker(c.cfg.connectionKeepAlivePingInterval)
|
||||
c.mu.Unlock()
|
||||
|
||||
go c.keepAlive(ctx)
|
||||
}
|
||||
|
||||
for {
|
||||
message := c.readOp()
|
||||
if message == nil {
|
||||
return
|
||||
}
|
||||
|
||||
switch message.Type {
|
||||
case startMsg:
|
||||
if !c.subscribe(message) {
|
||||
return
|
||||
}
|
||||
case stopMsg:
|
||||
c.mu.Lock()
|
||||
closer := c.active[message.ID]
|
||||
c.mu.Unlock()
|
||||
if closer == nil {
|
||||
c.sendError(message.ID, gqlerror.Errorf("%s is not running, cannot stop", message.ID))
|
||||
continue
|
||||
}
|
||||
|
||||
closer()
|
||||
case connectionTerminateMsg:
|
||||
c.close(websocket.CloseNormalClosure, "terminated")
|
||||
return
|
||||
default:
|
||||
c.sendConnectionError("unexpected message %s", message.Type)
|
||||
c.close(websocket.CloseProtocolError, "unexpected message")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *wsConnection) keepAlive(ctx context.Context) {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
c.keepAliveTicker.Stop()
|
||||
return
|
||||
case <-c.keepAliveTicker.C:
|
||||
c.write(&operationMessage{Type: connectionKeepAliveMsg})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *wsConnection) subscribe(message *operationMessage) bool {
|
||||
var reqParams params
|
||||
if err := jsonDecode(bytes.NewReader(message.Payload), &reqParams); err != nil {
|
||||
c.sendConnectionError("invalid json")
|
||||
return false
|
||||
}
|
||||
|
||||
var (
|
||||
doc *ast.QueryDocument
|
||||
cacheHit bool
|
||||
)
|
||||
if c.cache != nil {
|
||||
val, ok := c.cache.Get(reqParams.Query)
|
||||
if ok {
|
||||
doc = val.(*ast.QueryDocument)
|
||||
cacheHit = true
|
||||
}
|
||||
}
|
||||
if !cacheHit {
|
||||
var qErr gqlerror.List
|
||||
doc, qErr = gqlparser.LoadQuery(c.exec.Schema(), reqParams.Query)
|
||||
if qErr != nil {
|
||||
c.sendError(message.ID, qErr...)
|
||||
return true
|
||||
}
|
||||
if c.cache != nil {
|
||||
c.cache.Add(reqParams.Query, doc)
|
||||
}
|
||||
}
|
||||
|
||||
op := doc.Operations.ForName(reqParams.OperationName)
|
||||
if op == nil {
|
||||
c.sendError(message.ID, gqlerror.Errorf("operation %s not found", reqParams.OperationName))
|
||||
return true
|
||||
}
|
||||
|
||||
vars, err := validator.VariableValues(c.exec.Schema(), op, reqParams.Variables)
|
||||
if err != nil {
|
||||
c.sendError(message.ID, err)
|
||||
return true
|
||||
}
|
||||
reqCtx := c.cfg.newRequestContext(c.exec, doc, op, reqParams.Query, vars)
|
||||
ctx := graphql.WithRequestContext(c.ctx, reqCtx)
|
||||
|
||||
if c.initPayload != nil {
|
||||
ctx = withInitPayload(ctx, c.initPayload)
|
||||
}
|
||||
|
||||
if op.Operation != ast.Subscription {
|
||||
var result *graphql.Response
|
||||
if op.Operation == ast.Query {
|
||||
result = c.exec.Query(ctx, op)
|
||||
} else {
|
||||
result = c.exec.Mutation(ctx, op)
|
||||
}
|
||||
|
||||
c.sendData(message.ID, result)
|
||||
c.write(&operationMessage{ID: message.ID, Type: completeMsg})
|
||||
return true
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
c.mu.Lock()
|
||||
c.active[message.ID] = cancel
|
||||
c.mu.Unlock()
|
||||
go func() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
userErr := reqCtx.Recover(ctx, r)
|
||||
c.sendError(message.ID, &gqlerror.Error{Message: userErr.Error()})
|
||||
}
|
||||
}()
|
||||
next := c.exec.Subscription(ctx, op)
|
||||
for result := next(); result != nil; result = next() {
|
||||
c.sendData(message.ID, result)
|
||||
}
|
||||
|
||||
c.write(&operationMessage{ID: message.ID, Type: completeMsg})
|
||||
|
||||
c.mu.Lock()
|
||||
delete(c.active, message.ID)
|
||||
c.mu.Unlock()
|
||||
cancel()
|
||||
}()
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *wsConnection) sendData(id string, response *graphql.Response) {
|
||||
b, err := json.Marshal(response)
|
||||
if err != nil {
|
||||
c.sendError(id, gqlerror.Errorf("unable to encode json response: %s", err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
c.write(&operationMessage{Type: dataMsg, ID: id, Payload: b})
|
||||
}
|
||||
|
||||
func (c *wsConnection) sendError(id string, errors ...*gqlerror.Error) {
|
||||
var errs []error
|
||||
for _, err := range errors {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
b, err := json.Marshal(errs)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
c.write(&operationMessage{Type: errorMsg, ID: id, Payload: b})
|
||||
}
|
||||
|
||||
func (c *wsConnection) sendConnectionError(format string, args ...interface{}) {
|
||||
b, err := json.Marshal(&gqlerror.Error{Message: fmt.Sprintf(format, args...)})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
c.write(&operationMessage{Type: connectionErrorMsg, Payload: b})
|
||||
}
|
||||
|
||||
func (c *wsConnection) readOp() *operationMessage {
|
||||
_, r, err := c.conn.NextReader()
|
||||
if err != nil {
|
||||
c.sendConnectionError("invalid json")
|
||||
return nil
|
||||
}
|
||||
message := operationMessage{}
|
||||
if err := jsonDecode(r, &message); err != nil {
|
||||
c.sendConnectionError("invalid json")
|
||||
return nil
|
||||
}
|
||||
|
||||
return &message
|
||||
}
|
||||
|
||||
func (c *wsConnection) close(closeCode int, message string) {
|
||||
c.mu.Lock()
|
||||
_ = c.conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(closeCode, message))
|
||||
c.mu.Unlock()
|
||||
_ = c.conn.Close()
|
||||
}
|
||||
163
vendor/github.com/99designs/gqlgen/internal/code/compare.go
generated
vendored
163
vendor/github.com/99designs/gqlgen/internal/code/compare.go
generated
vendored
|
|
@ -1,163 +0,0 @@
|
|||
package code
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/types"
|
||||
)
|
||||
|
||||
// CompatibleTypes isnt a strict comparison, it allows for pointer differences
|
||||
func CompatibleTypes(expected types.Type, actual types.Type) error {
|
||||
//fmt.Println("Comparing ", expected.String(), actual.String())
|
||||
|
||||
// Special case to deal with pointer mismatches
|
||||
{
|
||||
expectedPtr, expectedIsPtr := expected.(*types.Pointer)
|
||||
actualPtr, actualIsPtr := actual.(*types.Pointer)
|
||||
|
||||
if expectedIsPtr && actualIsPtr {
|
||||
return CompatibleTypes(expectedPtr.Elem(), actualPtr.Elem())
|
||||
}
|
||||
if expectedIsPtr && !actualIsPtr {
|
||||
return CompatibleTypes(expectedPtr.Elem(), actual)
|
||||
}
|
||||
if !expectedIsPtr && actualIsPtr {
|
||||
return CompatibleTypes(expected, actualPtr.Elem())
|
||||
}
|
||||
}
|
||||
|
||||
switch expected := expected.(type) {
|
||||
case *types.Slice:
|
||||
if actual, ok := actual.(*types.Slice); ok {
|
||||
return CompatibleTypes(expected.Elem(), actual.Elem())
|
||||
}
|
||||
|
||||
case *types.Array:
|
||||
if actual, ok := actual.(*types.Array); ok {
|
||||
if expected.Len() != actual.Len() {
|
||||
return fmt.Errorf("array length differs")
|
||||
}
|
||||
|
||||
return CompatibleTypes(expected.Elem(), actual.Elem())
|
||||
}
|
||||
|
||||
case *types.Basic:
|
||||
if actual, ok := actual.(*types.Basic); ok {
|
||||
if actual.Kind() != expected.Kind() {
|
||||
return fmt.Errorf("basic kind differs, %s != %s", expected.Name(), actual.Name())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
case *types.Struct:
|
||||
if actual, ok := actual.(*types.Struct); ok {
|
||||
if expected.NumFields() != actual.NumFields() {
|
||||
return fmt.Errorf("number of struct fields differ")
|
||||
}
|
||||
|
||||
for i := 0; i < expected.NumFields(); i++ {
|
||||
if expected.Field(i).Name() != actual.Field(i).Name() {
|
||||
return fmt.Errorf("struct field %d name differs, %s != %s", i, expected.Field(i).Name(), actual.Field(i).Name())
|
||||
}
|
||||
if err := CompatibleTypes(expected.Field(i).Type(), actual.Field(i).Type()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
case *types.Tuple:
|
||||
if actual, ok := actual.(*types.Tuple); ok {
|
||||
if expected.Len() != actual.Len() {
|
||||
return fmt.Errorf("tuple length differs, %d != %d", expected.Len(), actual.Len())
|
||||
}
|
||||
|
||||
for i := 0; i < expected.Len(); i++ {
|
||||
if err := CompatibleTypes(expected.At(i).Type(), actual.At(i).Type()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
case *types.Signature:
|
||||
if actual, ok := actual.(*types.Signature); ok {
|
||||
if err := CompatibleTypes(expected.Params(), actual.Params()); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := CompatibleTypes(expected.Results(), actual.Results()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
case *types.Interface:
|
||||
if actual, ok := actual.(*types.Interface); ok {
|
||||
if expected.NumMethods() != actual.NumMethods() {
|
||||
return fmt.Errorf("interface method count differs, %d != %d", expected.NumMethods(), actual.NumMethods())
|
||||
}
|
||||
|
||||
for i := 0; i < expected.NumMethods(); i++ {
|
||||
if expected.Method(i).Name() != actual.Method(i).Name() {
|
||||
return fmt.Errorf("interface method %d name differs, %s != %s", i, expected.Method(i).Name(), actual.Method(i).Name())
|
||||
}
|
||||
if err := CompatibleTypes(expected.Method(i).Type(), actual.Method(i).Type()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
case *types.Map:
|
||||
if actual, ok := actual.(*types.Map); ok {
|
||||
if err := CompatibleTypes(expected.Key(), actual.Key()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := CompatibleTypes(expected.Elem(), actual.Elem()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
case *types.Chan:
|
||||
if actual, ok := actual.(*types.Chan); ok {
|
||||
return CompatibleTypes(expected.Elem(), actual.Elem())
|
||||
}
|
||||
|
||||
case *types.Named:
|
||||
if actual, ok := actual.(*types.Named); ok {
|
||||
if NormalizeVendor(expected.Obj().Pkg().Path()) != NormalizeVendor(actual.Obj().Pkg().Path()) {
|
||||
return fmt.Errorf(
|
||||
"package name of named type differs, %s != %s",
|
||||
NormalizeVendor(expected.Obj().Pkg().Path()),
|
||||
NormalizeVendor(actual.Obj().Pkg().Path()),
|
||||
)
|
||||
}
|
||||
|
||||
if expected.Obj().Name() != actual.Obj().Name() {
|
||||
return fmt.Errorf(
|
||||
"named type name differs, %s != %s",
|
||||
NormalizeVendor(expected.Obj().Name()),
|
||||
NormalizeVendor(actual.Obj().Name()),
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Before models are generated all missing references will be Invalid Basic references.
|
||||
// lets assume these are valid too.
|
||||
if actual, ok := actual.(*types.Basic); ok && actual.Kind() == types.Invalid {
|
||||
return nil
|
||||
}
|
||||
|
||||
default:
|
||||
return fmt.Errorf("missing support for %T", expected)
|
||||
}
|
||||
|
||||
return fmt.Errorf("type mismatch %T != %T", expected, actual)
|
||||
}
|
||||
114
vendor/github.com/99designs/gqlgen/internal/code/imports.go
generated
vendored
114
vendor/github.com/99designs/gqlgen/internal/code/imports.go
generated
vendored
|
|
@ -1,114 +0,0 @@
|
|||
package code
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"go/build"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/tools/go/packages"
|
||||
)
|
||||
|
||||
var nameForPackageCache = sync.Map{}
|
||||
|
||||
var gopaths []string
|
||||
|
||||
func init() {
|
||||
gopaths = filepath.SplitList(build.Default.GOPATH)
|
||||
for i, p := range gopaths {
|
||||
gopaths[i] = filepath.ToSlash(filepath.Join(p, "src"))
|
||||
}
|
||||
}
|
||||
|
||||
// NameForDir manually looks for package stanzas in files located in the given directory. This can be
|
||||
// much faster than having to consult go list, because we already know exactly where to look.
|
||||
func NameForDir(dir string) string {
|
||||
dir, err := filepath.Abs(dir)
|
||||
if err != nil {
|
||||
return SanitizePackageName(filepath.Base(dir))
|
||||
}
|
||||
files, err := ioutil.ReadDir(dir)
|
||||
if err != nil {
|
||||
return SanitizePackageName(filepath.Base(dir))
|
||||
}
|
||||
fset := token.NewFileSet()
|
||||
for _, file := range files {
|
||||
if !strings.HasSuffix(strings.ToLower(file.Name()), ".go") {
|
||||
continue
|
||||
}
|
||||
|
||||
filename := filepath.Join(dir, file.Name())
|
||||
if src, err := parser.ParseFile(fset, filename, nil, parser.PackageClauseOnly); err == nil {
|
||||
return src.Name.Name
|
||||
}
|
||||
}
|
||||
|
||||
return SanitizePackageName(filepath.Base(dir))
|
||||
}
|
||||
|
||||
// ImportPathForDir takes a path and returns a golang import path for the package
|
||||
func ImportPathForDir(dir string) (res string) {
|
||||
dir, err := filepath.Abs(dir)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
dir = filepath.ToSlash(dir)
|
||||
|
||||
modDir := dir
|
||||
assumedPart := ""
|
||||
for {
|
||||
f, err := ioutil.ReadFile(filepath.Join(modDir, "/", "go.mod"))
|
||||
if err == nil {
|
||||
// found it, stop searching
|
||||
return string(modregex.FindSubmatch(f)[1]) + assumedPart
|
||||
}
|
||||
|
||||
assumedPart = "/" + filepath.Base(modDir) + assumedPart
|
||||
modDir, err = filepath.Abs(filepath.Join(modDir, ".."))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Walked all the way to the root and didnt find anything :'(
|
||||
if modDir == "/" {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for _, gopath := range gopaths {
|
||||
if len(gopath) < len(dir) && strings.EqualFold(gopath, dir[0:len(gopath)]) {
|
||||
return dir[len(gopath)+1:]
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
var modregex = regexp.MustCompile("module (.*)\n")
|
||||
|
||||
// NameForPackage returns the package name for a given import path. This can be really slow.
|
||||
func NameForPackage(importPath string) string {
|
||||
if importPath == "" {
|
||||
panic(errors.New("import path can not be empty"))
|
||||
}
|
||||
if v, ok := nameForPackageCache.Load(importPath); ok {
|
||||
return v.(string)
|
||||
}
|
||||
importPath = QualifyPackagePath(importPath)
|
||||
p, _ := packages.Load(&packages.Config{
|
||||
Mode: packages.NeedName,
|
||||
}, importPath)
|
||||
|
||||
if len(p) != 1 || p[0].Name == "" {
|
||||
return SanitizePackageName(filepath.Base(importPath))
|
||||
}
|
||||
|
||||
nameForPackageCache.Store(importPath, p[0].Name)
|
||||
|
||||
return p[0].Name
|
||||
}
|
||||
56
vendor/github.com/99designs/gqlgen/internal/code/util.go
generated
vendored
56
vendor/github.com/99designs/gqlgen/internal/code/util.go
generated
vendored
|
|
@ -1,56 +0,0 @@
|
|||
package code
|
||||
|
||||
import (
|
||||
"go/build"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// take a string in the form github.com/package/blah.Type and split it into package and type
|
||||
func PkgAndType(name string) (string, string) {
|
||||
parts := strings.Split(name, ".")
|
||||
if len(parts) == 1 {
|
||||
return "", name
|
||||
}
|
||||
|
||||
return strings.Join(parts[:len(parts)-1], "."), parts[len(parts)-1]
|
||||
}
|
||||
|
||||
var modsRegex = regexp.MustCompile(`^(\*|\[\])*`)
|
||||
|
||||
// NormalizeVendor takes a qualified package path and turns it into normal one.
|
||||
// eg .
|
||||
// github.com/foo/vendor/github.com/99designs/gqlgen/graphql becomes
|
||||
// github.com/99designs/gqlgen/graphql
|
||||
func NormalizeVendor(pkg string) string {
|
||||
modifiers := modsRegex.FindAllString(pkg, 1)[0]
|
||||
pkg = strings.TrimPrefix(pkg, modifiers)
|
||||
parts := strings.Split(pkg, "/vendor/")
|
||||
return modifiers + parts[len(parts)-1]
|
||||
}
|
||||
|
||||
// QualifyPackagePath takes an import and fully qualifies it with a vendor dir, if one is required.
|
||||
// eg .
|
||||
// github.com/99designs/gqlgen/graphql becomes
|
||||
// github.com/foo/vendor/github.com/99designs/gqlgen/graphql
|
||||
//
|
||||
// x/tools/packages only supports 'qualified package paths' so this will need to be done prior to calling it
|
||||
// See https://github.com/golang/go/issues/30289
|
||||
func QualifyPackagePath(importPath string) string {
|
||||
wd, _ := os.Getwd()
|
||||
|
||||
pkg, err := build.Import(importPath, wd, 0)
|
||||
if err != nil {
|
||||
return importPath
|
||||
}
|
||||
|
||||
return pkg.ImportPath
|
||||
}
|
||||
|
||||
var invalidPackageNameChar = regexp.MustCompile(`[^\w]`)
|
||||
|
||||
func SanitizePackageName(pkg string) string {
|
||||
return invalidPackageNameChar.ReplaceAllLiteralString(filepath.Base(pkg), "_")
|
||||
}
|
||||
103
vendor/github.com/99designs/gqlgen/internal/imports/prune.go
generated
vendored
103
vendor/github.com/99designs/gqlgen/internal/imports/prune.go
generated
vendored
|
|
@ -1,103 +0,0 @@
|
|||
// Wrapper around x/tools/imports that only removes imports, never adds new ones.
|
||||
|
||||
package imports
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/printer"
|
||||
"go/token"
|
||||
"strings"
|
||||
|
||||
"github.com/99designs/gqlgen/internal/code"
|
||||
|
||||
"golang.org/x/tools/go/ast/astutil"
|
||||
"golang.org/x/tools/imports"
|
||||
)
|
||||
|
||||
type visitFn func(node ast.Node)
|
||||
|
||||
func (fn visitFn) Visit(node ast.Node) ast.Visitor {
|
||||
fn(node)
|
||||
return fn
|
||||
}
|
||||
|
||||
// Prune removes any unused imports
|
||||
func Prune(filename string, src []byte) ([]byte, error) {
|
||||
fset := token.NewFileSet()
|
||||
|
||||
file, err := parser.ParseFile(fset, filename, src, parser.ParseComments|parser.AllErrors)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
unused, err := getUnusedImports(file, filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for ipath, name := range unused {
|
||||
astutil.DeleteNamedImport(fset, file, name, ipath)
|
||||
}
|
||||
printConfig := &printer.Config{Mode: printer.TabIndent, Tabwidth: 8}
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := printConfig.Fprint(&buf, fset, file); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return imports.Process(filename, buf.Bytes(), &imports.Options{FormatOnly: true, Comments: true, TabIndent: true, TabWidth: 8})
|
||||
}
|
||||
|
||||
func getUnusedImports(file ast.Node, filename string) (map[string]string, error) {
|
||||
imported := map[string]*ast.ImportSpec{}
|
||||
used := map[string]bool{}
|
||||
|
||||
ast.Walk(visitFn(func(node ast.Node) {
|
||||
if node == nil {
|
||||
return
|
||||
}
|
||||
switch v := node.(type) {
|
||||
case *ast.ImportSpec:
|
||||
if v.Name != nil {
|
||||
imported[v.Name.Name] = v
|
||||
break
|
||||
}
|
||||
ipath := strings.Trim(v.Path.Value, `"`)
|
||||
if ipath == "C" {
|
||||
break
|
||||
}
|
||||
|
||||
local := code.NameForPackage(ipath)
|
||||
|
||||
imported[local] = v
|
||||
case *ast.SelectorExpr:
|
||||
xident, ok := v.X.(*ast.Ident)
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
if xident.Obj != nil {
|
||||
// if the parser can resolve it, it's not a package ref
|
||||
break
|
||||
}
|
||||
used[xident.Name] = true
|
||||
}
|
||||
}), file)
|
||||
|
||||
for pkg := range used {
|
||||
delete(imported, pkg)
|
||||
}
|
||||
|
||||
unusedImport := map[string]string{}
|
||||
for pkg, is := range imported {
|
||||
if !used[pkg] && pkg != "_" && pkg != "." {
|
||||
name := ""
|
||||
if is.Name != nil {
|
||||
name = is.Name.Name
|
||||
}
|
||||
unusedImport[strings.Trim(is.Path.Value, `"`)] = name
|
||||
}
|
||||
}
|
||||
|
||||
return unusedImport, nil
|
||||
}
|
||||
9
vendor/github.com/99designs/gqlgen/main.go
generated
vendored
9
vendor/github.com/99designs/gqlgen/main.go
generated
vendored
|
|
@ -1,9 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/99designs/gqlgen/cmd"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cmd.Execute()
|
||||
}
|
||||
232
vendor/github.com/99designs/gqlgen/plugin/modelgen/models.go
generated
vendored
232
vendor/github.com/99designs/gqlgen/plugin/modelgen/models.go
generated
vendored
|
|
@ -1,232 +0,0 @@
|
|||
package modelgen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/types"
|
||||
"sort"
|
||||
|
||||
"github.com/99designs/gqlgen/codegen/config"
|
||||
"github.com/99designs/gqlgen/codegen/templates"
|
||||
"github.com/99designs/gqlgen/internal/code"
|
||||
"github.com/99designs/gqlgen/plugin"
|
||||
"github.com/vektah/gqlparser/ast"
|
||||
)
|
||||
|
||||
type ModelBuild struct {
|
||||
PackageName string
|
||||
Interfaces []*Interface
|
||||
Models []*Object
|
||||
Enums []*Enum
|
||||
Scalars []string
|
||||
}
|
||||
|
||||
type Interface struct {
|
||||
Description string
|
||||
Name string
|
||||
}
|
||||
|
||||
type Object struct {
|
||||
Description string
|
||||
Name string
|
||||
Fields []*Field
|
||||
Implements []string
|
||||
}
|
||||
|
||||
type Field struct {
|
||||
Description string
|
||||
Name string
|
||||
Type types.Type
|
||||
Tag string
|
||||
}
|
||||
|
||||
type Enum struct {
|
||||
Description string
|
||||
Name string
|
||||
Values []*EnumValue
|
||||
}
|
||||
|
||||
type EnumValue struct {
|
||||
Description string
|
||||
Name string
|
||||
}
|
||||
|
||||
func New() plugin.Plugin {
|
||||
return &Plugin{}
|
||||
}
|
||||
|
||||
type Plugin struct{}
|
||||
|
||||
var _ plugin.ConfigMutator = &Plugin{}
|
||||
|
||||
func (m *Plugin) Name() string {
|
||||
return "modelgen"
|
||||
}
|
||||
|
||||
func (m *Plugin) MutateConfig(cfg *config.Config) error {
|
||||
if err := cfg.Check(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
schema, _, err := cfg.LoadSchema()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cfg.InjectBuiltins(schema)
|
||||
|
||||
binder, err := cfg.NewBinder(schema)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
b := &ModelBuild{
|
||||
PackageName: cfg.Model.Package,
|
||||
}
|
||||
|
||||
for _, schemaType := range schema.Types {
|
||||
if cfg.Models.UserDefined(schemaType.Name) {
|
||||
continue
|
||||
}
|
||||
|
||||
switch schemaType.Kind {
|
||||
case ast.Interface, ast.Union:
|
||||
it := &Interface{
|
||||
Description: schemaType.Description,
|
||||
Name: schemaType.Name,
|
||||
}
|
||||
|
||||
b.Interfaces = append(b.Interfaces, it)
|
||||
case ast.Object, ast.InputObject:
|
||||
if schemaType == schema.Query || schemaType == schema.Mutation || schemaType == schema.Subscription {
|
||||
continue
|
||||
}
|
||||
it := &Object{
|
||||
Description: schemaType.Description,
|
||||
Name: schemaType.Name,
|
||||
}
|
||||
|
||||
for _, implementor := range schema.GetImplements(schemaType) {
|
||||
it.Implements = append(it.Implements, implementor.Name)
|
||||
}
|
||||
|
||||
for _, field := range schemaType.Fields {
|
||||
var typ types.Type
|
||||
fieldDef := schema.Types[field.Type.Name()]
|
||||
|
||||
if cfg.Models.UserDefined(field.Type.Name()) {
|
||||
pkg, typeName := code.PkgAndType(cfg.Models[field.Type.Name()].Model[0])
|
||||
typ, err = binder.FindType(pkg, typeName)
|
||||
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)
|
||||
}
|
||||
|
||||
it.Fields = append(it.Fields, &Field{
|
||||
Name: name,
|
||||
Type: typ,
|
||||
Description: field.Description,
|
||||
Tag: `json:"` + field.Name + `"`,
|
||||
})
|
||||
}
|
||||
|
||||
b.Models = append(b.Models, it)
|
||||
case ast.Enum:
|
||||
it := &Enum{
|
||||
Name: schemaType.Name,
|
||||
Description: schemaType.Description,
|
||||
}
|
||||
|
||||
for _, v := range schemaType.EnumValues {
|
||||
it.Values = append(it.Values, &EnumValue{
|
||||
Name: v.Name,
|
||||
Description: v.Description,
|
||||
})
|
||||
}
|
||||
|
||||
b.Enums = append(b.Enums, it)
|
||||
case ast.Scalar:
|
||||
b.Scalars = append(b.Scalars, schemaType.Name)
|
||||
}
|
||||
}
|
||||
|
||||
sort.Slice(b.Enums, func(i, j int) bool { return b.Enums[i].Name < b.Enums[j].Name })
|
||||
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 })
|
||||
|
||||
for _, it := range b.Enums {
|
||||
cfg.Models.Add(it.Name, cfg.Model.ImportPath()+"."+templates.ToGo(it.Name))
|
||||
}
|
||||
for _, it := range b.Models {
|
||||
cfg.Models.Add(it.Name, cfg.Model.ImportPath()+"."+templates.ToGo(it.Name))
|
||||
}
|
||||
for _, it := range b.Interfaces {
|
||||
cfg.Models.Add(it.Name, cfg.Model.ImportPath()+"."+templates.ToGo(it.Name))
|
||||
}
|
||||
for _, it := range b.Scalars {
|
||||
cfg.Models.Add(it, "github.com/99designs/gqlgen/graphql.String")
|
||||
}
|
||||
|
||||
if len(b.Models) == 0 && len(b.Enums) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return templates.Render(templates.Options{
|
||||
PackageName: cfg.Model.Package,
|
||||
Filename: cfg.Model.Filename,
|
||||
Data: b,
|
||||
GeneratedHeader: true,
|
||||
})
|
||||
}
|
||||
|
||||
func isStruct(t types.Type) bool {
|
||||
_, is := t.Underlying().(*types.Struct)
|
||||
return is
|
||||
}
|
||||
85
vendor/github.com/99designs/gqlgen/plugin/modelgen/models.gotpl
generated
vendored
85
vendor/github.com/99designs/gqlgen/plugin/modelgen/models.gotpl
generated
vendored
|
|
@ -1,85 +0,0 @@
|
|||
{{ reserveImport "context" }}
|
||||
{{ reserveImport "fmt" }}
|
||||
{{ reserveImport "io" }}
|
||||
{{ reserveImport "strconv" }}
|
||||
{{ reserveImport "time" }}
|
||||
{{ reserveImport "sync" }}
|
||||
{{ reserveImport "errors" }}
|
||||
{{ reserveImport "bytes" }}
|
||||
|
||||
{{ reserveImport "github.com/vektah/gqlparser" }}
|
||||
{{ reserveImport "github.com/vektah/gqlparser/ast" }}
|
||||
{{ reserveImport "github.com/99designs/gqlgen/graphql" }}
|
||||
{{ reserveImport "github.com/99designs/gqlgen/graphql/introspection" }}
|
||||
|
||||
{{- range $model := .Interfaces }}
|
||||
{{ with .Description }} {{.|prefixLines "// "}} {{ end }}
|
||||
type {{.Name|go }} interface {
|
||||
Is{{.Name|go }}()
|
||||
}
|
||||
{{- end }}
|
||||
|
||||
{{ range $model := .Models }}
|
||||
{{with .Description }} {{.|prefixLines "// "}} {{end}}
|
||||
type {{ .Name|go }} struct {
|
||||
{{- range $field := .Fields }}
|
||||
{{- with .Description }}
|
||||
{{.|prefixLines "// "}}
|
||||
{{- end}}
|
||||
{{ $field.Name|go }} {{$field.Type | ref}} `{{$field.Tag}}`
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
{{- range $iface := .Implements }}
|
||||
func ({{ $model.Name|go }}) Is{{ $iface|go }}() {}
|
||||
{{- end }}
|
||||
{{- end}}
|
||||
|
||||
{{ range $enum := .Enums }}
|
||||
{{ with .Description|go }} {{.|prefixLines "// "}} {{end}}
|
||||
type {{.Name|go }} string
|
||||
const (
|
||||
{{- range $value := .Values}}
|
||||
{{- with .Description}}
|
||||
{{.|prefixLines "// "}}
|
||||
{{- end}}
|
||||
{{ $enum.Name|go }}{{ .Name|go }} {{$enum.Name|go }} = {{.Name|quote}}
|
||||
{{- end }}
|
||||
)
|
||||
|
||||
var All{{.Name|go }} = []{{ .Name|go }}{
|
||||
{{- range $value := .Values}}
|
||||
{{$enum.Name|go }}{{ .Name|go }},
|
||||
{{- end }}
|
||||
}
|
||||
|
||||
func (e {{.Name|go }}) IsValid() bool {
|
||||
switch e {
|
||||
case {{ range $index, $element := .Values}}{{if $index}},{{end}}{{ $enum.Name|go }}{{ $element.Name|go }}{{end}}:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (e {{.Name|go }}) String() string {
|
||||
return string(e)
|
||||
}
|
||||
|
||||
func (e *{{.Name|go }}) UnmarshalGQL(v interface{}) error {
|
||||
str, ok := v.(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("enums must be strings")
|
||||
}
|
||||
|
||||
*e = {{ .Name|go }}(str)
|
||||
if !e.IsValid() {
|
||||
return fmt.Errorf("%s is not a valid {{ .Name }}", str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e {{.Name|go }}) MarshalGQL(w io.Writer) {
|
||||
fmt.Fprint(w, strconv.Quote(e.String()))
|
||||
}
|
||||
|
||||
{{- end }}
|
||||
20
vendor/github.com/99designs/gqlgen/plugin/plugin.go
generated
vendored
20
vendor/github.com/99designs/gqlgen/plugin/plugin.go
generated
vendored
|
|
@ -1,20 +0,0 @@
|
|||
// plugin package interfaces are EXPERIMENTAL.
|
||||
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"github.com/99designs/gqlgen/codegen"
|
||||
"github.com/99designs/gqlgen/codegen/config"
|
||||
)
|
||||
|
||||
type Plugin interface {
|
||||
Name() string
|
||||
}
|
||||
|
||||
type ConfigMutator interface {
|
||||
MutateConfig(cfg *config.Config) error
|
||||
}
|
||||
|
||||
type CodeGenerator interface {
|
||||
GenerateCode(cfg *codegen.Data) error
|
||||
}
|
||||
53
vendor/github.com/99designs/gqlgen/plugin/resolvergen/resolver.go
generated
vendored
53
vendor/github.com/99designs/gqlgen/plugin/resolvergen/resolver.go
generated
vendored
|
|
@ -1,53 +0,0 @@
|
|||
package resolvergen
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/99designs/gqlgen/codegen"
|
||||
"github.com/99designs/gqlgen/codegen/templates"
|
||||
"github.com/99designs/gqlgen/plugin"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func New() plugin.Plugin {
|
||||
return &Plugin{}
|
||||
}
|
||||
|
||||
type Plugin struct{}
|
||||
|
||||
var _ plugin.CodeGenerator = &Plugin{}
|
||||
|
||||
func (m *Plugin) Name() string {
|
||||
return "resovlergen"
|
||||
}
|
||||
func (m *Plugin) GenerateCode(data *codegen.Data) error {
|
||||
if !data.Config.Resolver.IsDefined() {
|
||||
return nil
|
||||
}
|
||||
|
||||
resolverBuild := &ResolverBuild{
|
||||
Data: data,
|
||||
PackageName: data.Config.Resolver.Package,
|
||||
ResolverType: data.Config.Resolver.Type,
|
||||
}
|
||||
filename := data.Config.Resolver.Filename
|
||||
|
||||
if _, err := os.Stat(filename); os.IsNotExist(errors.Cause(err)) {
|
||||
return templates.Render(templates.Options{
|
||||
PackageName: data.Config.Resolver.Package,
|
||||
Filename: data.Config.Resolver.Filename,
|
||||
Data: resolverBuild,
|
||||
})
|
||||
}
|
||||
|
||||
log.Printf("Skipped resolver: %s already exists\n", filename)
|
||||
return nil
|
||||
}
|
||||
|
||||
type ResolverBuild struct {
|
||||
*codegen.Data
|
||||
|
||||
PackageName string
|
||||
ResolverType string
|
||||
}
|
||||
40
vendor/github.com/99designs/gqlgen/plugin/resolvergen/resolver.gotpl
generated
vendored
40
vendor/github.com/99designs/gqlgen/plugin/resolvergen/resolver.gotpl
generated
vendored
|
|
@ -1,40 +0,0 @@
|
|||
// THIS CODE IS A STARTING POINT ONLY. IT WILL NOT BE UPDATED WITH SCHEMA CHANGES.
|
||||
|
||||
{{ reserveImport "context" }}
|
||||
{{ reserveImport "fmt" }}
|
||||
{{ reserveImport "io" }}
|
||||
{{ reserveImport "strconv" }}
|
||||
{{ reserveImport "time" }}
|
||||
{{ reserveImport "sync" }}
|
||||
{{ reserveImport "errors" }}
|
||||
{{ reserveImport "bytes" }}
|
||||
|
||||
{{ reserveImport "github.com/99designs/gqlgen/handler" }}
|
||||
{{ reserveImport "github.com/vektah/gqlparser" }}
|
||||
{{ reserveImport "github.com/vektah/gqlparser/ast" }}
|
||||
{{ reserveImport "github.com/99designs/gqlgen/graphql" }}
|
||||
{{ reserveImport "github.com/99designs/gqlgen/graphql/introspection" }}
|
||||
|
||||
type {{.ResolverType}} struct {}
|
||||
|
||||
{{ range $object := .Objects -}}
|
||||
{{- if $object.HasResolvers -}}
|
||||
func (r *{{$.ResolverType}}) {{$object.Name}}() {{ $object.ResolverInterface | ref }} {
|
||||
return &{{lcFirst $object.Name}}Resolver{r}
|
||||
}
|
||||
{{ end -}}
|
||||
{{ end }}
|
||||
|
||||
{{ range $object := .Objects -}}
|
||||
{{- if $object.HasResolvers -}}
|
||||
type {{lcFirst $object.Name}}Resolver struct { *Resolver }
|
||||
|
||||
{{ range $field := $object.Fields -}}
|
||||
{{- if $field.IsResolver -}}
|
||||
func (r *{{lcFirst $object.Name}}Resolver) {{$field.GoFieldName}}{{ $field.ShortResolverDeclaration }} {
|
||||
panic("not implemented")
|
||||
}
|
||||
{{ end -}}
|
||||
{{ end -}}
|
||||
{{ end -}}
|
||||
{{ end }}
|
||||
49
vendor/github.com/99designs/gqlgen/plugin/servergen/server.go
generated
vendored
49
vendor/github.com/99designs/gqlgen/plugin/servergen/server.go
generated
vendored
|
|
@ -1,49 +0,0 @@
|
|||
package servergen
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/99designs/gqlgen/codegen"
|
||||
"github.com/99designs/gqlgen/codegen/templates"
|
||||
"github.com/99designs/gqlgen/plugin"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func New(filename string) plugin.Plugin {
|
||||
return &Plugin{filename}
|
||||
}
|
||||
|
||||
type Plugin struct {
|
||||
filename string
|
||||
}
|
||||
|
||||
var _ plugin.CodeGenerator = &Plugin{}
|
||||
|
||||
func (m *Plugin) Name() string {
|
||||
return "servergen"
|
||||
}
|
||||
func (m *Plugin) GenerateCode(data *codegen.Data) error {
|
||||
serverBuild := &ServerBuild{
|
||||
ExecPackageName: data.Config.Exec.ImportPath(),
|
||||
ResolverPackageName: data.Config.Resolver.ImportPath(),
|
||||
}
|
||||
|
||||
if _, err := os.Stat(m.filename); os.IsNotExist(errors.Cause(err)) {
|
||||
return templates.Render(templates.Options{
|
||||
PackageName: "main",
|
||||
Filename: m.filename,
|
||||
Data: serverBuild,
|
||||
})
|
||||
}
|
||||
|
||||
log.Printf("Skipped server: %s already exists\n", m.filename)
|
||||
return nil
|
||||
}
|
||||
|
||||
type ServerBuild struct {
|
||||
codegen.Data
|
||||
|
||||
ExecPackageName string
|
||||
ResolverPackageName string
|
||||
}
|
||||
20
vendor/github.com/99designs/gqlgen/plugin/servergen/server.gotpl
generated
vendored
20
vendor/github.com/99designs/gqlgen/plugin/servergen/server.gotpl
generated
vendored
|
|
@ -1,20 +0,0 @@
|
|||
{{ reserveImport "context" }}
|
||||
{{ reserveImport "log" }}
|
||||
{{ reserveImport "net/http" }}
|
||||
{{ reserveImport "os" }}
|
||||
{{ reserveImport "github.com/99designs/gqlgen/handler" }}
|
||||
|
||||
const defaultPort = "8080"
|
||||
|
||||
func main() {
|
||||
port := os.Getenv("PORT")
|
||||
if port == "" {
|
||||
port = defaultPort
|
||||
}
|
||||
|
||||
http.Handle("/", handler.Playground("GraphQL playground", "/query"))
|
||||
http.Handle("/query", handler.GraphQL({{ lookupImport .ExecPackageName }}.NewExecutableSchema({{ lookupImport .ExecPackageName}}.Config{Resolvers: &{{ lookupImport .ResolverPackageName}}.Resolver{}})))
|
||||
|
||||
log.Printf("connect to http://localhost:%s/ for GraphQL playground", port)
|
||||
log.Fatal(http.ListenAndServe(":" + port, nil))
|
||||
}
|
||||
5
vendor/github.com/99designs/gqlgen/tools.go
generated
vendored
5
vendor/github.com/99designs/gqlgen/tools.go
generated
vendored
|
|
@ -1,5 +0,0 @@
|
|||
// +build tools
|
||||
|
||||
package main
|
||||
|
||||
import _ "github.com/vektah/dataloaden"
|
||||
5
vendor/github.com/BurntSushi/toml/.gitignore
generated
vendored
5
vendor/github.com/BurntSushi/toml/.gitignore
generated
vendored
|
|
@ -1,5 +0,0 @@
|
|||
TAGS
|
||||
tags
|
||||
.*.swp
|
||||
tomlcheck/tomlcheck
|
||||
toml.test
|
||||
15
vendor/github.com/BurntSushi/toml/.travis.yml
generated
vendored
15
vendor/github.com/BurntSushi/toml/.travis.yml
generated
vendored
|
|
@ -1,15 +0,0 @@
|
|||
language: go
|
||||
go:
|
||||
- 1.1
|
||||
- 1.2
|
||||
- 1.3
|
||||
- 1.4
|
||||
- 1.5
|
||||
- 1.6
|
||||
- tip
|
||||
install:
|
||||
- go install ./...
|
||||
- go get github.com/BurntSushi/toml-test
|
||||
script:
|
||||
- export PATH="$PATH:$HOME/gopath/bin"
|
||||
- make test
|
||||
3
vendor/github.com/BurntSushi/toml/COMPATIBLE
generated
vendored
3
vendor/github.com/BurntSushi/toml/COMPATIBLE
generated
vendored
|
|
@ -1,3 +0,0 @@
|
|||
Compatible with TOML version
|
||||
[v0.4.0](https://github.com/toml-lang/toml/blob/v0.4.0/versions/en/toml-v0.4.0.md)
|
||||
|
||||
21
vendor/github.com/BurntSushi/toml/COPYING
generated
vendored
21
vendor/github.com/BurntSushi/toml/COPYING
generated
vendored
|
|
@ -1,21 +0,0 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013 TOML authors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
19
vendor/github.com/BurntSushi/toml/Makefile
generated
vendored
19
vendor/github.com/BurntSushi/toml/Makefile
generated
vendored
|
|
@ -1,19 +0,0 @@
|
|||
install:
|
||||
go install ./...
|
||||
|
||||
test: install
|
||||
go test -v
|
||||
toml-test toml-test-decoder
|
||||
toml-test -encoder toml-test-encoder
|
||||
|
||||
fmt:
|
||||
gofmt -w *.go */*.go
|
||||
colcheck *.go */*.go
|
||||
|
||||
tags:
|
||||
find ./ -name '*.go' -print0 | xargs -0 gotags > TAGS
|
||||
|
||||
push:
|
||||
git push origin master
|
||||
git push github master
|
||||
|
||||
218
vendor/github.com/BurntSushi/toml/README.md
generated
vendored
218
vendor/github.com/BurntSushi/toml/README.md
generated
vendored
|
|
@ -1,218 +0,0 @@
|
|||
## TOML parser and encoder for Go with reflection
|
||||
|
||||
TOML stands for Tom's Obvious, Minimal Language. This Go package provides a
|
||||
reflection interface similar to Go's standard library `json` and `xml`
|
||||
packages. This package also supports the `encoding.TextUnmarshaler` and
|
||||
`encoding.TextMarshaler` interfaces so that you can define custom data
|
||||
representations. (There is an example of this below.)
|
||||
|
||||
Spec: https://github.com/toml-lang/toml
|
||||
|
||||
Compatible with TOML version
|
||||
[v0.4.0](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md)
|
||||
|
||||
Documentation: https://godoc.org/github.com/BurntSushi/toml
|
||||
|
||||
Installation:
|
||||
|
||||
```bash
|
||||
go get github.com/BurntSushi/toml
|
||||
```
|
||||
|
||||
Try the toml validator:
|
||||
|
||||
```bash
|
||||
go get github.com/BurntSushi/toml/cmd/tomlv
|
||||
tomlv some-toml-file.toml
|
||||
```
|
||||
|
||||
[](https://travis-ci.org/BurntSushi/toml) [](https://godoc.org/github.com/BurntSushi/toml)
|
||||
|
||||
### Testing
|
||||
|
||||
This package passes all tests in
|
||||
[toml-test](https://github.com/BurntSushi/toml-test) for both the decoder
|
||||
and the encoder.
|
||||
|
||||
### Examples
|
||||
|
||||
This package works similarly to how the Go standard library handles `XML`
|
||||
and `JSON`. Namely, data is loaded into Go values via reflection.
|
||||
|
||||
For the simplest example, consider some TOML file as just a list of keys
|
||||
and values:
|
||||
|
||||
```toml
|
||||
Age = 25
|
||||
Cats = [ "Cauchy", "Plato" ]
|
||||
Pi = 3.14
|
||||
Perfection = [ 6, 28, 496, 8128 ]
|
||||
DOB = 1987-07-05T05:45:00Z
|
||||
```
|
||||
|
||||
Which could be defined in Go as:
|
||||
|
||||
```go
|
||||
type Config struct {
|
||||
Age int
|
||||
Cats []string
|
||||
Pi float64
|
||||
Perfection []int
|
||||
DOB time.Time // requires `import time`
|
||||
}
|
||||
```
|
||||
|
||||
And then decoded with:
|
||||
|
||||
```go
|
||||
var conf Config
|
||||
if _, err := toml.Decode(tomlData, &conf); err != nil {
|
||||
// handle error
|
||||
}
|
||||
```
|
||||
|
||||
You can also use struct tags if your struct field name doesn't map to a TOML
|
||||
key value directly:
|
||||
|
||||
```toml
|
||||
some_key_NAME = "wat"
|
||||
```
|
||||
|
||||
```go
|
||||
type TOML struct {
|
||||
ObscureKey string `toml:"some_key_NAME"`
|
||||
}
|
||||
```
|
||||
|
||||
### Using the `encoding.TextUnmarshaler` interface
|
||||
|
||||
Here's an example that automatically parses duration strings into
|
||||
`time.Duration` values:
|
||||
|
||||
```toml
|
||||
[[song]]
|
||||
name = "Thunder Road"
|
||||
duration = "4m49s"
|
||||
|
||||
[[song]]
|
||||
name = "Stairway to Heaven"
|
||||
duration = "8m03s"
|
||||
```
|
||||
|
||||
Which can be decoded with:
|
||||
|
||||
```go
|
||||
type song struct {
|
||||
Name string
|
||||
Duration duration
|
||||
}
|
||||
type songs struct {
|
||||
Song []song
|
||||
}
|
||||
var favorites songs
|
||||
if _, err := toml.Decode(blob, &favorites); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for _, s := range favorites.Song {
|
||||
fmt.Printf("%s (%s)\n", s.Name, s.Duration)
|
||||
}
|
||||
```
|
||||
|
||||
And you'll also need a `duration` type that satisfies the
|
||||
`encoding.TextUnmarshaler` interface:
|
||||
|
||||
```go
|
||||
type duration struct {
|
||||
time.Duration
|
||||
}
|
||||
|
||||
func (d *duration) UnmarshalText(text []byte) error {
|
||||
var err error
|
||||
d.Duration, err = time.ParseDuration(string(text))
|
||||
return err
|
||||
}
|
||||
```
|
||||
|
||||
### More complex usage
|
||||
|
||||
Here's an example of how to load the example from the official spec page:
|
||||
|
||||
```toml
|
||||
# This is a TOML document. Boom.
|
||||
|
||||
title = "TOML Example"
|
||||
|
||||
[owner]
|
||||
name = "Tom Preston-Werner"
|
||||
organization = "GitHub"
|
||||
bio = "GitHub Cofounder & CEO\nLikes tater tots and beer."
|
||||
dob = 1979-05-27T07:32:00Z # First class dates? Why not?
|
||||
|
||||
[database]
|
||||
server = "192.168.1.1"
|
||||
ports = [ 8001, 8001, 8002 ]
|
||||
connection_max = 5000
|
||||
enabled = true
|
||||
|
||||
[servers]
|
||||
|
||||
# You can indent as you please. Tabs or spaces. TOML don't care.
|
||||
[servers.alpha]
|
||||
ip = "10.0.0.1"
|
||||
dc = "eqdc10"
|
||||
|
||||
[servers.beta]
|
||||
ip = "10.0.0.2"
|
||||
dc = "eqdc10"
|
||||
|
||||
[clients]
|
||||
data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it
|
||||
|
||||
# Line breaks are OK when inside arrays
|
||||
hosts = [
|
||||
"alpha",
|
||||
"omega"
|
||||
]
|
||||
```
|
||||
|
||||
And the corresponding Go types are:
|
||||
|
||||
```go
|
||||
type tomlConfig struct {
|
||||
Title string
|
||||
Owner ownerInfo
|
||||
DB database `toml:"database"`
|
||||
Servers map[string]server
|
||||
Clients clients
|
||||
}
|
||||
|
||||
type ownerInfo struct {
|
||||
Name string
|
||||
Org string `toml:"organization"`
|
||||
Bio string
|
||||
DOB time.Time
|
||||
}
|
||||
|
||||
type database struct {
|
||||
Server string
|
||||
Ports []int
|
||||
ConnMax int `toml:"connection_max"`
|
||||
Enabled bool
|
||||
}
|
||||
|
||||
type server struct {
|
||||
IP string
|
||||
DC string
|
||||
}
|
||||
|
||||
type clients struct {
|
||||
Data [][]interface{}
|
||||
Hosts []string
|
||||
}
|
||||
```
|
||||
|
||||
Note that a case insensitive match will be tried if an exact match can't be
|
||||
found.
|
||||
|
||||
A working example of the above can be found in `_examples/example.{go,toml}`.
|
||||
509
vendor/github.com/BurntSushi/toml/decode.go
generated
vendored
509
vendor/github.com/BurntSushi/toml/decode.go
generated
vendored
|
|
@ -1,509 +0,0 @@
|
|||
package toml
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func e(format string, args ...interface{}) error {
|
||||
return fmt.Errorf("toml: "+format, args...)
|
||||
}
|
||||
|
||||
// Unmarshaler is the interface implemented by objects that can unmarshal a
|
||||
// TOML description of themselves.
|
||||
type Unmarshaler interface {
|
||||
UnmarshalTOML(interface{}) error
|
||||
}
|
||||
|
||||
// Unmarshal decodes the contents of `p` in TOML format into a pointer `v`.
|
||||
func Unmarshal(p []byte, v interface{}) error {
|
||||
_, err := Decode(string(p), v)
|
||||
return err
|
||||
}
|
||||
|
||||
// Primitive is a TOML value that hasn't been decoded into a Go value.
|
||||
// When using the various `Decode*` functions, the type `Primitive` may
|
||||
// be given to any value, and its decoding will be delayed.
|
||||
//
|
||||
// A `Primitive` value can be decoded using the `PrimitiveDecode` function.
|
||||
//
|
||||
// The underlying representation of a `Primitive` value is subject to change.
|
||||
// Do not rely on it.
|
||||
//
|
||||
// N.B. Primitive values are still parsed, so using them will only avoid
|
||||
// the overhead of reflection. They can be useful when you don't know the
|
||||
// exact type of TOML data until run time.
|
||||
type Primitive struct {
|
||||
undecoded interface{}
|
||||
context Key
|
||||
}
|
||||
|
||||
// DEPRECATED!
|
||||
//
|
||||
// Use MetaData.PrimitiveDecode instead.
|
||||
func PrimitiveDecode(primValue Primitive, v interface{}) error {
|
||||
md := MetaData{decoded: make(map[string]bool)}
|
||||
return md.unify(primValue.undecoded, rvalue(v))
|
||||
}
|
||||
|
||||
// PrimitiveDecode is just like the other `Decode*` functions, except it
|
||||
// decodes a TOML value that has already been parsed. Valid primitive values
|
||||
// can *only* be obtained from values filled by the decoder functions,
|
||||
// including this method. (i.e., `v` may contain more `Primitive`
|
||||
// values.)
|
||||
//
|
||||
// Meta data for primitive values is included in the meta data returned by
|
||||
// the `Decode*` functions with one exception: keys returned by the Undecoded
|
||||
// method will only reflect keys that were decoded. Namely, any keys hidden
|
||||
// behind a Primitive will be considered undecoded. Executing this method will
|
||||
// update the undecoded keys in the meta data. (See the example.)
|
||||
func (md *MetaData) PrimitiveDecode(primValue Primitive, v interface{}) error {
|
||||
md.context = primValue.context
|
||||
defer func() { md.context = nil }()
|
||||
return md.unify(primValue.undecoded, rvalue(v))
|
||||
}
|
||||
|
||||
// Decode will decode the contents of `data` in TOML format into a pointer
|
||||
// `v`.
|
||||
//
|
||||
// TOML hashes correspond to Go structs or maps. (Dealer's choice. They can be
|
||||
// used interchangeably.)
|
||||
//
|
||||
// TOML arrays of tables correspond to either a slice of structs or a slice
|
||||
// of maps.
|
||||
//
|
||||
// TOML datetimes correspond to Go `time.Time` values.
|
||||
//
|
||||
// All other TOML types (float, string, int, bool and array) correspond
|
||||
// to the obvious Go types.
|
||||
//
|
||||
// An exception to the above rules is if a type implements the
|
||||
// encoding.TextUnmarshaler interface. In this case, any primitive TOML value
|
||||
// (floats, strings, integers, booleans and datetimes) will be converted to
|
||||
// a byte string and given to the value's UnmarshalText method. See the
|
||||
// Unmarshaler example for a demonstration with time duration strings.
|
||||
//
|
||||
// Key mapping
|
||||
//
|
||||
// TOML keys can map to either keys in a Go map or field names in a Go
|
||||
// struct. The special `toml` struct tag may be used to map TOML keys to
|
||||
// struct fields that don't match the key name exactly. (See the example.)
|
||||
// A case insensitive match to struct names will be tried if an exact match
|
||||
// can't be found.
|
||||
//
|
||||
// The mapping between TOML values and Go values is loose. That is, there
|
||||
// may exist TOML values that cannot be placed into your representation, and
|
||||
// there may be parts of your representation that do not correspond to
|
||||
// TOML values. This loose mapping can be made stricter by using the IsDefined
|
||||
// and/or Undecoded methods on the MetaData returned.
|
||||
//
|
||||
// This decoder will not handle cyclic types. If a cyclic type is passed,
|
||||
// `Decode` will not terminate.
|
||||
func Decode(data string, v interface{}) (MetaData, error) {
|
||||
rv := reflect.ValueOf(v)
|
||||
if rv.Kind() != reflect.Ptr {
|
||||
return MetaData{}, e("Decode of non-pointer %s", reflect.TypeOf(v))
|
||||
}
|
||||
if rv.IsNil() {
|
||||
return MetaData{}, e("Decode of nil %s", reflect.TypeOf(v))
|
||||
}
|
||||
p, err := parse(data)
|
||||
if err != nil {
|
||||
return MetaData{}, err
|
||||
}
|
||||
md := MetaData{
|
||||
p.mapping, p.types, p.ordered,
|
||||
make(map[string]bool, len(p.ordered)), nil,
|
||||
}
|
||||
return md, md.unify(p.mapping, indirect(rv))
|
||||
}
|
||||
|
||||
// DecodeFile is just like Decode, except it will automatically read the
|
||||
// contents of the file at `fpath` and decode it for you.
|
||||
func DecodeFile(fpath string, v interface{}) (MetaData, error) {
|
||||
bs, err := ioutil.ReadFile(fpath)
|
||||
if err != nil {
|
||||
return MetaData{}, err
|
||||
}
|
||||
return Decode(string(bs), v)
|
||||
}
|
||||
|
||||
// DecodeReader is just like Decode, except it will consume all bytes
|
||||
// from the reader and decode it for you.
|
||||
func DecodeReader(r io.Reader, v interface{}) (MetaData, error) {
|
||||
bs, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return MetaData{}, err
|
||||
}
|
||||
return Decode(string(bs), v)
|
||||
}
|
||||
|
||||
// unify performs a sort of type unification based on the structure of `rv`,
|
||||
// which is the client representation.
|
||||
//
|
||||
// Any type mismatch produces an error. Finding a type that we don't know
|
||||
// how to handle produces an unsupported type error.
|
||||
func (md *MetaData) unify(data interface{}, rv reflect.Value) error {
|
||||
|
||||
// Special case. Look for a `Primitive` value.
|
||||
if rv.Type() == reflect.TypeOf((*Primitive)(nil)).Elem() {
|
||||
// Save the undecoded data and the key context into the primitive
|
||||
// value.
|
||||
context := make(Key, len(md.context))
|
||||
copy(context, md.context)
|
||||
rv.Set(reflect.ValueOf(Primitive{
|
||||
undecoded: data,
|
||||
context: context,
|
||||
}))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Special case. Unmarshaler Interface support.
|
||||
if rv.CanAddr() {
|
||||
if v, ok := rv.Addr().Interface().(Unmarshaler); ok {
|
||||
return v.UnmarshalTOML(data)
|
||||
}
|
||||
}
|
||||
|
||||
// Special case. Handle time.Time values specifically.
|
||||
// TODO: Remove this code when we decide to drop support for Go 1.1.
|
||||
// This isn't necessary in Go 1.2 because time.Time satisfies the encoding
|
||||
// interfaces.
|
||||
if rv.Type().AssignableTo(rvalue(time.Time{}).Type()) {
|
||||
return md.unifyDatetime(data, rv)
|
||||
}
|
||||
|
||||
// Special case. Look for a value satisfying the TextUnmarshaler interface.
|
||||
if v, ok := rv.Interface().(TextUnmarshaler); ok {
|
||||
return md.unifyText(data, v)
|
||||
}
|
||||
// BUG(burntsushi)
|
||||
// The behavior here is incorrect whenever a Go type satisfies the
|
||||
// encoding.TextUnmarshaler interface but also corresponds to a TOML
|
||||
// hash or array. In particular, the unmarshaler should only be applied
|
||||
// to primitive TOML values. But at this point, it will be applied to
|
||||
// all kinds of values and produce an incorrect error whenever those values
|
||||
// are hashes or arrays (including arrays of tables).
|
||||
|
||||
k := rv.Kind()
|
||||
|
||||
// laziness
|
||||
if k >= reflect.Int && k <= reflect.Uint64 {
|
||||
return md.unifyInt(data, rv)
|
||||
}
|
||||
switch k {
|
||||
case reflect.Ptr:
|
||||
elem := reflect.New(rv.Type().Elem())
|
||||
err := md.unify(data, reflect.Indirect(elem))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rv.Set(elem)
|
||||
return nil
|
||||
case reflect.Struct:
|
||||
return md.unifyStruct(data, rv)
|
||||
case reflect.Map:
|
||||
return md.unifyMap(data, rv)
|
||||
case reflect.Array:
|
||||
return md.unifyArray(data, rv)
|
||||
case reflect.Slice:
|
||||
return md.unifySlice(data, rv)
|
||||
case reflect.String:
|
||||
return md.unifyString(data, rv)
|
||||
case reflect.Bool:
|
||||
return md.unifyBool(data, rv)
|
||||
case reflect.Interface:
|
||||
// we only support empty interfaces.
|
||||
if rv.NumMethod() > 0 {
|
||||
return e("unsupported type %s", rv.Type())
|
||||
}
|
||||
return md.unifyAnything(data, rv)
|
||||
case reflect.Float32:
|
||||
fallthrough
|
||||
case reflect.Float64:
|
||||
return md.unifyFloat64(data, rv)
|
||||
}
|
||||
return e("unsupported type %s", rv.Kind())
|
||||
}
|
||||
|
||||
func (md *MetaData) unifyStruct(mapping interface{}, rv reflect.Value) error {
|
||||
tmap, ok := mapping.(map[string]interface{})
|
||||
if !ok {
|
||||
if mapping == nil {
|
||||
return nil
|
||||
}
|
||||
return e("type mismatch for %s: expected table but found %T",
|
||||
rv.Type().String(), mapping)
|
||||
}
|
||||
|
||||
for key, datum := range tmap {
|
||||
var f *field
|
||||
fields := cachedTypeFields(rv.Type())
|
||||
for i := range fields {
|
||||
ff := &fields[i]
|
||||
if ff.name == key {
|
||||
f = ff
|
||||
break
|
||||
}
|
||||
if f == nil && strings.EqualFold(ff.name, key) {
|
||||
f = ff
|
||||
}
|
||||
}
|
||||
if f != nil {
|
||||
subv := rv
|
||||
for _, i := range f.index {
|
||||
subv = indirect(subv.Field(i))
|
||||
}
|
||||
if isUnifiable(subv) {
|
||||
md.decoded[md.context.add(key).String()] = true
|
||||
md.context = append(md.context, key)
|
||||
if err := md.unify(datum, subv); err != nil {
|
||||
return err
|
||||
}
|
||||
md.context = md.context[0 : len(md.context)-1]
|
||||
} else if f.name != "" {
|
||||
// Bad user! No soup for you!
|
||||
return e("cannot write unexported field %s.%s",
|
||||
rv.Type().String(), f.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (md *MetaData) unifyMap(mapping interface{}, rv reflect.Value) error {
|
||||
tmap, ok := mapping.(map[string]interface{})
|
||||
if !ok {
|
||||
if tmap == nil {
|
||||
return nil
|
||||
}
|
||||
return badtype("map", mapping)
|
||||
}
|
||||
if rv.IsNil() {
|
||||
rv.Set(reflect.MakeMap(rv.Type()))
|
||||
}
|
||||
for k, v := range tmap {
|
||||
md.decoded[md.context.add(k).String()] = true
|
||||
md.context = append(md.context, k)
|
||||
|
||||
rvkey := indirect(reflect.New(rv.Type().Key()))
|
||||
rvval := reflect.Indirect(reflect.New(rv.Type().Elem()))
|
||||
if err := md.unify(v, rvval); err != nil {
|
||||
return err
|
||||
}
|
||||
md.context = md.context[0 : len(md.context)-1]
|
||||
|
||||
rvkey.SetString(k)
|
||||
rv.SetMapIndex(rvkey, rvval)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (md *MetaData) unifyArray(data interface{}, rv reflect.Value) error {
|
||||
datav := reflect.ValueOf(data)
|
||||
if datav.Kind() != reflect.Slice {
|
||||
if !datav.IsValid() {
|
||||
return nil
|
||||
}
|
||||
return badtype("slice", data)
|
||||
}
|
||||
sliceLen := datav.Len()
|
||||
if sliceLen != rv.Len() {
|
||||
return e("expected array length %d; got TOML array of length %d",
|
||||
rv.Len(), sliceLen)
|
||||
}
|
||||
return md.unifySliceArray(datav, rv)
|
||||
}
|
||||
|
||||
func (md *MetaData) unifySlice(data interface{}, rv reflect.Value) error {
|
||||
datav := reflect.ValueOf(data)
|
||||
if datav.Kind() != reflect.Slice {
|
||||
if !datav.IsValid() {
|
||||
return nil
|
||||
}
|
||||
return badtype("slice", data)
|
||||
}
|
||||
n := datav.Len()
|
||||
if rv.IsNil() || rv.Cap() < n {
|
||||
rv.Set(reflect.MakeSlice(rv.Type(), n, n))
|
||||
}
|
||||
rv.SetLen(n)
|
||||
return md.unifySliceArray(datav, rv)
|
||||
}
|
||||
|
||||
func (md *MetaData) unifySliceArray(data, rv reflect.Value) error {
|
||||
sliceLen := data.Len()
|
||||
for i := 0; i < sliceLen; i++ {
|
||||
v := data.Index(i).Interface()
|
||||
sliceval := indirect(rv.Index(i))
|
||||
if err := md.unify(v, sliceval); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (md *MetaData) unifyDatetime(data interface{}, rv reflect.Value) error {
|
||||
if _, ok := data.(time.Time); ok {
|
||||
rv.Set(reflect.ValueOf(data))
|
||||
return nil
|
||||
}
|
||||
return badtype("time.Time", data)
|
||||
}
|
||||
|
||||
func (md *MetaData) unifyString(data interface{}, rv reflect.Value) error {
|
||||
if s, ok := data.(string); ok {
|
||||
rv.SetString(s)
|
||||
return nil
|
||||
}
|
||||
return badtype("string", data)
|
||||
}
|
||||
|
||||
func (md *MetaData) unifyFloat64(data interface{}, rv reflect.Value) error {
|
||||
if num, ok := data.(float64); ok {
|
||||
switch rv.Kind() {
|
||||
case reflect.Float32:
|
||||
fallthrough
|
||||
case reflect.Float64:
|
||||
rv.SetFloat(num)
|
||||
default:
|
||||
panic("bug")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return badtype("float", data)
|
||||
}
|
||||
|
||||
func (md *MetaData) unifyInt(data interface{}, rv reflect.Value) error {
|
||||
if num, ok := data.(int64); ok {
|
||||
if rv.Kind() >= reflect.Int && rv.Kind() <= reflect.Int64 {
|
||||
switch rv.Kind() {
|
||||
case reflect.Int, reflect.Int64:
|
||||
// No bounds checking necessary.
|
||||
case reflect.Int8:
|
||||
if num < math.MinInt8 || num > math.MaxInt8 {
|
||||
return e("value %d is out of range for int8", num)
|
||||
}
|
||||
case reflect.Int16:
|
||||
if num < math.MinInt16 || num > math.MaxInt16 {
|
||||
return e("value %d is out of range for int16", num)
|
||||
}
|
||||
case reflect.Int32:
|
||||
if num < math.MinInt32 || num > math.MaxInt32 {
|
||||
return e("value %d is out of range for int32", num)
|
||||
}
|
||||
}
|
||||
rv.SetInt(num)
|
||||
} else if rv.Kind() >= reflect.Uint && rv.Kind() <= reflect.Uint64 {
|
||||
unum := uint64(num)
|
||||
switch rv.Kind() {
|
||||
case reflect.Uint, reflect.Uint64:
|
||||
// No bounds checking necessary.
|
||||
case reflect.Uint8:
|
||||
if num < 0 || unum > math.MaxUint8 {
|
||||
return e("value %d is out of range for uint8", num)
|
||||
}
|
||||
case reflect.Uint16:
|
||||
if num < 0 || unum > math.MaxUint16 {
|
||||
return e("value %d is out of range for uint16", num)
|
||||
}
|
||||
case reflect.Uint32:
|
||||
if num < 0 || unum > math.MaxUint32 {
|
||||
return e("value %d is out of range for uint32", num)
|
||||
}
|
||||
}
|
||||
rv.SetUint(unum)
|
||||
} else {
|
||||
panic("unreachable")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return badtype("integer", data)
|
||||
}
|
||||
|
||||
func (md *MetaData) unifyBool(data interface{}, rv reflect.Value) error {
|
||||
if b, ok := data.(bool); ok {
|
||||
rv.SetBool(b)
|
||||
return nil
|
||||
}
|
||||
return badtype("boolean", data)
|
||||
}
|
||||
|
||||
func (md *MetaData) unifyAnything(data interface{}, rv reflect.Value) error {
|
||||
rv.Set(reflect.ValueOf(data))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (md *MetaData) unifyText(data interface{}, v TextUnmarshaler) error {
|
||||
var s string
|
||||
switch sdata := data.(type) {
|
||||
case TextMarshaler:
|
||||
text, err := sdata.MarshalText()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s = string(text)
|
||||
case fmt.Stringer:
|
||||
s = sdata.String()
|
||||
case string:
|
||||
s = sdata
|
||||
case bool:
|
||||
s = fmt.Sprintf("%v", sdata)
|
||||
case int64:
|
||||
s = fmt.Sprintf("%d", sdata)
|
||||
case float64:
|
||||
s = fmt.Sprintf("%f", sdata)
|
||||
default:
|
||||
return badtype("primitive (string-like)", data)
|
||||
}
|
||||
if err := v.UnmarshalText([]byte(s)); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// rvalue returns a reflect.Value of `v`. All pointers are resolved.
|
||||
func rvalue(v interface{}) reflect.Value {
|
||||
return indirect(reflect.ValueOf(v))
|
||||
}
|
||||
|
||||
// indirect returns the value pointed to by a pointer.
|
||||
// Pointers are followed until the value is not a pointer.
|
||||
// New values are allocated for each nil pointer.
|
||||
//
|
||||
// An exception to this rule is if the value satisfies an interface of
|
||||
// interest to us (like encoding.TextUnmarshaler).
|
||||
func indirect(v reflect.Value) reflect.Value {
|
||||
if v.Kind() != reflect.Ptr {
|
||||
if v.CanSet() {
|
||||
pv := v.Addr()
|
||||
if _, ok := pv.Interface().(TextUnmarshaler); ok {
|
||||
return pv
|
||||
}
|
||||
}
|
||||
return v
|
||||
}
|
||||
if v.IsNil() {
|
||||
v.Set(reflect.New(v.Type().Elem()))
|
||||
}
|
||||
return indirect(reflect.Indirect(v))
|
||||
}
|
||||
|
||||
func isUnifiable(rv reflect.Value) bool {
|
||||
if rv.CanSet() {
|
||||
return true
|
||||
}
|
||||
if _, ok := rv.Interface().(TextUnmarshaler); ok {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func badtype(expected string, data interface{}) error {
|
||||
return e("cannot load TOML value of type %T into a Go %s", data, expected)
|
||||
}
|
||||
121
vendor/github.com/BurntSushi/toml/decode_meta.go
generated
vendored
121
vendor/github.com/BurntSushi/toml/decode_meta.go
generated
vendored
|
|
@ -1,121 +0,0 @@
|
|||
package toml
|
||||
|
||||
import "strings"
|
||||
|
||||
// MetaData allows access to meta information about TOML data that may not
|
||||
// be inferrable via reflection. In particular, whether a key has been defined
|
||||
// and the TOML type of a key.
|
||||
type MetaData struct {
|
||||
mapping map[string]interface{}
|
||||
types map[string]tomlType
|
||||
keys []Key
|
||||
decoded map[string]bool
|
||||
context Key // Used only during decoding.
|
||||
}
|
||||
|
||||
// IsDefined returns true if the key given exists in the TOML data. The key
|
||||
// should be specified hierarchially. e.g.,
|
||||
//
|
||||
// // access the TOML key 'a.b.c'
|
||||
// IsDefined("a", "b", "c")
|
||||
//
|
||||
// IsDefined will return false if an empty key given. Keys are case sensitive.
|
||||
func (md *MetaData) IsDefined(key ...string) bool {
|
||||
if len(key) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
var hash map[string]interface{}
|
||||
var ok bool
|
||||
var hashOrVal interface{} = md.mapping
|
||||
for _, k := range key {
|
||||
if hash, ok = hashOrVal.(map[string]interface{}); !ok {
|
||||
return false
|
||||
}
|
||||
if hashOrVal, ok = hash[k]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Type returns a string representation of the type of the key specified.
|
||||
//
|
||||
// Type will return the empty string if given an empty key or a key that
|
||||
// does not exist. Keys are case sensitive.
|
||||
func (md *MetaData) Type(key ...string) string {
|
||||
fullkey := strings.Join(key, ".")
|
||||
if typ, ok := md.types[fullkey]; ok {
|
||||
return typ.typeString()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Key is the type of any TOML key, including key groups. Use (MetaData).Keys
|
||||
// to get values of this type.
|
||||
type Key []string
|
||||
|
||||
func (k Key) String() string {
|
||||
return strings.Join(k, ".")
|
||||
}
|
||||
|
||||
func (k Key) maybeQuotedAll() string {
|
||||
var ss []string
|
||||
for i := range k {
|
||||
ss = append(ss, k.maybeQuoted(i))
|
||||
}
|
||||
return strings.Join(ss, ".")
|
||||
}
|
||||
|
||||
func (k Key) maybeQuoted(i int) string {
|
||||
quote := false
|
||||
for _, c := range k[i] {
|
||||
if !isBareKeyChar(c) {
|
||||
quote = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if quote {
|
||||
return "\"" + strings.Replace(k[i], "\"", "\\\"", -1) + "\""
|
||||
}
|
||||
return k[i]
|
||||
}
|
||||
|
||||
func (k Key) add(piece string) Key {
|
||||
newKey := make(Key, len(k)+1)
|
||||
copy(newKey, k)
|
||||
newKey[len(k)] = piece
|
||||
return newKey
|
||||
}
|
||||
|
||||
// Keys returns a slice of every key in the TOML data, including key groups.
|
||||
// Each key is itself a slice, where the first element is the top of the
|
||||
// hierarchy and the last is the most specific.
|
||||
//
|
||||
// The list will have the same order as the keys appeared in the TOML data.
|
||||
//
|
||||
// All keys returned are non-empty.
|
||||
func (md *MetaData) Keys() []Key {
|
||||
return md.keys
|
||||
}
|
||||
|
||||
// Undecoded returns all keys that have not been decoded in the order in which
|
||||
// they appear in the original TOML document.
|
||||
//
|
||||
// This includes keys that haven't been decoded because of a Primitive value.
|
||||
// Once the Primitive value is decoded, the keys will be considered decoded.
|
||||
//
|
||||
// Also note that decoding into an empty interface will result in no decoding,
|
||||
// and so no keys will be considered decoded.
|
||||
//
|
||||
// In this sense, the Undecoded keys correspond to keys in the TOML document
|
||||
// that do not have a concrete type in your representation.
|
||||
func (md *MetaData) Undecoded() []Key {
|
||||
undecoded := make([]Key, 0, len(md.keys))
|
||||
for _, key := range md.keys {
|
||||
if !md.decoded[key.String()] {
|
||||
undecoded = append(undecoded, key)
|
||||
}
|
||||
}
|
||||
return undecoded
|
||||
}
|
||||
27
vendor/github.com/BurntSushi/toml/doc.go
generated
vendored
27
vendor/github.com/BurntSushi/toml/doc.go
generated
vendored
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
Package toml provides facilities for decoding and encoding TOML configuration
|
||||
files via reflection. There is also support for delaying decoding with
|
||||
the Primitive type, and querying the set of keys in a TOML document with the
|
||||
MetaData type.
|
||||
|
||||
The specification implemented: https://github.com/toml-lang/toml
|
||||
|
||||
The sub-command github.com/BurntSushi/toml/cmd/tomlv can be used to verify
|
||||
whether a file is a valid TOML document. It can also be used to print the
|
||||
type of each key in a TOML document.
|
||||
|
||||
Testing
|
||||
|
||||
There are two important types of tests used for this package. The first is
|
||||
contained inside '*_test.go' files and uses the standard Go unit testing
|
||||
framework. These tests are primarily devoted to holistically testing the
|
||||
decoder and encoder.
|
||||
|
||||
The second type of testing is used to verify the implementation's adherence
|
||||
to the TOML specification. These tests have been factored into their own
|
||||
project: https://github.com/BurntSushi/toml-test
|
||||
|
||||
The reason the tests are in a separate project is so that they can be used by
|
||||
any implementation of TOML. Namely, it is language agnostic.
|
||||
*/
|
||||
package toml
|
||||
568
vendor/github.com/BurntSushi/toml/encode.go
generated
vendored
568
vendor/github.com/BurntSushi/toml/encode.go
generated
vendored
|
|
@ -1,568 +0,0 @@
|
|||
package toml
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type tomlEncodeError struct{ error }
|
||||
|
||||
var (
|
||||
errArrayMixedElementTypes = errors.New(
|
||||
"toml: cannot encode array with mixed element types")
|
||||
errArrayNilElement = errors.New(
|
||||
"toml: cannot encode array with nil element")
|
||||
errNonString = errors.New(
|
||||
"toml: cannot encode a map with non-string key type")
|
||||
errAnonNonStruct = errors.New(
|
||||
"toml: cannot encode an anonymous field that is not a struct")
|
||||
errArrayNoTable = errors.New(
|
||||
"toml: TOML array element cannot contain a table")
|
||||
errNoKey = errors.New(
|
||||
"toml: top-level values must be Go maps or structs")
|
||||
errAnything = errors.New("") // used in testing
|
||||
)
|
||||
|
||||
var quotedReplacer = strings.NewReplacer(
|
||||
"\t", "\\t",
|
||||
"\n", "\\n",
|
||||
"\r", "\\r",
|
||||
"\"", "\\\"",
|
||||
"\\", "\\\\",
|
||||
)
|
||||
|
||||
// Encoder controls the encoding of Go values to a TOML document to some
|
||||
// io.Writer.
|
||||
//
|
||||
// The indentation level can be controlled with the Indent field.
|
||||
type Encoder struct {
|
||||
// A single indentation level. By default it is two spaces.
|
||||
Indent string
|
||||
|
||||
// hasWritten is whether we have written any output to w yet.
|
||||
hasWritten bool
|
||||
w *bufio.Writer
|
||||
}
|
||||
|
||||
// NewEncoder returns a TOML encoder that encodes Go values to the io.Writer
|
||||
// given. By default, a single indentation level is 2 spaces.
|
||||
func NewEncoder(w io.Writer) *Encoder {
|
||||
return &Encoder{
|
||||
w: bufio.NewWriter(w),
|
||||
Indent: " ",
|
||||
}
|
||||
}
|
||||
|
||||
// Encode writes a TOML representation of the Go value to the underlying
|
||||
// io.Writer. If the value given cannot be encoded to a valid TOML document,
|
||||
// then an error is returned.
|
||||
//
|
||||
// The mapping between Go values and TOML values should be precisely the same
|
||||
// as for the Decode* functions. Similarly, the TextMarshaler interface is
|
||||
// supported by encoding the resulting bytes as strings. (If you want to write
|
||||
// arbitrary binary data then you will need to use something like base64 since
|
||||
// TOML does not have any binary types.)
|
||||
//
|
||||
// When encoding TOML hashes (i.e., Go maps or structs), keys without any
|
||||
// sub-hashes are encoded first.
|
||||
//
|
||||
// If a Go map is encoded, then its keys are sorted alphabetically for
|
||||
// deterministic output. More control over this behavior may be provided if
|
||||
// there is demand for it.
|
||||
//
|
||||
// Encoding Go values without a corresponding TOML representation---like map
|
||||
// types with non-string keys---will cause an error to be returned. Similarly
|
||||
// for mixed arrays/slices, arrays/slices with nil elements, embedded
|
||||
// non-struct types and nested slices containing maps or structs.
|
||||
// (e.g., [][]map[string]string is not allowed but []map[string]string is OK
|
||||
// and so is []map[string][]string.)
|
||||
func (enc *Encoder) Encode(v interface{}) error {
|
||||
rv := eindirect(reflect.ValueOf(v))
|
||||
if err := enc.safeEncode(Key([]string{}), rv); err != nil {
|
||||
return err
|
||||
}
|
||||
return enc.w.Flush()
|
||||
}
|
||||
|
||||
func (enc *Encoder) safeEncode(key Key, rv reflect.Value) (err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
if terr, ok := r.(tomlEncodeError); ok {
|
||||
err = terr.error
|
||||
return
|
||||
}
|
||||
panic(r)
|
||||
}
|
||||
}()
|
||||
enc.encode(key, rv)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (enc *Encoder) encode(key Key, rv reflect.Value) {
|
||||
// Special case. Time needs to be in ISO8601 format.
|
||||
// Special case. If we can marshal the type to text, then we used that.
|
||||
// Basically, this prevents the encoder for handling these types as
|
||||
// generic structs (or whatever the underlying type of a TextMarshaler is).
|
||||
switch rv.Interface().(type) {
|
||||
case time.Time, TextMarshaler:
|
||||
enc.keyEqElement(key, rv)
|
||||
return
|
||||
}
|
||||
|
||||
k := rv.Kind()
|
||||
switch k {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32,
|
||||
reflect.Int64,
|
||||
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32,
|
||||
reflect.Uint64,
|
||||
reflect.Float32, reflect.Float64, reflect.String, reflect.Bool:
|
||||
enc.keyEqElement(key, rv)
|
||||
case reflect.Array, reflect.Slice:
|
||||
if typeEqual(tomlArrayHash, tomlTypeOfGo(rv)) {
|
||||
enc.eArrayOfTables(key, rv)
|
||||
} else {
|
||||
enc.keyEqElement(key, rv)
|
||||
}
|
||||
case reflect.Interface:
|
||||
if rv.IsNil() {
|
||||
return
|
||||
}
|
||||
enc.encode(key, rv.Elem())
|
||||
case reflect.Map:
|
||||
if rv.IsNil() {
|
||||
return
|
||||
}
|
||||
enc.eTable(key, rv)
|
||||
case reflect.Ptr:
|
||||
if rv.IsNil() {
|
||||
return
|
||||
}
|
||||
enc.encode(key, rv.Elem())
|
||||
case reflect.Struct:
|
||||
enc.eTable(key, rv)
|
||||
default:
|
||||
panic(e("unsupported type for key '%s': %s", key, k))
|
||||
}
|
||||
}
|
||||
|
||||
// eElement encodes any value that can be an array element (primitives and
|
||||
// arrays).
|
||||
func (enc *Encoder) eElement(rv reflect.Value) {
|
||||
switch v := rv.Interface().(type) {
|
||||
case time.Time:
|
||||
// Special case time.Time as a primitive. Has to come before
|
||||
// TextMarshaler below because time.Time implements
|
||||
// encoding.TextMarshaler, but we need to always use UTC.
|
||||
enc.wf(v.UTC().Format("2006-01-02T15:04:05Z"))
|
||||
return
|
||||
case TextMarshaler:
|
||||
// Special case. Use text marshaler if it's available for this value.
|
||||
if s, err := v.MarshalText(); err != nil {
|
||||
encPanic(err)
|
||||
} else {
|
||||
enc.writeQuoted(string(s))
|
||||
}
|
||||
return
|
||||
}
|
||||
switch rv.Kind() {
|
||||
case reflect.Bool:
|
||||
enc.wf(strconv.FormatBool(rv.Bool()))
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32,
|
||||
reflect.Int64:
|
||||
enc.wf(strconv.FormatInt(rv.Int(), 10))
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16,
|
||||
reflect.Uint32, reflect.Uint64:
|
||||
enc.wf(strconv.FormatUint(rv.Uint(), 10))
|
||||
case reflect.Float32:
|
||||
enc.wf(floatAddDecimal(strconv.FormatFloat(rv.Float(), 'f', -1, 32)))
|
||||
case reflect.Float64:
|
||||
enc.wf(floatAddDecimal(strconv.FormatFloat(rv.Float(), 'f', -1, 64)))
|
||||
case reflect.Array, reflect.Slice:
|
||||
enc.eArrayOrSliceElement(rv)
|
||||
case reflect.Interface:
|
||||
enc.eElement(rv.Elem())
|
||||
case reflect.String:
|
||||
enc.writeQuoted(rv.String())
|
||||
default:
|
||||
panic(e("unexpected primitive type: %s", rv.Kind()))
|
||||
}
|
||||
}
|
||||
|
||||
// By the TOML spec, all floats must have a decimal with at least one
|
||||
// number on either side.
|
||||
func floatAddDecimal(fstr string) string {
|
||||
if !strings.Contains(fstr, ".") {
|
||||
return fstr + ".0"
|
||||
}
|
||||
return fstr
|
||||
}
|
||||
|
||||
func (enc *Encoder) writeQuoted(s string) {
|
||||
enc.wf("\"%s\"", quotedReplacer.Replace(s))
|
||||
}
|
||||
|
||||
func (enc *Encoder) eArrayOrSliceElement(rv reflect.Value) {
|
||||
length := rv.Len()
|
||||
enc.wf("[")
|
||||
for i := 0; i < length; i++ {
|
||||
elem := rv.Index(i)
|
||||
enc.eElement(elem)
|
||||
if i != length-1 {
|
||||
enc.wf(", ")
|
||||
}
|
||||
}
|
||||
enc.wf("]")
|
||||
}
|
||||
|
||||
func (enc *Encoder) eArrayOfTables(key Key, rv reflect.Value) {
|
||||
if len(key) == 0 {
|
||||
encPanic(errNoKey)
|
||||
}
|
||||
for i := 0; i < rv.Len(); i++ {
|
||||
trv := rv.Index(i)
|
||||
if isNil(trv) {
|
||||
continue
|
||||
}
|
||||
panicIfInvalidKey(key)
|
||||
enc.newline()
|
||||
enc.wf("%s[[%s]]", enc.indentStr(key), key.maybeQuotedAll())
|
||||
enc.newline()
|
||||
enc.eMapOrStruct(key, trv)
|
||||
}
|
||||
}
|
||||
|
||||
func (enc *Encoder) eTable(key Key, rv reflect.Value) {
|
||||
panicIfInvalidKey(key)
|
||||
if len(key) == 1 {
|
||||
// Output an extra newline between top-level tables.
|
||||
// (The newline isn't written if nothing else has been written though.)
|
||||
enc.newline()
|
||||
}
|
||||
if len(key) > 0 {
|
||||
enc.wf("%s[%s]", enc.indentStr(key), key.maybeQuotedAll())
|
||||
enc.newline()
|
||||
}
|
||||
enc.eMapOrStruct(key, rv)
|
||||
}
|
||||
|
||||
func (enc *Encoder) eMapOrStruct(key Key, rv reflect.Value) {
|
||||
switch rv := eindirect(rv); rv.Kind() {
|
||||
case reflect.Map:
|
||||
enc.eMap(key, rv)
|
||||
case reflect.Struct:
|
||||
enc.eStruct(key, rv)
|
||||
default:
|
||||
panic("eTable: unhandled reflect.Value Kind: " + rv.Kind().String())
|
||||
}
|
||||
}
|
||||
|
||||
func (enc *Encoder) eMap(key Key, rv reflect.Value) {
|
||||
rt := rv.Type()
|
||||
if rt.Key().Kind() != reflect.String {
|
||||
encPanic(errNonString)
|
||||
}
|
||||
|
||||
// Sort keys so that we have deterministic output. And write keys directly
|
||||
// underneath this key first, before writing sub-structs or sub-maps.
|
||||
var mapKeysDirect, mapKeysSub []string
|
||||
for _, mapKey := range rv.MapKeys() {
|
||||
k := mapKey.String()
|
||||
if typeIsHash(tomlTypeOfGo(rv.MapIndex(mapKey))) {
|
||||
mapKeysSub = append(mapKeysSub, k)
|
||||
} else {
|
||||
mapKeysDirect = append(mapKeysDirect, k)
|
||||
}
|
||||
}
|
||||
|
||||
var writeMapKeys = func(mapKeys []string) {
|
||||
sort.Strings(mapKeys)
|
||||
for _, mapKey := range mapKeys {
|
||||
mrv := rv.MapIndex(reflect.ValueOf(mapKey))
|
||||
if isNil(mrv) {
|
||||
// Don't write anything for nil fields.
|
||||
continue
|
||||
}
|
||||
enc.encode(key.add(mapKey), mrv)
|
||||
}
|
||||
}
|
||||
writeMapKeys(mapKeysDirect)
|
||||
writeMapKeys(mapKeysSub)
|
||||
}
|
||||
|
||||
func (enc *Encoder) eStruct(key Key, rv reflect.Value) {
|
||||
// Write keys for fields directly under this key first, because if we write
|
||||
// a field that creates a new table, then all keys under it will be in that
|
||||
// table (not the one we're writing here).
|
||||
rt := rv.Type()
|
||||
var fieldsDirect, fieldsSub [][]int
|
||||
var addFields func(rt reflect.Type, rv reflect.Value, start []int)
|
||||
addFields = func(rt reflect.Type, rv reflect.Value, start []int) {
|
||||
for i := 0; i < rt.NumField(); i++ {
|
||||
f := rt.Field(i)
|
||||
// skip unexported fields
|
||||
if f.PkgPath != "" && !f.Anonymous {
|
||||
continue
|
||||
}
|
||||
frv := rv.Field(i)
|
||||
if f.Anonymous {
|
||||
t := f.Type
|
||||
switch t.Kind() {
|
||||
case reflect.Struct:
|
||||
// Treat anonymous struct fields with
|
||||
// tag names as though they are not
|
||||
// anonymous, like encoding/json does.
|
||||
if getOptions(f.Tag).name == "" {
|
||||
addFields(t, frv, f.Index)
|
||||
continue
|
||||
}
|
||||
case reflect.Ptr:
|
||||
if t.Elem().Kind() == reflect.Struct &&
|
||||
getOptions(f.Tag).name == "" {
|
||||
if !frv.IsNil() {
|
||||
addFields(t.Elem(), frv.Elem(), f.Index)
|
||||
}
|
||||
continue
|
||||
}
|
||||
// Fall through to the normal field encoding logic below
|
||||
// for non-struct anonymous fields.
|
||||
}
|
||||
}
|
||||
|
||||
if typeIsHash(tomlTypeOfGo(frv)) {
|
||||
fieldsSub = append(fieldsSub, append(start, f.Index...))
|
||||
} else {
|
||||
fieldsDirect = append(fieldsDirect, append(start, f.Index...))
|
||||
}
|
||||
}
|
||||
}
|
||||
addFields(rt, rv, nil)
|
||||
|
||||
var writeFields = func(fields [][]int) {
|
||||
for _, fieldIndex := range fields {
|
||||
sft := rt.FieldByIndex(fieldIndex)
|
||||
sf := rv.FieldByIndex(fieldIndex)
|
||||
if isNil(sf) {
|
||||
// Don't write anything for nil fields.
|
||||
continue
|
||||
}
|
||||
|
||||
opts := getOptions(sft.Tag)
|
||||
if opts.skip {
|
||||
continue
|
||||
}
|
||||
keyName := sft.Name
|
||||
if opts.name != "" {
|
||||
keyName = opts.name
|
||||
}
|
||||
if opts.omitempty && isEmpty(sf) {
|
||||
continue
|
||||
}
|
||||
if opts.omitzero && isZero(sf) {
|
||||
continue
|
||||
}
|
||||
|
||||
enc.encode(key.add(keyName), sf)
|
||||
}
|
||||
}
|
||||
writeFields(fieldsDirect)
|
||||
writeFields(fieldsSub)
|
||||
}
|
||||
|
||||
// tomlTypeName returns the TOML type name of the Go value's type. It is
|
||||
// used to determine whether the types of array elements are mixed (which is
|
||||
// forbidden). If the Go value is nil, then it is illegal for it to be an array
|
||||
// element, and valueIsNil is returned as true.
|
||||
|
||||
// Returns the TOML type of a Go value. The type may be `nil`, which means
|
||||
// no concrete TOML type could be found.
|
||||
func tomlTypeOfGo(rv reflect.Value) tomlType {
|
||||
if isNil(rv) || !rv.IsValid() {
|
||||
return nil
|
||||
}
|
||||
switch rv.Kind() {
|
||||
case reflect.Bool:
|
||||
return tomlBool
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32,
|
||||
reflect.Int64,
|
||||
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32,
|
||||
reflect.Uint64:
|
||||
return tomlInteger
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return tomlFloat
|
||||
case reflect.Array, reflect.Slice:
|
||||
if typeEqual(tomlHash, tomlArrayType(rv)) {
|
||||
return tomlArrayHash
|
||||
}
|
||||
return tomlArray
|
||||
case reflect.Ptr, reflect.Interface:
|
||||
return tomlTypeOfGo(rv.Elem())
|
||||
case reflect.String:
|
||||
return tomlString
|
||||
case reflect.Map:
|
||||
return tomlHash
|
||||
case reflect.Struct:
|
||||
switch rv.Interface().(type) {
|
||||
case time.Time:
|
||||
return tomlDatetime
|
||||
case TextMarshaler:
|
||||
return tomlString
|
||||
default:
|
||||
return tomlHash
|
||||
}
|
||||
default:
|
||||
panic("unexpected reflect.Kind: " + rv.Kind().String())
|
||||
}
|
||||
}
|
||||
|
||||
// tomlArrayType returns the element type of a TOML array. The type returned
|
||||
// may be nil if it cannot be determined (e.g., a nil slice or a zero length
|
||||
// slize). This function may also panic if it finds a type that cannot be
|
||||
// expressed in TOML (such as nil elements, heterogeneous arrays or directly
|
||||
// nested arrays of tables).
|
||||
func tomlArrayType(rv reflect.Value) tomlType {
|
||||
if isNil(rv) || !rv.IsValid() || rv.Len() == 0 {
|
||||
return nil
|
||||
}
|
||||
firstType := tomlTypeOfGo(rv.Index(0))
|
||||
if firstType == nil {
|
||||
encPanic(errArrayNilElement)
|
||||
}
|
||||
|
||||
rvlen := rv.Len()
|
||||
for i := 1; i < rvlen; i++ {
|
||||
elem := rv.Index(i)
|
||||
switch elemType := tomlTypeOfGo(elem); {
|
||||
case elemType == nil:
|
||||
encPanic(errArrayNilElement)
|
||||
case !typeEqual(firstType, elemType):
|
||||
encPanic(errArrayMixedElementTypes)
|
||||
}
|
||||
}
|
||||
// If we have a nested array, then we must make sure that the nested
|
||||
// array contains ONLY primitives.
|
||||
// This checks arbitrarily nested arrays.
|
||||
if typeEqual(firstType, tomlArray) || typeEqual(firstType, tomlArrayHash) {
|
||||
nest := tomlArrayType(eindirect(rv.Index(0)))
|
||||
if typeEqual(nest, tomlHash) || typeEqual(nest, tomlArrayHash) {
|
||||
encPanic(errArrayNoTable)
|
||||
}
|
||||
}
|
||||
return firstType
|
||||
}
|
||||
|
||||
type tagOptions struct {
|
||||
skip bool // "-"
|
||||
name string
|
||||
omitempty bool
|
||||
omitzero bool
|
||||
}
|
||||
|
||||
func getOptions(tag reflect.StructTag) tagOptions {
|
||||
t := tag.Get("toml")
|
||||
if t == "-" {
|
||||
return tagOptions{skip: true}
|
||||
}
|
||||
var opts tagOptions
|
||||
parts := strings.Split(t, ",")
|
||||
opts.name = parts[0]
|
||||
for _, s := range parts[1:] {
|
||||
switch s {
|
||||
case "omitempty":
|
||||
opts.omitempty = true
|
||||
case "omitzero":
|
||||
opts.omitzero = true
|
||||
}
|
||||
}
|
||||
return opts
|
||||
}
|
||||
|
||||
func isZero(rv reflect.Value) bool {
|
||||
switch rv.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return rv.Int() == 0
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
return rv.Uint() == 0
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return rv.Float() == 0.0
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isEmpty(rv reflect.Value) bool {
|
||||
switch rv.Kind() {
|
||||
case reflect.Array, reflect.Slice, reflect.Map, reflect.String:
|
||||
return rv.Len() == 0
|
||||
case reflect.Bool:
|
||||
return !rv.Bool()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (enc *Encoder) newline() {
|
||||
if enc.hasWritten {
|
||||
enc.wf("\n")
|
||||
}
|
||||
}
|
||||
|
||||
func (enc *Encoder) keyEqElement(key Key, val reflect.Value) {
|
||||
if len(key) == 0 {
|
||||
encPanic(errNoKey)
|
||||
}
|
||||
panicIfInvalidKey(key)
|
||||
enc.wf("%s%s = ", enc.indentStr(key), key.maybeQuoted(len(key)-1))
|
||||
enc.eElement(val)
|
||||
enc.newline()
|
||||
}
|
||||
|
||||
func (enc *Encoder) wf(format string, v ...interface{}) {
|
||||
if _, err := fmt.Fprintf(enc.w, format, v...); err != nil {
|
||||
encPanic(err)
|
||||
}
|
||||
enc.hasWritten = true
|
||||
}
|
||||
|
||||
func (enc *Encoder) indentStr(key Key) string {
|
||||
return strings.Repeat(enc.Indent, len(key)-1)
|
||||
}
|
||||
|
||||
func encPanic(err error) {
|
||||
panic(tomlEncodeError{err})
|
||||
}
|
||||
|
||||
func eindirect(v reflect.Value) reflect.Value {
|
||||
switch v.Kind() {
|
||||
case reflect.Ptr, reflect.Interface:
|
||||
return eindirect(v.Elem())
|
||||
default:
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
func isNil(rv reflect.Value) bool {
|
||||
switch rv.Kind() {
|
||||
case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
|
||||
return rv.IsNil()
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func panicIfInvalidKey(key Key) {
|
||||
for _, k := range key {
|
||||
if len(k) == 0 {
|
||||
encPanic(e("Key '%s' is not a valid table name. Key names "+
|
||||
"cannot be empty.", key.maybeQuotedAll()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func isValidKeyName(s string) bool {
|
||||
return len(s) != 0
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue