Compare commits
2 Commits
main
...
feat/imple
Author | SHA1 | Date |
---|---|---|
RaviAnand Mohabir | 2c7e2c8899 | 1 year ago |
RaviAnand Mohabir | 97c0152a7d | 1 year ago |
@ -0,0 +1 @@
|
||||
.env
|
@ -0,0 +1,38 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Publish schema",
|
||||
"type": "shell",
|
||||
"command": "npx wgc subgraph publish ${input:subgraph} --schema=${input:subgraph}/graph/schema.graphqls",
|
||||
"problemMatcher": [],
|
||||
"options": {
|
||||
"env": {
|
||||
"COSMO_API_URL": "http://localhost:3001",
|
||||
"COSMO_API_KEY": "cosmo_6a71cff4085e8353d85e876114e6010b"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Check schema",
|
||||
"type": "shell",
|
||||
"command": "npx wgc subgraph check ${input:subgraph} --schema=${input:subgraph}/graph/schema.graphqls",
|
||||
"problemMatcher": [],
|
||||
"options": {
|
||||
"env": {
|
||||
"COSMO_API_URL": "http://localhost:3001",
|
||||
"COSMO_API_KEY": "cosmo_6a71cff4085e8353d85e876114e6010b"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"id": "subgraph",
|
||||
"description": "The name of the subgraph",
|
||||
"type": "promptString"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,175 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
# Infrastructure services
|
||||
clickhouse:
|
||||
image: clickhouse/clickhouse-server:${DC_CLICKHOUSE_VERSION:-23}
|
||||
environment:
|
||||
CLICKHOUSE_DB: ${CLICKHOUSE_DATABASE:-cosmo}
|
||||
CLICKHOUSE_USER: ${CLICKHOUSE_USER:-default}
|
||||
CLICKHOUSE_PASSWORD: ${CLICKHOUSE_PASSWORD:-changeme}
|
||||
CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: ${CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT:-1}
|
||||
ports:
|
||||
- "8123:8123"
|
||||
- "9000:9000"
|
||||
- "9440:9440"
|
||||
volumes:
|
||||
- clickhouse:/var/lib/clickhouse
|
||||
- ./docker/clickhouse/init-db.sh:/docker-entrypoint-initdb.d/init-db.sh
|
||||
|
||||
postgres:
|
||||
image: postgres:${DC_POSTGRESQL_VERSION:-15.3}
|
||||
environment:
|
||||
POSTGRES_USER: ${POSTGRES_USER:-postgres}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-changeme}
|
||||
POSTGRES_DB: ${POSTGRES_DB:-controlplane}
|
||||
PGDATA: /data/postgres
|
||||
volumes:
|
||||
- ./docker/postgres/init.sql:/docker-entrypoint-initdb.d/init.sql
|
||||
- postgres:/data/postgres
|
||||
# ports:
|
||||
# - "5432:5432"
|
||||
restart: unless-stopped
|
||||
|
||||
keycloak:
|
||||
image: ghcr.io/wundergraph/cosmo/keycloak:${DC_KEYCLOAK_VERSION:-latest}
|
||||
platform: linux/amd64
|
||||
environment:
|
||||
KEYCLOAK_ADMIN: ${KEYCLOAK_ADMIN:-admin}
|
||||
KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD:-changeme}
|
||||
KC_DB: postgres
|
||||
KC_DB_URL_HOST: postgres
|
||||
KC_DB_URL_DATABASE: ${POSTGRES_DB:-keycloak}
|
||||
KC_DB_PASSWORD: ${POSTGRES_PASSWORD:-changeme}
|
||||
KC_DB_USERNAME: ${POSTGRES_USER:-postgres}
|
||||
KC_DB_SCHEMA: public
|
||||
command:
|
||||
- "start-dev"
|
||||
- "--import-realm"
|
||||
ports:
|
||||
- "8080:8080"
|
||||
volumes:
|
||||
- ./docker/keycloak/realm.json:/opt/keycloak/data/import/realm.json:ro
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
|
||||
# Cosmo Platform
|
||||
otelcollector:
|
||||
# On the public repo
|
||||
image: ghcr.io/wundergraph/cosmo/otelcollector:${DC_OTELCOLLECTOR_VERSION:-latest}
|
||||
platform: linux/amd64
|
||||
environment:
|
||||
CLICKHOUSE_ENDPOINT: "clickhouse://${CLICKHOUSE_USER:-default}:${CLICKHOUSE_PASSWORD:-changeme}@clickhouse:9000/${CLICKHOUSE_DATABASE:-cosmo}?dial_timeout=15s&compress=lz4"
|
||||
OTEL_INGEST_JWT_SECRET: ${OTEL_INGEST_JWT_SECRET:-fkczyomvdprgvtmvkuhvprxuggkbgwld}
|
||||
PROMETHEUS_REMOTE_ENDPOINT: "http://prometheus:9090/api/v1/write"
|
||||
PROMETHEUS_USERNAME: ${PROMETHEUS_USERNAME:-admin}
|
||||
PROMETHEUS_PASSWORD: ${PROMETHEUS_PASSWORD:-test}
|
||||
ports:
|
||||
- "4318:4318"
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- clickhouse
|
||||
|
||||
controlplane:
|
||||
image: ghcr.io/wundergraph/cosmo/controlplane:${DC_CONTROLPLANE_VERSION:-latest}
|
||||
platform: linux/amd64
|
||||
environment:
|
||||
DB_URL: "postgresql://postgres:changeme@postgres:5432/controlplane"
|
||||
PORT: 3001
|
||||
HOST: "0.0.0.0"
|
||||
ALLOWED_ORIGINS: "http://localhost:3000"
|
||||
LOG_LEVEL: "info"
|
||||
DEBUG_SQL: "true"
|
||||
CLICKHOUSE_DSN: "http://default:changeme@clickhouse:8123?database=cosmo"
|
||||
AUTH_REDIRECT_URI: "http://localhost:3001/v1/auth/callback"
|
||||
WEB_BASE_URL: "http://localhost:3000"
|
||||
AUTH_JWT_SECRET: "fkczyomvdprgvtmvkuhvprxuggkbgwld"
|
||||
KC_CLIENT_ID: "studio"
|
||||
KC_REALM: "cosmo"
|
||||
KC_ADMIN_USER: ${KEYCLOAK_ADMIN:-admin}
|
||||
KC_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD:-changeme}
|
||||
KC_API_URL: "http://keycloak:8080"
|
||||
KC_FRONTEND_URL: "http://localhost:8080"
|
||||
PROMETHEUS_API_URL: "http://admin:test@prometheus:9090/api/v1"
|
||||
ports:
|
||||
- "3001:3001"
|
||||
restart: on-failure
|
||||
depends_on:
|
||||
- postgres
|
||||
- clickhouse
|
||||
|
||||
router:
|
||||
image: ghcr.io/wundergraph/cosmo/router:${DC_ROUTER_VERSION:-latest}
|
||||
platform: linux/amd64
|
||||
environment:
|
||||
LOG_LEVEL: info
|
||||
FEDERATED_GRAPH_NAME: production
|
||||
CORS_ALLOW_CREDENTIALS: true
|
||||
LISTEN_ADDR: "0.0.0.0:3002"
|
||||
CONTROLPLANE_URL: http://controlplane:3001
|
||||
DEFAULT_TELEMETRY_ENDPOINT: http://otelcollector:4318
|
||||
GRAPH_API_TOKEN: ${ROUTER_TOKEN}
|
||||
restart: on-failure
|
||||
ports:
|
||||
- "3002:3002"
|
||||
|
||||
studio:
|
||||
image: ghcr.io/wundergraph/cosmo/studio:${DC_STUDIO_VERSION:-latest}
|
||||
platform: linux/amd64
|
||||
environment:
|
||||
NEXT_PUBLIC_COSMO_CP_URL: http://localhost:3001
|
||||
HOSTNAME: "0.0.0.0"
|
||||
ports:
|
||||
- "3000:3000"
|
||||
|
||||
# Migrations & Seed
|
||||
seed:
|
||||
image: ghcr.io/wundergraph/cosmo/controlplane:${DC_CONTROLPLANE_VERSION:-latest}
|
||||
platform: linux/amd64
|
||||
command:
|
||||
- "/app/dist/bin/seed.js"
|
||||
environment:
|
||||
KC_REALM: "cosmo"
|
||||
KC_API_URL: "http://keycloak:8080"
|
||||
KC_ADMIN_USER: "admin"
|
||||
KC_ADMIN_PASSWORD: "changeme"
|
||||
KC_CLIENT_ID: "studio"
|
||||
API_KEY: cosmo_669b576aaadc10ee1ae81d9193425705
|
||||
DB_URL: "postgresql://postgres:changeme@postgres:5432/controlplane"
|
||||
USER_EMAIL: foo@wundergraph.com
|
||||
USER_PASSWORD: bar
|
||||
USER_FIRSTNAME: foo
|
||||
USER_LASTNAME: bar
|
||||
ORGANIZATION_NAME: wundergraph
|
||||
ORGANIZATION_SLUG: wundergraph
|
||||
restart: on-failure
|
||||
depends_on:
|
||||
- postgres
|
||||
- clickhouse
|
||||
- keycloak
|
||||
|
||||
clickhouse-migration:
|
||||
image: ghcr.io/wundergraph/cosmo/controlplane:${DC_CONTROLPLANE_VERSION:-latest}
|
||||
platform: linux/amd64
|
||||
command: node dist/bin/ch-migrate.js
|
||||
depends_on:
|
||||
- clickhouse
|
||||
environment:
|
||||
- CLICKHOUSE_DSN=clickhouse://default:changeme@clickhouse:9000/cosmo
|
||||
restart: on-failure
|
||||
|
||||
database-migration:
|
||||
image: ghcr.io/wundergraph/cosmo/controlplane:${DC_CONTROLPLANE_VERSION:-latest}
|
||||
platform: linux/amd64
|
||||
command: node dist/bin/db-migrate.js
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
- DB_URL=postgresql://postgres:changeme@postgres:5432/controlplane
|
||||
restart: on-failure
|
||||
|
||||
volumes:
|
||||
postgres:
|
||||
clickhouse:
|
||||
prometheus:
|
@ -0,0 +1,3 @@
|
||||
# Docker
|
||||
|
||||
This directory contains files for building and running the Docker images for cosmo stack.
|
@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
clickhouse client -n <<-EOSQL
|
||||
CREATE DATABASE IF NOT EXISTS cosmo;
|
||||
EOSQL
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,2 @@
|
||||
-- Create database for local keycloak instance
|
||||
CREATE DATABASE keycloak;
|
@ -0,0 +1,3 @@
|
||||
global:
|
||||
scrape_interval: 10s
|
||||
evaluation_interval: 10s
|
@ -0,0 +1,2 @@
|
||||
basic_auth_users:
|
||||
admin: $2b$12$hNf2lSsxfm0.i4a.1kVpSOVyBCfIB51VRjgBUyv6kdnyTlgWj81Ay #test
|
@ -0,0 +1,6 @@
|
||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||
github.com/nyaruka/phonenumbers v1.0.73 h1:bP2WN8/NUP8tQebR+WCIejFaibwYMHOaB7MQVayclUo=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/twilio/twilio-go v0.26.0 h1:wFW4oTe3/LKt6bvByP7eio8JsjtaLHjMQKOUEzQry7U=
|
||||
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
|
@ -0,0 +1,21 @@
|
||||
# If you prefer the allow list template instead of the deny list, see community template:
|
||||
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
|
||||
#
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Test binary, built with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
|
||||
# Go workspace file
|
||||
go.work
|
@ -0,0 +1,26 @@
|
||||
module github.com/Dan6erbond/sitling/pets
|
||||
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/99designs/gqlgen v0.17.39
|
||||
github.com/vektah/gqlparser/v2 v2.5.10
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/agnivade/levenshtein v1.1.1 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.3 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/sosodev/duration v1.1.0 // indirect
|
||||
github.com/urfave/cli/v2 v2.25.5 // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||
golang.org/x/mod v0.10.0 // indirect
|
||||
golang.org/x/sys v0.8.0 // indirect
|
||||
golang.org/x/text v0.9.0 // indirect
|
||||
golang.org/x/tools v0.9.3 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
@ -0,0 +1,47 @@
|
||||
github.com/99designs/gqlgen v0.17.39 h1:wPTAyc2fqVjAWT5DsJ21k/lLudgnXzURwbsjVNegFpU=
|
||||
github.com/99designs/gqlgen v0.17.39/go.mod h1:b62q1USk82GYIVjC60h02YguAZLqYZtvWml8KkhJps4=
|
||||
github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8=
|
||||
github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=
|
||||
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=
|
||||
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 h1:fRzb/w+pyskVMQ+UbP35JkH8yB7MYb4q/qhBarqZE6g=
|
||||
github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.3 h1:kmRrRLlInXvng0SmLxmQpQkpbYAvcXm7NPDrgxJa9mE=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.3/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
||||
github.com/sosodev/duration v1.1.0 h1:kQcaiGbJaIsRqgQy7VGlZrVw1giWO+lDoX3MCPnpVO4=
|
||||
github.com/sosodev/duration v1.1.0/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg=
|
||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||
github.com/urfave/cli/v2 v2.25.5 h1:d0NIAyhh5shGscroL7ek/Ya9QYQE0KNabJgiUinIQkc=
|
||||
github.com/urfave/cli/v2 v2.25.5/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
|
||||
github.com/vektah/gqlparser/v2 v2.5.10 h1:6zSM4azXC9u4Nxy5YmdmGu4uKamfwsdKTwp5zsEealU=
|
||||
github.com/vektah/gqlparser/v2 v2.5.10/go.mod h1:1rCcfwB2ekJofmluGWXMSEnPMZgbxzwj6FaZ/4OT8Cc=
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
|
||||
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
|
||||
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
|
||||
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM=
|
||||
golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
|
||||
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/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
@ -0,0 +1,88 @@
|
||||
# Where are all the schema files located? globs are supported eg src/**/*.graphqls
|
||||
schema:
|
||||
- graph/*.graphqls
|
||||
|
||||
# Where should the generated server code go?
|
||||
exec:
|
||||
filename: graph/generated.go
|
||||
package: graph
|
||||
|
||||
# Uncomment to enable federation
|
||||
federation:
|
||||
filename: graph/federation.go
|
||||
package: graph
|
||||
version: 2
|
||||
|
||||
# Where should any generated models go?
|
||||
model:
|
||||
filename: graph/model/models_gen.go
|
||||
package: model
|
||||
|
||||
# Where should the resolver implementations go?
|
||||
resolver:
|
||||
layout: follow-schema
|
||||
dir: graph
|
||||
package: graph
|
||||
filename_template: "{name}.resolvers.go"
|
||||
# Optional: turn on to not generate template comments above resolvers
|
||||
# omit_template_comment: false
|
||||
|
||||
# Optional: turn on use ` + "`" + `gqlgen:"fieldName"` + "`" + ` tags in your models
|
||||
# struct_tag: json
|
||||
|
||||
# Optional: turn on to use []Thing instead of []*Thing
|
||||
# omit_slice_element_pointers: false
|
||||
|
||||
# Optional: turn on to omit Is<Name>() methods to interface and unions
|
||||
# omit_interface_checks : true
|
||||
|
||||
# Optional: turn on to skip generation of ComplexityRoot struct content and Complexity function
|
||||
# omit_complexity: false
|
||||
|
||||
# Optional: turn on to not generate any file notice comments in generated files
|
||||
# omit_gqlgen_file_notice: false
|
||||
|
||||
# Optional: turn on to exclude the gqlgen version in the generated file notice. No effect if `omit_gqlgen_file_notice` is true.
|
||||
# omit_gqlgen_version_in_file_notice: false
|
||||
|
||||
# Optional: turn off to make struct-type struct fields not use pointers
|
||||
# e.g. type Thing struct { FieldA OtherThing } instead of { FieldA *OtherThing }
|
||||
# struct_fields_always_pointers: true
|
||||
|
||||
# Optional: turn off to make resolvers return values instead of pointers for structs
|
||||
# resolvers_always_return_pointers: true
|
||||
|
||||
# Optional: turn on to return pointers instead of values in unmarshalInput
|
||||
# return_pointers_in_unmarshalinput: false
|
||||
|
||||
# Optional: wrap nullable input fields with Omittable
|
||||
# nullable_input_omittable: true
|
||||
|
||||
# Optional: set to speed up generation time by not performing a final validation pass.
|
||||
# skip_validation: true
|
||||
|
||||
# Optional: set to skip running `go mod tidy` when generating server code
|
||||
# skip_mod_tidy: true
|
||||
|
||||
# gqlgen will search for any type names in the schema in these go packages
|
||||
# if they match it will use them, otherwise it will generate them.
|
||||
autobind:
|
||||
# - "github.com/Dan6erbond/sitling/pets/graph/model"
|
||||
|
||||
# This section declares type mapping between the GraphQL and go type systems
|
||||
#
|
||||
# The first line in each type will be used as defaults for resolver arguments and
|
||||
# modelgen, the others will be allowed when binding to fields. Configure them to
|
||||
# your liking
|
||||
models:
|
||||
ID:
|
||||
model:
|
||||
- github.com/99designs/gqlgen/graphql.ID
|
||||
- github.com/99designs/gqlgen/graphql.Int
|
||||
- github.com/99designs/gqlgen/graphql.Int64
|
||||
- github.com/99designs/gqlgen/graphql.Int32
|
||||
Int:
|
||||
model:
|
||||
- github.com/99designs/gqlgen/graphql.Int
|
||||
- github.com/99designs/gqlgen/graphql.Int64
|
||||
- github.com/99designs/gqlgen/graphql.Int32
|
@ -0,0 +1,26 @@
|
||||
package graph
|
||||
|
||||
// This file will be automatically regenerated based on the schema, any resolver implementations
|
||||
// will be copied through when generating and any unknown code will be moved to the end.
|
||||
// Code generated by github.com/99designs/gqlgen version v0.17.39
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/Dan6erbond/sitling/pets/graph/model"
|
||||
)
|
||||
|
||||
// FindPetByID is the resolver for the findPetByID field.
|
||||
func (r *entityResolver) FindPetByID(ctx context.Context, id string) (*model.Pet, error) {
|
||||
return &model.Pet{ID: id}, nil
|
||||
}
|
||||
|
||||
// FindUserByID is the resolver for the findUserByID field.
|
||||
func (r *entityResolver) FindUserByID(ctx context.Context, id string) (*model.User, error) {
|
||||
return &model.User{ID: id}, nil
|
||||
}
|
||||
|
||||
// Entity returns EntityResolver implementation.
|
||||
func (r *Resolver) Entity() EntityResolver { return &entityResolver{r} }
|
||||
|
||||
type entityResolver struct{ *Resolver }
|
@ -0,0 +1,224 @@
|
||||
// Code generated by github.com/99designs/gqlgen, DO NOT EDIT.
|
||||
|
||||
package graph
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/99designs/gqlgen/plugin/federation/fedruntime"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrUnknownType = errors.New("unknown type")
|
||||
ErrTypeNotFound = errors.New("type not found")
|
||||
)
|
||||
|
||||
func (ec *executionContext) __resolve__service(ctx context.Context) (fedruntime.Service, error) {
|
||||
if ec.DisableIntrospection {
|
||||
return fedruntime.Service{}, errors.New("federated introspection disabled")
|
||||
}
|
||||
|
||||
var sdl []string
|
||||
|
||||
for _, src := range sources {
|
||||
if src.BuiltIn {
|
||||
continue
|
||||
}
|
||||
sdl = append(sdl, src.Input)
|
||||
}
|
||||
|
||||
return fedruntime.Service{
|
||||
SDL: strings.Join(sdl, "\n"),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) __resolve_entities(ctx context.Context, representations []map[string]interface{}) []fedruntime.Entity {
|
||||
list := make([]fedruntime.Entity, len(representations))
|
||||
|
||||
repsMap := map[string]struct {
|
||||
i []int
|
||||
r []map[string]interface{}
|
||||
}{}
|
||||
|
||||
// We group entities by typename so that we can parallelize their resolution.
|
||||
// This is particularly helpful when there are entity groups in multi mode.
|
||||
buildRepresentationGroups := func(reps []map[string]interface{}) {
|
||||
for i, rep := range reps {
|
||||
typeName, ok := rep["__typename"].(string)
|
||||
if !ok {
|
||||
// If there is no __typename, we just skip the representation;
|
||||
// we just won't be resolving these unknown types.
|
||||
ec.Error(ctx, errors.New("__typename must be an existing string"))
|
||||
continue
|
||||
}
|
||||
|
||||
_r := repsMap[typeName]
|
||||
_r.i = append(_r.i, i)
|
||||
_r.r = append(_r.r, rep)
|
||||
repsMap[typeName] = _r
|
||||
}
|
||||
}
|
||||
|
||||
isMulti := func(typeName string) bool {
|
||||
switch typeName {
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
resolveEntity := func(ctx context.Context, typeName string, rep map[string]interface{}, idx []int, i int) (err error) {
|
||||
// we need to do our own panic handling, because we may be called in a
|
||||
// goroutine, where the usual panic handling can't catch us
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err = ec.Recover(ctx, r)
|
||||
}
|
||||
}()
|
||||
|
||||
switch typeName {
|
||||
case "Pet":
|
||||
resolverName, err := entityResolverNameForPet(ctx, rep)
|
||||
if err != nil {
|
||||
return fmt.Errorf(`finding resolver for Entity "Pet": %w`, err)
|
||||
}
|
||||
switch resolverName {
|
||||
|
||||
case "findPetByID":
|
||||
id0, err := ec.unmarshalNID2string(ctx, rep["id"])
|
||||
if err != nil {
|
||||
return fmt.Errorf(`unmarshalling param 0 for findPetByID(): %w`, err)
|
||||
}
|
||||
entity, err := ec.resolvers.Entity().FindPetByID(ctx, id0)
|
||||
if err != nil {
|
||||
return fmt.Errorf(`resolving Entity "Pet": %w`, err)
|
||||
}
|
||||
|
||||
list[idx[i]] = entity
|
||||
return nil
|
||||
}
|
||||
case "User":
|
||||
resolverName, err := entityResolverNameForUser(ctx, rep)
|
||||
if err != nil {
|
||||
return fmt.Errorf(`finding resolver for Entity "User": %w`, err)
|
||||
}
|
||||
switch resolverName {
|
||||
|
||||
case "findUserByID":
|
||||
id0, err := ec.unmarshalNID2string(ctx, rep["id"])
|
||||
if err != nil {
|
||||
return fmt.Errorf(`unmarshalling param 0 for findUserByID(): %w`, err)
|
||||
}
|
||||
entity, err := ec.resolvers.Entity().FindUserByID(ctx, id0)
|
||||
if err != nil {
|
||||
return fmt.Errorf(`resolving Entity "User": %w`, err)
|
||||
}
|
||||
|
||||
list[idx[i]] = entity
|
||||
return nil
|
||||
}
|
||||
|
||||
}
|
||||
return fmt.Errorf("%w: %s", ErrUnknownType, typeName)
|
||||
}
|
||||
|
||||
resolveManyEntities := func(ctx context.Context, typeName string, reps []map[string]interface{}, idx []int) (err error) {
|
||||
// we need to do our own panic handling, because we may be called in a
|
||||
// goroutine, where the usual panic handling can't catch us
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err = ec.Recover(ctx, r)
|
||||
}
|
||||
}()
|
||||
|
||||
switch typeName {
|
||||
|
||||
default:
|
||||
return errors.New("unknown type: " + typeName)
|
||||
}
|
||||
}
|
||||
|
||||
resolveEntityGroup := func(typeName string, reps []map[string]interface{}, idx []int) {
|
||||
if isMulti(typeName) {
|
||||
err := resolveManyEntities(ctx, typeName, reps, idx)
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
}
|
||||
} else {
|
||||
// if there are multiple entities to resolve, parallelize (similar to
|
||||
// graphql.FieldSet.Dispatch)
|
||||
var e sync.WaitGroup
|
||||
e.Add(len(reps))
|
||||
for i, rep := range reps {
|
||||
i, rep := i, rep
|
||||
go func(i int, rep map[string]interface{}) {
|
||||
err := resolveEntity(ctx, typeName, rep, idx, i)
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
}
|
||||
e.Done()
|
||||
}(i, rep)
|
||||
}
|
||||
e.Wait()
|
||||
}
|
||||
}
|
||||
buildRepresentationGroups(representations)
|
||||
|
||||
switch len(repsMap) {
|
||||
case 0:
|
||||
return list
|
||||
case 1:
|
||||
for typeName, reps := range repsMap {
|
||||
resolveEntityGroup(typeName, reps.r, reps.i)
|
||||
}
|
||||
return list
|
||||
default:
|
||||
var g sync.WaitGroup
|
||||
g.Add(len(repsMap))
|
||||
for typeName, reps := range repsMap {
|
||||
go func(typeName string, reps []map[string]interface{}, idx []int) {
|
||||
resolveEntityGroup(typeName, reps, idx)
|
||||
g.Done()
|
||||
}(typeName, reps.r, reps.i)
|
||||
}
|
||||
g.Wait()
|
||||
return list
|
||||
}
|
||||
}
|
||||
|
||||
func entityResolverNameForPet(ctx context.Context, rep map[string]interface{}) (string, error) {
|
||||
for {
|
||||
var (
|
||||
m map[string]interface{}
|
||||
val interface{}
|
||||
ok bool
|
||||
)
|
||||
_ = val
|
||||
m = rep
|
||||
if _, ok = m["id"]; !ok {
|
||||
break
|
||||
}
|
||||
return "findPetByID", nil
|
||||
}
|
||||
return "", fmt.Errorf("%w for Pet", ErrTypeNotFound)
|
||||
}
|
||||
|
||||
func entityResolverNameForUser(ctx context.Context, rep map[string]interface{}) (string, error) {
|
||||
for {
|
||||
var (
|
||||
m map[string]interface{}
|
||||
val interface{}
|
||||
ok bool
|
||||
)
|
||||
_ = val
|
||||
m = rep
|
||||
if _, ok = m["id"]; !ok {
|
||||
break
|
||||
}
|
||||
return "findUserByID", nil
|
||||
}
|
||||
return "", fmt.Errorf("%w for User", ErrTypeNotFound)
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,17 @@
|
||||
// Code generated by github.com/99designs/gqlgen, DO NOT EDIT.
|
||||
|
||||
package model
|
||||
|
||||
type Pet struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
func (Pet) IsEntity() {}
|
||||
|
||||
type User struct {
|
||||
ID string `json:"id"`
|
||||
Pets []*Pet `json:"pets"`
|
||||
}
|
||||
|
||||
func (User) IsEntity() {}
|
@ -0,0 +1,8 @@
|
||||
//go:generate go run github.com/99designs/gqlgen generate
|
||||
package graph
|
||||
|
||||
// This file will not be regenerated automatically.
|
||||
//
|
||||
// It serves as dependency injection for your app, add any dependencies you require here.
|
||||
|
||||
type Resolver struct{}
|
@ -0,0 +1,13 @@
|
||||
type Pet @key(fields: "id") {
|
||||
id: ID!
|
||||
name: String!
|
||||
}
|
||||
|
||||
extend type User @key(fields: "id") {
|
||||
id: ID!
|
||||
pets: [Pet!]!
|
||||
}
|
||||
|
||||
type Query {
|
||||
pet(id: ID!): Pet
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package graph
|
||||
|
||||
// This file will be automatically regenerated based on the schema, any resolver implementations
|
||||
// will be copied through when generating and any unknown code will be moved to the end.
|
||||
// Code generated by github.com/99designs/gqlgen version v0.17.39
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/Dan6erbond/sitling/pets/graph/model"
|
||||
)
|
||||
|
||||
// Pet is the resolver for the pet field.
|
||||
func (r *queryResolver) Pet(ctx context.Context, id string) (*model.Pet, error) {
|
||||
return &model.Pet{ID: id, Name: "Ace"}, nil
|
||||
}
|
||||
|
||||
// Query returns QueryResolver implementation.
|
||||
func (r *Resolver) Query() QueryResolver { return &queryResolver{r} }
|
||||
|
||||
type queryResolver struct{ *Resolver }
|
@ -0,0 +1,28 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/99designs/gqlgen/graphql/handler"
|
||||
"github.com/99designs/gqlgen/graphql/playground"
|
||||
"github.com/Dan6erbond/sitling/pets/graph"
|
||||
)
|
||||
|
||||
const defaultPort = "3005"
|
||||
|
||||
func main() {
|
||||
port := os.Getenv("PORT")
|
||||
if port == "" {
|
||||
port = defaultPort
|
||||
}
|
||||
|
||||
srv := handler.NewDefaultServer(graph.NewExecutableSchema(graph.Config{Resolvers: &graph.Resolver{}}))
|
||||
|
||||
http.Handle("/", playground.Handler("GraphQL playground", "/query"))
|
||||
http.Handle("/query", srv)
|
||||
|
||||
log.Printf("connect to http://localhost:%s/ for GraphQL playground", port)
|
||||
log.Fatal(http.ListenAndServe(":"+port, nil))
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
//go:build tools
|
||||
// +build tools
|
||||
|
||||
package tools
|
||||
|
||||
import (
|
||||
_ "github.com/99designs/gqlgen"
|
||||
_ "github.com/99designs/gqlgen/graphql/introspection"
|
||||
)
|
@ -0,0 +1,21 @@
|
||||
# If you prefer the allow list template instead of the deny list, see community template:
|
||||
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
|
||||
#
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Test binary, built with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
|
||||
# Go workspace file
|
||||
go.work
|
@ -0,0 +1,26 @@
|
||||
module github.com/Dan6erbond/sitling/users
|
||||
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/99designs/gqlgen v0.17.39
|
||||
github.com/vektah/gqlparser/v2 v2.5.10
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/agnivade/levenshtein v1.1.1 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.3 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/sosodev/duration v1.1.0 // indirect
|
||||
github.com/urfave/cli/v2 v2.25.5 // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||
golang.org/x/mod v0.10.0 // indirect
|
||||
golang.org/x/sys v0.8.0 // indirect
|
||||
golang.org/x/text v0.9.0 // indirect
|
||||
golang.org/x/tools v0.9.3 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
@ -0,0 +1,47 @@
|
||||
github.com/99designs/gqlgen v0.17.39 h1:wPTAyc2fqVjAWT5DsJ21k/lLudgnXzURwbsjVNegFpU=
|
||||
github.com/99designs/gqlgen v0.17.39/go.mod h1:b62q1USk82GYIVjC60h02YguAZLqYZtvWml8KkhJps4=
|
||||
github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8=
|
||||
github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=
|
||||
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=
|
||||
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 h1:fRzb/w+pyskVMQ+UbP35JkH8yB7MYb4q/qhBarqZE6g=
|
||||
github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.3 h1:kmRrRLlInXvng0SmLxmQpQkpbYAvcXm7NPDrgxJa9mE=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.3/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
||||
github.com/sosodev/duration v1.1.0 h1:kQcaiGbJaIsRqgQy7VGlZrVw1giWO+lDoX3MCPnpVO4=
|
||||
github.com/sosodev/duration v1.1.0/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg=
|
||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||
github.com/urfave/cli/v2 v2.25.5 h1:d0NIAyhh5shGscroL7ek/Ya9QYQE0KNabJgiUinIQkc=
|
||||
github.com/urfave/cli/v2 v2.25.5/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
|
||||
github.com/vektah/gqlparser/v2 v2.5.10 h1:6zSM4azXC9u4Nxy5YmdmGu4uKamfwsdKTwp5zsEealU=
|
||||
github.com/vektah/gqlparser/v2 v2.5.10/go.mod h1:1rCcfwB2ekJofmluGWXMSEnPMZgbxzwj6FaZ/4OT8Cc=
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
|
||||
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
|
||||
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
|
||||
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM=
|
||||
golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
|
||||
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/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
@ -0,0 +1,88 @@
|
||||
# Where are all the schema files located? globs are supported eg src/**/*.graphqls
|
||||
schema:
|
||||
- graph/*.graphqls
|
||||
|
||||
# Where should the generated server code go?
|
||||
exec:
|
||||
filename: graph/generated.go
|
||||
package: graph
|
||||
|
||||
# Uncomment to enable federation
|
||||
federation:
|
||||
filename: graph/federation.go
|
||||
package: graph
|
||||
version: 2
|
||||
|
||||
# Where should any generated models go?
|
||||
model:
|
||||
filename: graph/model/models_gen.go
|
||||
package: model
|
||||
|
||||
# Where should the resolver implementations go?
|
||||
resolver:
|
||||
layout: follow-schema
|
||||
dir: graph
|
||||
package: graph
|
||||
filename_template: "{name}.resolvers.go"
|
||||
# Optional: turn on to not generate template comments above resolvers
|
||||
# omit_template_comment: false
|
||||
|
||||
# Optional: turn on use ` + "`" + `gqlgen:"fieldName"` + "`" + ` tags in your models
|
||||
# struct_tag: json
|
||||
|
||||
# Optional: turn on to use []Thing instead of []*Thing
|
||||
# omit_slice_element_pointers: false
|
||||
|
||||
# Optional: turn on to omit Is<Name>() methods to interface and unions
|
||||
# omit_interface_checks : true
|
||||
|
||||
# Optional: turn on to skip generation of ComplexityRoot struct content and Complexity function
|
||||
# omit_complexity: false
|
||||
|
||||
# Optional: turn on to not generate any file notice comments in generated files
|
||||
# omit_gqlgen_file_notice: false
|
||||
|
||||
# Optional: turn on to exclude the gqlgen version in the generated file notice. No effect if `omit_gqlgen_file_notice` is true.
|
||||
# omit_gqlgen_version_in_file_notice: false
|
||||
|
||||
# Optional: turn off to make struct-type struct fields not use pointers
|
||||
# e.g. type Thing struct { FieldA OtherThing } instead of { FieldA *OtherThing }
|
||||
# struct_fields_always_pointers: true
|
||||
|
||||
# Optional: turn off to make resolvers return values instead of pointers for structs
|
||||
# resolvers_always_return_pointers: true
|
||||
|
||||
# Optional: turn on to return pointers instead of values in unmarshalInput
|
||||
# return_pointers_in_unmarshalinput: false
|
||||
|
||||
# Optional: wrap nullable input fields with Omittable
|
||||
# nullable_input_omittable: true
|
||||
|
||||
# Optional: set to speed up generation time by not performing a final validation pass.
|
||||
# skip_validation: true
|
||||
|
||||
# Optional: set to skip running `go mod tidy` when generating server code
|
||||
# skip_mod_tidy: true
|
||||
|
||||
# gqlgen will search for any type names in the schema in these go packages
|
||||
# if they match it will use them, otherwise it will generate them.
|
||||
autobind:
|
||||
# - "github.com/Dan6erbond/sitling/users/users/graph/model"
|
||||
|
||||
# This section declares type mapping between the GraphQL and go type systems
|
||||
#
|
||||
# The first line in each type will be used as defaults for resolver arguments and
|
||||
# modelgen, the others will be allowed when binding to fields. Configure them to
|
||||
# your liking
|
||||
models:
|
||||
ID:
|
||||
model:
|
||||
- github.com/99designs/gqlgen/graphql.ID
|
||||
- github.com/99designs/gqlgen/graphql.Int
|
||||
- github.com/99designs/gqlgen/graphql.Int64
|
||||
- github.com/99designs/gqlgen/graphql.Int32
|
||||
Int:
|
||||
model:
|
||||
- github.com/99designs/gqlgen/graphql.Int
|
||||
- github.com/99designs/gqlgen/graphql.Int64
|
||||
- github.com/99designs/gqlgen/graphql.Int32
|
@ -0,0 +1,26 @@
|
||||
package graph
|
||||
|
||||
// This file will be automatically regenerated based on the schema, any resolver implementations
|
||||
// will be copied through when generating and any unknown code will be moved to the end.
|
||||
// Code generated by github.com/99designs/gqlgen version v0.17.39
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/Dan6erbond/sitling/users/graph/model"
|
||||
)
|
||||
|
||||
// FindPetByID is the resolver for the findPetByID field.
|
||||
func (r *entityResolver) FindPetByID(ctx context.Context, id string) (*model.Pet, error) {
|
||||
return &model.Pet{ID: id}, nil
|
||||
}
|
||||
|
||||
// FindUserByID is the resolver for the findUserByID field.
|
||||
func (r *entityResolver) FindUserByID(ctx context.Context, id string) (*model.User, error) {
|
||||
return &model.User{ID: id}, nil
|
||||
}
|
||||
|
||||
// Entity returns EntityResolver implementation.
|
||||
func (r *Resolver) Entity() EntityResolver { return &entityResolver{r} }
|
||||
|
||||
type entityResolver struct{ *Resolver }
|
@ -0,0 +1,224 @@
|
||||
// Code generated by github.com/99designs/gqlgen, DO NOT EDIT.
|
||||
|
||||
package graph
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/99designs/gqlgen/plugin/federation/fedruntime"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrUnknownType = errors.New("unknown type")
|
||||
ErrTypeNotFound = errors.New("type not found")
|
||||
)
|
||||
|
||||
func (ec *executionContext) __resolve__service(ctx context.Context) (fedruntime.Service, error) {
|
||||
if ec.DisableIntrospection {
|
||||
return fedruntime.Service{}, errors.New("federated introspection disabled")
|
||||
}
|
||||
|
||||
var sdl []string
|
||||
|
||||
for _, src := range sources {
|
||||
if src.BuiltIn {
|
||||
continue
|
||||
}
|
||||
sdl = append(sdl, src.Input)
|
||||
}
|
||||
|
||||
return fedruntime.Service{
|
||||
SDL: strings.Join(sdl, "\n"),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) __resolve_entities(ctx context.Context, representations []map[string]interface{}) []fedruntime.Entity {
|
||||
list := make([]fedruntime.Entity, len(representations))
|
||||
|
||||
repsMap := map[string]struct {
|
||||
i []int
|
||||
r []map[string]interface{}
|
||||
}{}
|
||||
|
||||
// We group entities by typename so that we can parallelize their resolution.
|
||||
// This is particularly helpful when there are entity groups in multi mode.
|
||||
buildRepresentationGroups := func(reps []map[string]interface{}) {
|
||||
for i, rep := range reps {
|
||||
typeName, ok := rep["__typename"].(string)
|
||||
if !ok {
|
||||
// If there is no __typename, we just skip the representation;
|
||||
// we just won't be resolving these unknown types.
|
||||
ec.Error(ctx, errors.New("__typename must be an existing string"))
|
||||
continue
|
||||
}
|
||||
|
||||
_r := repsMap[typeName]
|
||||
_r.i = append(_r.i, i)
|
||||
_r.r = append(_r.r, rep)
|
||||
repsMap[typeName] = _r
|
||||
}
|
||||
}
|
||||
|
||||
isMulti := func(typeName string) bool {
|
||||
switch typeName {
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
resolveEntity := func(ctx context.Context, typeName string, rep map[string]interface{}, idx []int, i int) (err error) {
|
||||
// we need to do our own panic handling, because we may be called in a
|
||||
// goroutine, where the usual panic handling can't catch us
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err = ec.Recover(ctx, r)
|
||||
}
|
||||
}()
|
||||
|
||||
switch typeName {
|
||||
case "Pet":
|
||||
resolverName, err := entityResolverNameForPet(ctx, rep)
|
||||
if err != nil {
|
||||
return fmt.Errorf(`finding resolver for Entity "Pet": %w`, err)
|
||||
}
|
||||
switch resolverName {
|
||||
|
||||
case "findPetByID":
|
||||
id0, err := ec.unmarshalNID2string(ctx, rep["id"])
|
||||
if err != nil {
|
||||
return fmt.Errorf(`unmarshalling param 0 for findPetByID(): %w`, err)
|
||||
}
|
||||
entity, err := ec.resolvers.Entity().FindPetByID(ctx, id0)
|
||||
if err != nil {
|
||||
return fmt.Errorf(`resolving Entity "Pet": %w`, err)
|
||||
}
|
||||
|
||||
list[idx[i]] = entity
|
||||
return nil
|
||||
}
|
||||
case "User":
|
||||
resolverName, err := entityResolverNameForUser(ctx, rep)
|
||||
if err != nil {
|
||||
return fmt.Errorf(`finding resolver for Entity "User": %w`, err)
|
||||
}
|
||||
switch resolverName {
|
||||
|
||||
case "findUserByID":
|
||||
id0, err := ec.unmarshalNID2string(ctx, rep["id"])
|
||||
if err != nil {
|
||||
return fmt.Errorf(`unmarshalling param 0 for findUserByID(): %w`, err)
|
||||
}
|
||||
entity, err := ec.resolvers.Entity().FindUserByID(ctx, id0)
|
||||
if err != nil {
|
||||
return fmt.Errorf(`resolving Entity "User": %w`, err)
|
||||
}
|
||||
|
||||
list[idx[i]] = entity
|
||||
return nil
|
||||
}
|
||||
|
||||
}
|
||||
return fmt.Errorf("%w: %s", ErrUnknownType, typeName)
|
||||
}
|
||||
|
||||
resolveManyEntities := func(ctx context.Context, typeName string, reps []map[string]interface{}, idx []int) (err error) {
|
||||
// we need to do our own panic handling, because we may be called in a
|
||||
// goroutine, where the usual panic handling can't catch us
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err = ec.Recover(ctx, r)
|
||||
}
|
||||
}()
|
||||
|
||||
switch typeName {
|
||||
|
||||
default:
|
||||
return errors.New("unknown type: " + typeName)
|
||||
}
|
||||
}
|
||||
|
||||
resolveEntityGroup := func(typeName string, reps []map[string]interface{}, idx []int) {
|
||||
if isMulti(typeName) {
|
||||
err := resolveManyEntities(ctx, typeName, reps, idx)
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
}
|
||||
} else {
|
||||
// if there are multiple entities to resolve, parallelize (similar to
|
||||
// graphql.FieldSet.Dispatch)
|
||||
var e sync.WaitGroup
|
||||
e.Add(len(reps))
|
||||
for i, rep := range reps {
|
||||
i, rep := i, rep
|
||||
go func(i int, rep map[string]interface{}) {
|
||||
err := resolveEntity(ctx, typeName, rep, idx, i)
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
}
|
||||
e.Done()
|
||||
}(i, rep)
|
||||
}
|
||||
e.Wait()
|
||||
}
|
||||
}
|
||||
buildRepresentationGroups(representations)
|
||||
|
||||
switch len(repsMap) {
|
||||
case 0:
|
||||
return list
|
||||
case 1:
|
||||
for typeName, reps := range repsMap {
|
||||
resolveEntityGroup(typeName, reps.r, reps.i)
|
||||
}
|
||||
return list
|
||||
default:
|
||||
var g sync.WaitGroup
|
||||
g.Add(len(repsMap))
|
||||
for typeName, reps := range repsMap {
|
||||
go func(typeName string, reps []map[string]interface{}, idx []int) {
|
||||
resolveEntityGroup(typeName, reps, idx)
|
||||
g.Done()
|
||||
}(typeName, reps.r, reps.i)
|
||||
}
|
||||
g.Wait()
|
||||
return list
|
||||
}
|
||||
}
|
||||
|
||||
func entityResolverNameForPet(ctx context.Context, rep map[string]interface{}) (string, error) {
|
||||
for {
|
||||
var (
|
||||
m map[string]interface{}
|
||||
val interface{}
|
||||
ok bool
|
||||
)
|
||||
_ = val
|
||||
m = rep
|
||||
if _, ok = m["id"]; !ok {
|
||||
break
|
||||
}
|
||||
return "findPetByID", nil
|
||||
}
|
||||
return "", fmt.Errorf("%w for Pet", ErrTypeNotFound)
|
||||
}
|
||||
|
||||
func entityResolverNameForUser(ctx context.Context, rep map[string]interface{}) (string, error) {
|
||||
for {
|
||||
var (
|
||||
m map[string]interface{}
|
||||
val interface{}
|
||||
ok bool
|
||||
)
|
||||
_ = val
|
||||
m = rep
|
||||
if _, ok = m["id"]; !ok {
|
||||
break
|
||||
}
|
||||
return "findUserByID", nil
|
||||
}
|
||||
return "", fmt.Errorf("%w for User", ErrTypeNotFound)
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,16 @@
|
||||
// Code generated by github.com/99designs/gqlgen, DO NOT EDIT.
|
||||
|
||||
package model
|
||||
|
||||
type Pet struct {
|
||||
ID string `json:"id"`
|
||||
Owners []*User `json:"owners"`
|
||||
}
|
||||
|
||||
func (Pet) IsEntity() {}
|
||||
|
||||
type User struct {
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
func (User) IsEntity() {}
|
@ -0,0 +1,8 @@
|
||||
//go:generate go run github.com/99designs/gqlgen generate
|
||||
package graph
|
||||
|
||||
// This file will not be regenerated automatically.
|
||||
//
|
||||
// It serves as dependency injection for your app, add any dependencies you require here.
|
||||
|
||||
type Resolver struct{}
|
@ -0,0 +1,8 @@
|
||||
type User @key(fields: "id") {
|
||||
id: ID!
|
||||
}
|
||||
|
||||
extend type Pet @key(fields: "id") {
|
||||
id: ID!
|
||||
owners: [User!]!
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/99designs/gqlgen/graphql/handler"
|
||||
"github.com/99designs/gqlgen/graphql/playground"
|
||||
"github.com/Dan6erbond/sitling/users/graph"
|
||||
)
|
||||
|
||||
const defaultPort = "3006"
|
||||
|
||||
func main() {
|
||||
port := os.Getenv("PORT")
|
||||
if port == "" {
|
||||
port = defaultPort
|
||||
}
|
||||
|
||||
srv := handler.NewDefaultServer(graph.NewExecutableSchema(graph.Config{Resolvers: &graph.Resolver{}}))
|
||||
|
||||
http.Handle("/", playground.Handler("GraphQL playground", "/query"))
|
||||
http.Handle("/query", srv)
|
||||
|
||||
log.Printf("connect to http://localhost:%s/ for GraphQL playground", port)
|
||||
log.Fatal(http.ListenAndServe(":"+port, nil))
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
//go:build tools
|
||||
// +build tools
|
||||
|
||||
package tools
|
||||
|
||||
import (
|
||||
_ "github.com/99designs/gqlgen"
|
||||
_ "github.com/99designs/gqlgen/graphql/introspection"
|
||||
)
|
Loading…
Reference in New Issue