Add initialization command to setup new apps
This commit is contained in:
parent
5e86b445c5
commit
ecec2968e9
|
@ -27,3 +27,4 @@
|
||||||
main
|
main
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.swp
|
.swp
|
||||||
|
main
|
||||||
|
|
13
Dockerfile
13
Dockerfile
|
@ -12,7 +12,9 @@ RUN apk update && \
|
||||||
apk add --no-cache upx=3.95-r2
|
apk add --no-cache upx=3.95-r2
|
||||||
|
|
||||||
RUN go get -u github.com/dosco/esc && \
|
RUN go get -u github.com/dosco/esc && \
|
||||||
go get -u github.com/pilu/fresh
|
go get -u github.com/shanzi/wu && \
|
||||||
|
go install github.com/shanzi/wu && \
|
||||||
|
go get github.com/GeertJohan/go.rice/rice
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY . /app
|
COPY . /app
|
||||||
|
@ -22,10 +24,13 @@ COPY --from=react-build /web/build/ ./web/build/
|
||||||
|
|
||||||
ENV GO111MODULE=on
|
ENV GO111MODULE=on
|
||||||
RUN go mod vendor
|
RUN go mod vendor
|
||||||
|
# RUN go generate ./... && \
|
||||||
|
# CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o super-graph && \
|
||||||
|
# upx --ultra-brute -qq super-graph && \
|
||||||
|
# upx -t super-graph
|
||||||
|
|
||||||
RUN go generate ./... && \
|
RUN go generate ./... && \
|
||||||
CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o super-graph && \
|
CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o super-graph
|
||||||
upx --ultra-brute -qq super-graph && \
|
|
||||||
upx -t super-graph
|
|
||||||
|
|
||||||
# stage: 3
|
# stage: 3
|
||||||
FROM alpine:latest
|
FROM alpine:latest
|
||||||
|
|
|
@ -80,7 +80,7 @@ database:
|
||||||
type: postgres
|
type: postgres
|
||||||
host: db
|
host: db
|
||||||
port: 5432
|
port: 5432
|
||||||
dbname: app_development
|
dbname: {{app_name_slug}}_development
|
||||||
user: postgres
|
user: postgres
|
||||||
password: ''
|
password: ''
|
||||||
#pool_size: 10
|
#pool_size: 10
|
||||||
|
|
|
@ -11,16 +11,16 @@ services:
|
||||||
# ports:
|
# ports:
|
||||||
# - "6379:6379"
|
# - "6379:6379"
|
||||||
|
|
||||||
rails_app:
|
# rails_app:
|
||||||
build: rails-app/.
|
# build: rails-app/.
|
||||||
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
|
# command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
|
||||||
volumes:
|
# volumes:
|
||||||
- ./rails-app:/app
|
# - ./rails-app:/app
|
||||||
- /app/tmp
|
# - /app/tmp
|
||||||
ports:
|
# ports:
|
||||||
- "3000:3000"
|
# - "3000:3000"
|
||||||
depends_on:
|
# depends_on:
|
||||||
- db
|
# - db
|
||||||
|
|
||||||
super_graph:
|
super_graph:
|
||||||
build:
|
build:
|
||||||
|
@ -34,9 +34,9 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
- .:/app
|
- .:/app
|
||||||
working_dir: /app
|
working_dir: /app
|
||||||
command: fresh -c fresh.conf
|
command: wu -pattern="*.go" go run main.go serv
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
- rails_app
|
#- rails_app
|
||||||
|
|
||||||
# - redis
|
# - redis
|
||||||
|
|
14
fresh.conf
14
fresh.conf
|
@ -1,14 +0,0 @@
|
||||||
root: .
|
|
||||||
tmp_path: ./tmp
|
|
||||||
build_name: runner-build
|
|
||||||
build_log: runner-build-errors.log
|
|
||||||
valid_ext: .go, .tpl, .tmpl, .html, .yml, *.list
|
|
||||||
no_rebuild_ext: .tpl, .tmpl, .html
|
|
||||||
ignored: web, tmp, vendor, rails-app, docs, slides, bench, corpus
|
|
||||||
build_delay: 600
|
|
||||||
colors: 1
|
|
||||||
log_color_main: cyan
|
|
||||||
log_color_build: yellow
|
|
||||||
log_color_runner: green
|
|
||||||
log_color_watcher: magenta
|
|
||||||
log_color_app:
|
|
4
go.mod
4
go.mod
|
@ -1,6 +1,7 @@
|
||||||
module github.com/dosco/super-graph
|
module github.com/dosco/super-graph
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/GeertJohan/go.rice v1.0.0
|
||||||
github.com/Masterminds/semver v1.4.2
|
github.com/Masterminds/semver v1.4.2
|
||||||
github.com/OneOfOne/xxhash v1.2.5 // indirect
|
github.com/OneOfOne/xxhash v1.2.5 // indirect
|
||||||
github.com/adjust/gorails v0.0.0-20171013043634-2786ed0c03d3
|
github.com/adjust/gorails v0.0.0-20171013043634-2786ed0c03d3
|
||||||
|
@ -35,6 +36,9 @@ require (
|
||||||
github.com/valyala/fasttemplate v1.0.1
|
github.com/valyala/fasttemplate v1.0.1
|
||||||
github.com/vaughan0/go-ini v0.0.0-20130923145212-a98ad7ee00ec
|
github.com/vaughan0/go-ini v0.0.0-20130923145212-a98ad7ee00ec
|
||||||
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7
|
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7
|
||||||
|
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127
|
||||||
mellium.im/sasl v0.2.1 // indirect
|
mellium.im/sasl v0.2.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
|
go 1.13
|
||||||
|
|
9
go.sum
9
go.sum
|
@ -4,6 +4,9 @@ cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7h
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
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 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0=
|
||||||
|
github.com/GeertJohan/go.rice v1.0.0 h1:KkI6O9uMaQU3VEKaj01ulavtF7o1fWT7+pk/4voiMLQ=
|
||||||
|
github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0=
|
||||||
github.com/Masterminds/semver v1.4.2 h1:WBLTQ37jOCzSLtXNdoo8bNM8876KhNqOKvrlGITgsTc=
|
github.com/Masterminds/semver v1.4.2 h1:WBLTQ37jOCzSLtXNdoo8bNM8876KhNqOKvrlGITgsTc=
|
||||||
github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
||||||
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
||||||
|
@ -15,6 +18,7 @@ github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWX
|
||||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||||
github.com/adjust/gorails v0.0.0-20171013043634-2786ed0c03d3 h1:+qz9Ga6l6lKw6fgvk5RMV5HQznSLvI8Zxajwdj4FhFg=
|
github.com/adjust/gorails v0.0.0-20171013043634-2786ed0c03d3 h1:+qz9Ga6l6lKw6fgvk5RMV5HQznSLvI8Zxajwdj4FhFg=
|
||||||
github.com/adjust/gorails v0.0.0-20171013043634-2786ed0c03d3/go.mod h1:FlkD11RtgMTYjVuBnb7cxoHmQGqvPpCsr2atC88nl/M=
|
github.com/adjust/gorails v0.0.0-20171013043634-2786ed0c03d3/go.mod h1:FlkD11RtgMTYjVuBnb7cxoHmQGqvPpCsr2atC88nl/M=
|
||||||
|
github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
|
||||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||||
|
@ -51,6 +55,8 @@ github.com/cznic/ql v1.2.0/go.mod h1:FbpzhyZrqr0PVlK6ury+PoW3T0ODUV22OeWIxcaOrSE
|
||||||
github.com/cznic/sortutil v0.0.0-20150617083342-4c7342852e65/go.mod h1:q2w6Bg5jeox1B+QkJ6Wp/+Vn0G/bo3f1uY7Fn3vivIQ=
|
github.com/cznic/sortutil v0.0.0-20150617083342-4c7342852e65/go.mod h1:q2w6Bg5jeox1B+QkJ6Wp/+Vn0G/bo3f1uY7Fn3vivIQ=
|
||||||
github.com/cznic/strutil v0.0.0-20171016134553-529a34b1c186/go.mod h1:AHHPPPXTw0h6pVabbcbyGRK1DckRn7r/STdZEeIDzZc=
|
github.com/cznic/strutil v0.0.0-20171016134553-529a34b1c186/go.mod h1:AHHPPPXTw0h6pVabbcbyGRK1DckRn7r/STdZEeIDzZc=
|
||||||
github.com/cznic/zappy v0.0.0-20160723133515-2533cb5b45cc/go.mod h1:Y1SNZ4dRUOKXshKUbwUapqNncRrho4mkjQebgEHZLj8=
|
github.com/cznic/zappy v0.0.0-20160723133515-2533cb5b45cc/go.mod h1:Y1SNZ4dRUOKXshKUbwUapqNncRrho4mkjQebgEHZLj8=
|
||||||
|
github.com/daaku/go.zipexe v1.0.0 h1:VSOgZtH418pH9L16hC/JrgSNJbbAL26pj7lmD1+CGdY=
|
||||||
|
github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
@ -171,6 +177,7 @@ github.com/jackc/puddle v1.0.0 h1:rbjAshlgKscNa7j0jAM0uNQflis5o2XUogPMVAwtcsM=
|
||||||
github.com/jackc/puddle v1.0.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
github.com/jackc/puddle v1.0.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||||
github.com/jackc/tern v1.8.2 h1:+d9eK83fRS0dbf6nt+2tjILYF4FKG1O5xTFB8Lzc66U=
|
github.com/jackc/tern v1.8.2 h1:+d9eK83fRS0dbf6nt+2tjILYF4FKG1O5xTFB8Lzc66U=
|
||||||
github.com/jackc/tern v1.8.2/go.mod h1:AMppp2oyCT6rYnJHLLMmPWwahfFvdIVi6mr9gH81Nxs=
|
github.com/jackc/tern v1.8.2/go.mod h1:AMppp2oyCT6rYnJHLLMmPWwahfFvdIVi6mr9gH81Nxs=
|
||||||
|
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||||
github.com/jinzhu/inflection v0.0.0-20180308033659-04140366298a h1:eeaG9XMUvRBYXJi4pg1ZKM7nxc5AfXfojeLLW7O5J3k=
|
github.com/jinzhu/inflection v0.0.0-20180308033659-04140366298a h1:eeaG9XMUvRBYXJi4pg1ZKM7nxc5AfXfojeLLW7O5J3k=
|
||||||
github.com/jinzhu/inflection v0.0.0-20180308033659-04140366298a/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
github.com/jinzhu/inflection v0.0.0-20180308033659-04140366298a/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||||
|
@ -209,6 +216,7 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh
|
||||||
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
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/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/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8/go.mod h1:86wM1zFnC6/uDBfZGNwB65O+pR2OFi5q/YQaEUid1qA=
|
||||||
|
github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E=
|
||||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w=
|
github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w=
|
||||||
|
@ -332,6 +340,7 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190424112056-4829fb13d2c6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190424112056-4829fb13d2c6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 h1:fHDIZ2oxGnUZRN6WgWFCbYBjH9uqVPRCUVUDhs0wnbA=
|
||||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
|
|
|
@ -0,0 +1,152 @@
|
||||||
|
app_name: "Hello Development"
|
||||||
|
host_port: 0.0.0.0:8080
|
||||||
|
web_ui: true
|
||||||
|
|
||||||
|
# debug, info, warn, error, fatal, panic
|
||||||
|
log_level: "debug"
|
||||||
|
|
||||||
|
# Disable this in development to get a list of
|
||||||
|
# queries used. When enabled super graph
|
||||||
|
# will only allow queries from this list
|
||||||
|
# List saved to ./config/allow.list
|
||||||
|
use_allow_list: false
|
||||||
|
|
||||||
|
# Throw a 401 on auth failure for queries that need auth
|
||||||
|
# valid values: always, per_query, never
|
||||||
|
auth_fail_block: never
|
||||||
|
|
||||||
|
# Latency tracing for database queries and remote joins
|
||||||
|
# the resulting latency information is returned with the
|
||||||
|
# response
|
||||||
|
enable_tracing: true
|
||||||
|
|
||||||
|
# Watch the config folder and reload Super Graph
|
||||||
|
# with the new configs when a change is detected
|
||||||
|
reload_on_config_change: true
|
||||||
|
|
||||||
|
# File that points to the database seeding script
|
||||||
|
# seed_file: seed.js
|
||||||
|
|
||||||
|
# Path pointing to where the migrations can be found
|
||||||
|
migrations_path: ./config/migrations
|
||||||
|
|
||||||
|
# Postgres related environment Variables
|
||||||
|
# SG_DATABASE_HOST
|
||||||
|
# SG_DATABASE_PORT
|
||||||
|
# SG_DATABASE_USER
|
||||||
|
# SG_DATABASE_PASSWORD
|
||||||
|
|
||||||
|
# Auth related environment Variables
|
||||||
|
# SG_AUTH_RAILS_COOKIE_SECRET_KEY_BASE
|
||||||
|
# SG_AUTH_RAILS_REDIS_URL
|
||||||
|
# SG_AUTH_RAILS_REDIS_PASSWORD
|
||||||
|
# SG_AUTH_JWT_PUBLIC_KEY_FILE
|
||||||
|
|
||||||
|
# inflections:
|
||||||
|
# person: people
|
||||||
|
# sheep: sheep
|
||||||
|
|
||||||
|
auth:
|
||||||
|
# Can be 'rails' or 'jwt'
|
||||||
|
type: rails
|
||||||
|
cookie: _app_session
|
||||||
|
|
||||||
|
# Comment this out if you want to disable setting
|
||||||
|
# the user_id via a header. Good for testing
|
||||||
|
header: X-User-ID
|
||||||
|
|
||||||
|
rails:
|
||||||
|
# Rails version this is used for reading the
|
||||||
|
# various cookies formats.
|
||||||
|
version: 5.2
|
||||||
|
|
||||||
|
# Found in 'Rails.application.config.secret_key_base'
|
||||||
|
secret_key_base: 0a248500a64c01184edb4d7ad3a805488f8097ac761b76aaa6c17c01dcb7af03a2f18ba61b2868134b9c7b79a122bc0dadff4367414a2d173297bfea92be5566
|
||||||
|
|
||||||
|
# Remote cookie store. (memcache or redis)
|
||||||
|
# url: redis://redis:6379
|
||||||
|
# password: ""
|
||||||
|
# max_idle: 80
|
||||||
|
# max_active: 12000
|
||||||
|
|
||||||
|
# In most cases you don't need these
|
||||||
|
# salt: "encrypted cookie"
|
||||||
|
# sign_salt: "signed encrypted cookie"
|
||||||
|
# auth_salt: "authenticated encrypted cookie"
|
||||||
|
|
||||||
|
# jwt:
|
||||||
|
# provider: auth0
|
||||||
|
# secret: abc335bfcfdb04e50db5bb0a4d67ab9
|
||||||
|
# public_key_file: /secrets/public_key.pem
|
||||||
|
# public_key_type: ecdsa #rsa
|
||||||
|
|
||||||
|
database:
|
||||||
|
type: postgres
|
||||||
|
host: db
|
||||||
|
port: 5432
|
||||||
|
dbname: hello_database
|
||||||
|
user: postgres
|
||||||
|
password: ''
|
||||||
|
|
||||||
|
#schema: "public"
|
||||||
|
#pool_size: 10
|
||||||
|
#max_retries: 0
|
||||||
|
#log_level: "debug"
|
||||||
|
|
||||||
|
# Define variables here that you want to use in filters
|
||||||
|
# sub-queries must be wrapped in ()
|
||||||
|
variables:
|
||||||
|
account_id: "(select account_id from users where id = $user_id)"
|
||||||
|
|
||||||
|
# Define defaults to for the field key and values below
|
||||||
|
defaults:
|
||||||
|
# filter: ["{ user_id: { eq: $user_id } }"]
|
||||||
|
|
||||||
|
# Field and table names that you wish to block
|
||||||
|
blocklist:
|
||||||
|
- ar_internal_metadata
|
||||||
|
- schema_migrations
|
||||||
|
- secret
|
||||||
|
- password
|
||||||
|
- encrypted
|
||||||
|
- token
|
||||||
|
|
||||||
|
tables:
|
||||||
|
- name: users
|
||||||
|
# This filter will overwrite defaults.filter
|
||||||
|
# filter: ["{ id: { eq: $user_id } }"]
|
||||||
|
|
||||||
|
# - name: products
|
||||||
|
# # Multiple filters are AND'd together
|
||||||
|
# filter: [
|
||||||
|
# "{ price: { gt: 0 } }",
|
||||||
|
# "{ price: { lt: 8 } }"
|
||||||
|
# ]
|
||||||
|
|
||||||
|
- name: customers
|
||||||
|
# No filter is used for this field not
|
||||||
|
# even defaults.filter
|
||||||
|
filter: none
|
||||||
|
|
||||||
|
remotes:
|
||||||
|
- name: payments
|
||||||
|
id: stripe_id
|
||||||
|
url: http://rails_app:3000/stripe/$id
|
||||||
|
path: data
|
||||||
|
# debug: true
|
||||||
|
pass_headers:
|
||||||
|
- cookie
|
||||||
|
set_headers:
|
||||||
|
- name: Host
|
||||||
|
value: 0.0.0.0
|
||||||
|
# - name: Authorization
|
||||||
|
# value: Bearer <stripe_api_key>
|
||||||
|
|
||||||
|
- # You can create new fields that have a
|
||||||
|
# real db table backing them
|
||||||
|
name: me
|
||||||
|
table: users
|
||||||
|
filter: ["{ id: { eq: $user_id } }"]
|
||||||
|
|
||||||
|
# - name: posts
|
||||||
|
# filter: ["{ account_id: { _eq: $account_id } }"]
|
|
@ -0,0 +1,21 @@
|
||||||
|
-- Write your migrate up statements here
|
||||||
|
|
||||||
|
CREATE DATABASE hello_database
|
||||||
|
|
||||||
|
-- CREATE TABLE public.users (
|
||||||
|
-- id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||||
|
-- full_name text
|
||||||
|
-- email text UNIQUE NOT NULL CHECK (length(email) < 255),
|
||||||
|
-- encrypted_password text,
|
||||||
|
-- created_at timestamptz NOT NULL NOT NULL DEFAULT NOW(),
|
||||||
|
-- updated_at timestamptz NOT NULL NOT NULL DEFAULT NOW()
|
||||||
|
-- );
|
||||||
|
|
||||||
|
---- create above / drop below ----
|
||||||
|
|
||||||
|
-- Write your migrate down statements here. If this migration is irreversible
|
||||||
|
-- Then delete the separator line above.
|
||||||
|
|
||||||
|
-- DROP TABLE public.users
|
||||||
|
|
||||||
|
DROP DATABASE IF EXISTS hello_database
|
|
@ -0,0 +1,144 @@
|
||||||
|
app_name: "Hello Production"
|
||||||
|
host_port: 0.0.0.0:8080
|
||||||
|
web_ui: false
|
||||||
|
|
||||||
|
# debug, info, warn, error, fatal, panic, disable
|
||||||
|
log_level: "info"
|
||||||
|
|
||||||
|
# Disable this in development to get a list of
|
||||||
|
# queries used. When enabled super graph
|
||||||
|
# will only allow queries from this list
|
||||||
|
# List saved to ./config/allow.list
|
||||||
|
use_allow_list: true
|
||||||
|
|
||||||
|
# Throw a 401 on auth failure for queries that need auth
|
||||||
|
# valid values: always, per_query, never
|
||||||
|
auth_fail_block: always
|
||||||
|
|
||||||
|
# Latency tracing for database queries and remote joins
|
||||||
|
# the resulting latency information is returned with the
|
||||||
|
# response
|
||||||
|
enable_tracing: true
|
||||||
|
|
||||||
|
# File that points to the database seeding script
|
||||||
|
# seed_file: seed.js
|
||||||
|
|
||||||
|
# Path pointing to where the migrations can be found
|
||||||
|
# migrations_path: migrations
|
||||||
|
|
||||||
|
# Postgres related environment Variables
|
||||||
|
# SG_DATABASE_HOST
|
||||||
|
# SG_DATABASE_PORT
|
||||||
|
# SG_DATABASE_USER
|
||||||
|
# SG_DATABASE_PASSWORD
|
||||||
|
|
||||||
|
# Auth related environment Variables
|
||||||
|
# SG_AUTH_RAILS_COOKIE_SECRET_KEY_BASE
|
||||||
|
# SG_AUTH_RAILS_REDIS_URL
|
||||||
|
# SG_AUTH_RAILS_REDIS_PASSWORD
|
||||||
|
# SG_AUTH_JWT_PUBLIC_KEY_FILE
|
||||||
|
|
||||||
|
# inflections:
|
||||||
|
# person: people
|
||||||
|
# sheep: sheep
|
||||||
|
|
||||||
|
auth:
|
||||||
|
# Can be 'rails' or 'jwt'
|
||||||
|
type: rails
|
||||||
|
cookie: _app_session
|
||||||
|
|
||||||
|
# Comment this out if you want to disable setting
|
||||||
|
# the user_id via a header. Good for testing
|
||||||
|
header: X-User-ID
|
||||||
|
|
||||||
|
rails:
|
||||||
|
# Rails version this is used for reading the
|
||||||
|
# various cookies formats.
|
||||||
|
version: 5.2
|
||||||
|
|
||||||
|
# Found in 'Rails.application.config.secret_key_base'
|
||||||
|
secret_key_base: 0a248500a64c01184edb4d7ad3a805488f8097ac761b76aaa6c17c01dcb7af03a2f18ba61b2868134b9c7b79a122bc0dadff4367414a2d173297bfea92be5566
|
||||||
|
|
||||||
|
# Remote cookie store. (memcache or redis)
|
||||||
|
# url: redis://127.0.0.1:6379
|
||||||
|
# password: test
|
||||||
|
# max_idle: 80,
|
||||||
|
# max_active: 12000,
|
||||||
|
|
||||||
|
# In most cases you don't need these
|
||||||
|
# salt: "encrypted cookie"
|
||||||
|
# sign_salt: "signed encrypted cookie"
|
||||||
|
# auth_salt: "authenticated encrypted cookie"
|
||||||
|
|
||||||
|
# jwt:
|
||||||
|
# provider: auth0
|
||||||
|
# secret: abc335bfcfdb04e50db5bb0a4d67ab9
|
||||||
|
# public_key_file: /secrets/public_key.pem
|
||||||
|
# public_key_type: ecdsa #rsa
|
||||||
|
|
||||||
|
database:
|
||||||
|
type: postgres
|
||||||
|
host: db
|
||||||
|
port: 5432
|
||||||
|
dbname: hello_database
|
||||||
|
user: postgres
|
||||||
|
password: ''
|
||||||
|
#pool_size: 10
|
||||||
|
#max_retries: 0
|
||||||
|
#log_level: "debug"
|
||||||
|
|
||||||
|
# Define variables here that you want to use in filters
|
||||||
|
# sub-queries must be wrapped in ()
|
||||||
|
variables:
|
||||||
|
account_id: "(select account_id from users where id = $user_id)"
|
||||||
|
|
||||||
|
# Define defaults to for the field key and values below
|
||||||
|
defaults:
|
||||||
|
filter: ["{ user_id: { eq: $user_id } }"]
|
||||||
|
|
||||||
|
# Field and table names that you wish to block
|
||||||
|
blocklist:
|
||||||
|
- ar_internal_metadata
|
||||||
|
- schema_migrations
|
||||||
|
- secret
|
||||||
|
- password
|
||||||
|
- encrypted
|
||||||
|
- token
|
||||||
|
|
||||||
|
tables:
|
||||||
|
- name: users
|
||||||
|
# This filter will overwrite defaults.filter
|
||||||
|
filter: ["{ id: { eq: $user_id } }"]
|
||||||
|
|
||||||
|
- name: products
|
||||||
|
# Multiple filters are AND'd together
|
||||||
|
filter: [
|
||||||
|
"{ price: { gt: 0 } }",
|
||||||
|
"{ price: { lt: 8 } }"
|
||||||
|
]
|
||||||
|
|
||||||
|
- name: customers
|
||||||
|
# No filter is used for this field not
|
||||||
|
# even defaults.filter
|
||||||
|
filter: none
|
||||||
|
|
||||||
|
# remotes:
|
||||||
|
# - name: payments
|
||||||
|
# id: stripe_id
|
||||||
|
# url: http://rails_app:3000/stripe/$id
|
||||||
|
# path: data
|
||||||
|
# # pass_headers:
|
||||||
|
# # - cookie
|
||||||
|
# # - host
|
||||||
|
# set_headers:
|
||||||
|
# - name: Authorization
|
||||||
|
# value: Bearer <stripe_api_key>
|
||||||
|
|
||||||
|
- # You can create new fields that have a
|
||||||
|
# real db table backing them
|
||||||
|
name: me
|
||||||
|
table: users
|
||||||
|
filter: ["{ id: { eq: $user_id } }"]
|
||||||
|
|
||||||
|
# - name: posts
|
||||||
|
# filter: ["{ account_id: { _eq: $account_id } }"]
|
|
@ -0,0 +1,17 @@
|
||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
db:
|
||||||
|
image: postgres
|
||||||
|
ports:
|
||||||
|
- "5432:5432"
|
||||||
|
|
||||||
|
hello_api:
|
||||||
|
image: dosco/super-graph:latest
|
||||||
|
environment:
|
||||||
|
GO_ENV: "development"
|
||||||
|
volumes:
|
||||||
|
- ./config:/config
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
|
depends_on:
|
||||||
|
- db
|
|
@ -0,0 +1,17 @@
|
||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
db:
|
||||||
|
image: postgres
|
||||||
|
ports:
|
||||||
|
- "5432:5432"
|
||||||
|
|
||||||
|
hello_api:
|
||||||
|
image: dosco/super-graph:latest
|
||||||
|
environment:
|
||||||
|
GO_ENV: "development"
|
||||||
|
volumes:
|
||||||
|
- ./config:/config
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
|
depends_on:
|
||||||
|
- db
|
|
@ -337,21 +337,21 @@ func (c *compilerContext) renderJoinClose(sel *qcode.Select) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *compilerContext) renderJoinTable(sel *qcode.Select) {
|
func (c *compilerContext) renderJoinTable(sel *qcode.Select) error {
|
||||||
parent := &c.s[sel.ParentID]
|
parent := &c.s[sel.ParentID]
|
||||||
|
|
||||||
rel, err := c.schema.GetRel(sel.Table, parent.Table)
|
rel, err := c.schema.GetRel(sel.Table, parent.Table)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if rel.Type != RelOneToManyThrough {
|
if rel.Type != RelOneToManyThrough {
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
pt, err := c.schema.GetTable(parent.Table)
|
pt, err := c.schema.GetTable(parent.Table)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
//fmt.Fprintf(w, ` LEFT OUTER JOIN "%s" ON (("%s"."%s") = ("%s_%d"."%s"))`,
|
//fmt.Fprintf(w, ` LEFT OUTER JOIN "%s" ON (("%s"."%s") = ("%s_%d"."%s"))`,
|
||||||
|
@ -363,6 +363,8 @@ func (c *compilerContext) renderJoinTable(sel *qcode.Select) {
|
||||||
c.w.WriteString(`) = (`)
|
c.w.WriteString(`) = (`)
|
||||||
colWithTableID(c.w, pt.Name, parent.ID, rel.Col1)
|
colWithTableID(c.w, pt.Name, parent.ID, rel.Col1)
|
||||||
c.w.WriteString(`))`)
|
c.w.WriteString(`))`)
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *compilerContext) renderColumns(sel *qcode.Select) {
|
func (c *compilerContext) renderColumns(sel *qcode.Select) {
|
||||||
|
@ -537,10 +539,15 @@ func (c *compilerContext) renderBaseSelect(sel *qcode.Select, ti *DBTableInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isRoot {
|
if !isRoot {
|
||||||
c.renderJoinTable(sel)
|
if err := c.renderJoinTable(sel); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
c.w.WriteString(` WHERE (`)
|
c.w.WriteString(` WHERE (`)
|
||||||
c.renderRelationship(sel)
|
|
||||||
|
if err := c.renderRelationship(sel); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if isFil {
|
if isFil {
|
||||||
c.w.WriteString(` AND `)
|
c.w.WriteString(` AND `)
|
||||||
|
@ -610,12 +617,12 @@ func (c *compilerContext) renderOrderByColumns(sel *qcode.Select) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *compilerContext) renderRelationship(sel *qcode.Select) {
|
func (c *compilerContext) renderRelationship(sel *qcode.Select) error {
|
||||||
parent := c.s[sel.ParentID]
|
parent := c.s[sel.ParentID]
|
||||||
|
|
||||||
rel, err := c.schema.GetRel(sel.Table, parent.Table)
|
rel, err := c.schema.GetRel(sel.Table, parent.Table)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
switch rel.Type {
|
switch rel.Type {
|
||||||
|
@ -646,6 +653,8 @@ func (c *compilerContext) renderRelationship(sel *qcode.Select) {
|
||||||
colWithTable(c.w, rel.Through, rel.Col2)
|
colWithTable(c.w, rel.Through, rel.Col2)
|
||||||
c.w.WriteString(`))`)
|
c.w.WriteString(`))`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *compilerContext) renderWhere(sel *qcode.Select, ti *DBTableInfo) error {
|
func (c *compilerContext) renderWhere(sel *qcode.Select, ti *DBTableInfo) error {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
@ -31,20 +32,20 @@ type allowList struct {
|
||||||
active bool
|
active bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func initAllowList(path string) {
|
func initAllowList(cpath string) {
|
||||||
_allowList = allowList{
|
_allowList = allowList{
|
||||||
list: make(map[string]*allowItem),
|
list: make(map[string]*allowItem),
|
||||||
saveChan: make(chan *allowItem),
|
saveChan: make(chan *allowItem),
|
||||||
active: true,
|
active: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(path) != 0 {
|
if len(cpath) != 0 {
|
||||||
fp := fmt.Sprintf("%s/allow.list", path)
|
fp := path.Join(cpath, "allow.list")
|
||||||
|
|
||||||
if _, err := os.Stat(fp); err == nil {
|
if _, err := os.Stat(fp); err == nil {
|
||||||
_allowList.filepath = fp
|
_allowList.filepath = fp
|
||||||
} else if !os.IsNotExist(err) {
|
} else if !os.IsNotExist(err) {
|
||||||
panic(err)
|
logger.Fatal().Err(err).Send()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +55,7 @@ func initAllowList(path string) {
|
||||||
if _, err := os.Stat(fp); err == nil {
|
if _, err := os.Stat(fp); err == nil {
|
||||||
_allowList.filepath = fp
|
_allowList.filepath = fp
|
||||||
} else if !os.IsNotExist(err) {
|
} else if !os.IsNotExist(err) {
|
||||||
panic(err)
|
logger.Fatal().Err(err).Send()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,15 +65,25 @@ func initAllowList(path string) {
|
||||||
if _, err := os.Stat(fp); err == nil {
|
if _, err := os.Stat(fp); err == nil {
|
||||||
_allowList.filepath = fp
|
_allowList.filepath = fp
|
||||||
} else if !os.IsNotExist(err) {
|
} else if !os.IsNotExist(err) {
|
||||||
panic(err)
|
logger.Fatal().Err(err).Send()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(_allowList.filepath) == 0 {
|
if len(_allowList.filepath) == 0 {
|
||||||
panic("allow.list not found")
|
if conf.UseAllowList {
|
||||||
}
|
logger.Fatal().Msg("allow.list not found")
|
||||||
|
}
|
||||||
|
|
||||||
_allowList.load()
|
if len(cpath) == 0 {
|
||||||
|
_allowList.filepath = "./config/allow.list"
|
||||||
|
} else {
|
||||||
|
_allowList.filepath = path.Join(cpath, "allow.list")
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Warn().Msg("allow.list not found")
|
||||||
|
} else {
|
||||||
|
_allowList.load()
|
||||||
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for v := range _allowList.saveChan {
|
for v := range _allowList.saveChan {
|
||||||
|
@ -182,7 +193,7 @@ func (al *allowList) save(item *allowItem) {
|
||||||
|
|
||||||
f, err := os.Create(al.filepath)
|
f, err := os.Create(al.filepath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warn().Err(err).Msg("Failed to write allow list to file")
|
logger.Warn().Err(err).Msgf("Failed to write allow list: %s", al.filepath)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ func jwtHandler(next http.HandlerFunc) http.HandlerFunc {
|
||||||
case len(publicKeyFile) != 0:
|
case len(publicKeyFile) != 0:
|
||||||
kd, err := ioutil.ReadFile(publicKeyFile)
|
kd, err := ioutil.ReadFile(publicKeyFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
logger.Fatal().Err(err).Send()
|
||||||
}
|
}
|
||||||
|
|
||||||
switch conf.Auth.JWT.PubKeyType {
|
switch conf.Auth.JWT.PubKeyType {
|
||||||
|
@ -51,7 +51,7 @@ func jwtHandler(next http.HandlerFunc) http.HandlerFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
logger.Fatal().Err(err).Send()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,13 +28,13 @@ func railsRedisHandler(next http.HandlerFunc) http.HandlerFunc {
|
||||||
Dial: func() (redis.Conn, error) {
|
Dial: func() (redis.Conn, error) {
|
||||||
c, err := redis.DialURL(conf.Auth.Rails.URL)
|
c, err := redis.DialURL(conf.Auth.Rails.URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
logger.Fatal().Err(err).Send()
|
||||||
}
|
}
|
||||||
|
|
||||||
pwd := conf.Auth.Rails.Password
|
pwd := conf.Auth.Rails.Password
|
||||||
if len(pwd) != 0 {
|
if len(pwd) != 0 {
|
||||||
if _, err := c.Do("AUTH", pwd); err != nil {
|
if _, err := c.Do("AUTH", pwd); err != nil {
|
||||||
panic(err)
|
logger.Fatal().Err(err).Send()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return c, err
|
return c, err
|
||||||
|
|
17
serv/cmd.go
17
serv/cmd.go
|
@ -17,8 +17,6 @@ import (
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate esc -o static.go -ignore \\.DS_Store -prefix ../web/build -private -pkg serv ../web/build
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
serverName = "Super Graph"
|
serverName = "Super Graph"
|
||||||
|
|
||||||
|
@ -42,11 +40,10 @@ var (
|
||||||
migrateCmd *cobra.Command
|
migrateCmd *cobra.Command
|
||||||
statusCmd *cobra.Command
|
statusCmd *cobra.Command
|
||||||
newMigrationCmd *cobra.Command
|
newMigrationCmd *cobra.Command
|
||||||
|
initCmd *cobra.Command
|
||||||
)
|
)
|
||||||
|
|
||||||
func Init() {
|
func Init() {
|
||||||
var err error
|
|
||||||
|
|
||||||
rootCmd = &cobra.Command{
|
rootCmd = &cobra.Command{
|
||||||
Use: "super-graph",
|
Use: "super-graph",
|
||||||
Short: "An instant high-performance GraphQL API. No code needed. https://supergraph.dev",
|
Short: "An instant high-performance GraphQL API. No code needed. https://supergraph.dev",
|
||||||
|
@ -110,6 +107,13 @@ e.g. tern migrate -d last
|
||||||
Run: cmdNewMigration,
|
Run: cmdNewMigration,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initCmd = &cobra.Command{
|
||||||
|
Use: "init APP-NAME",
|
||||||
|
Short: "Initialize a new application",
|
||||||
|
Long: "Generate all the required files to start on a new Super Graph app",
|
||||||
|
Run: cmdInit,
|
||||||
|
}
|
||||||
|
|
||||||
logger = initLog()
|
logger = initLog()
|
||||||
|
|
||||||
rootCmd.Flags().StringVar(&confPath,
|
rootCmd.Flags().StringVar(&confPath,
|
||||||
|
@ -118,16 +122,13 @@ e.g. tern migrate -d last
|
||||||
//cmdMigrate.Flags().StringVarP(&cliOptions.destinationVersion,
|
//cmdMigrate.Flags().StringVarP(&cliOptions.destinationVersion,
|
||||||
// "destination", "d", "last", "destination migration version")
|
// "destination", "d", "last", "destination migration version")
|
||||||
|
|
||||||
|
rootCmd.AddCommand(initCmd)
|
||||||
rootCmd.AddCommand(servCmd)
|
rootCmd.AddCommand(servCmd)
|
||||||
rootCmd.AddCommand(seedCmd)
|
rootCmd.AddCommand(seedCmd)
|
||||||
rootCmd.AddCommand(migrateCmd)
|
rootCmd.AddCommand(migrateCmd)
|
||||||
rootCmd.AddCommand(statusCmd)
|
rootCmd.AddCommand(statusCmd)
|
||||||
rootCmd.AddCommand(newMigrationCmd)
|
rootCmd.AddCommand(newMigrationCmd)
|
||||||
|
|
||||||
if conf, err = initConf(); err != nil {
|
|
||||||
logger.Fatal().Err(err).Msg("failed to read config")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := rootCmd.Execute(); err != nil {
|
if err := rootCmd.Execute(); err != nil {
|
||||||
logger.Fatal().Err(err).Send()
|
logger.Fatal().Err(err).Send()
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
package serv
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
|
rice "github.com/GeertJohan/go.rice"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
func cmdInit(cmd *cobra.Command, args []string) {
|
||||||
|
if len(args) != 1 {
|
||||||
|
cmd.Help()
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpl := newTempl(map[string]string{
|
||||||
|
"app_name": strings.Title(strings.Join(args, " ")),
|
||||||
|
"app_name_slug": strings.ToLower(strings.Join(args, "_")),
|
||||||
|
})
|
||||||
|
|
||||||
|
// Create app folder and add relevant files
|
||||||
|
|
||||||
|
name := args[0]
|
||||||
|
appPath := path.Join("./", name)
|
||||||
|
|
||||||
|
ifNotExists(appPath, func(p string) error {
|
||||||
|
return os.Mkdir(p, os.ModePerm)
|
||||||
|
})
|
||||||
|
|
||||||
|
ifNotExists(path.Join(appPath, "seed.js"), func(p string) error {
|
||||||
|
if v, err := tmpl.get("docker-compose.yml"); err == nil {
|
||||||
|
return ioutil.WriteFile(p, v, 0644)
|
||||||
|
} else {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
ifNotExists(path.Join(appPath, "docker-compose.yml"), func(p string) error {
|
||||||
|
if v, err := tmpl.get("docker-compose.yml"); err == nil {
|
||||||
|
return ioutil.WriteFile(p, v, 0644)
|
||||||
|
} else {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Create app config folder and add relevant files
|
||||||
|
|
||||||
|
appConfigPath := path.Join(appPath, "config")
|
||||||
|
|
||||||
|
ifNotExists(appConfigPath, func(p string) error {
|
||||||
|
return os.Mkdir(p, os.ModePerm)
|
||||||
|
})
|
||||||
|
|
||||||
|
ifNotExists(path.Join(appConfigPath, "dev.yml"), func(p string) error {
|
||||||
|
if v, err := tmpl.get("dev.yml"); err == nil {
|
||||||
|
return ioutil.WriteFile(p, v, 0644)
|
||||||
|
} else {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
ifNotExists(path.Join(appConfigPath, "prod.yml"), func(p string) error {
|
||||||
|
if v, err := tmpl.get("prod.yml"); err == nil {
|
||||||
|
return ioutil.WriteFile(p, v, 0644)
|
||||||
|
} else {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Create app migrations folder and add relevant files
|
||||||
|
|
||||||
|
appMigrationsPath := path.Join(appConfigPath, "migrations")
|
||||||
|
|
||||||
|
ifNotExists(appMigrationsPath, func(p string) error {
|
||||||
|
return os.Mkdir(p, os.ModePerm)
|
||||||
|
})
|
||||||
|
|
||||||
|
ifNotExists(path.Join(appMigrationsPath, "100_init.sql"), func(p string) error {
|
||||||
|
if v, err := tmpl.get("100_init.sql"); err == nil {
|
||||||
|
return ioutil.WriteFile(p, v, 0644)
|
||||||
|
} else {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
logger.Info().Msgf("app '%s' initialized", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Templ struct {
|
||||||
|
*rice.Box
|
||||||
|
data map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newTempl(data map[string]string) *Templ {
|
||||||
|
return &Templ{rice.MustFindBox("../tmpl"), data}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Templ) get(name string) ([]byte, error) {
|
||||||
|
v := t.MustString(name)
|
||||||
|
b := bytes.Buffer{}
|
||||||
|
tm := template.Must(template.New(name).Parse(v))
|
||||||
|
|
||||||
|
if err := tm.Execute(&b, t.data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return b.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ifNotExists(filePath string, doFn func(string) error) {
|
||||||
|
_, err := os.Stat(filePath)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
logger.Info().Err(err).Msgf("create skipped '%s' exists", filePath)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if os.IsNotExist(err) == false {
|
||||||
|
logger.Fatal().Err(err).Msgf("unable to check if '%s' exists", filePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = doFn(filePath)
|
||||||
|
if err != nil {
|
||||||
|
logger.Fatal().Err(err).Msgf("unable to create '%s'", filePath)
|
||||||
|
}
|
||||||
|
logger.Info().Msgf("created '%s'", filePath)
|
||||||
|
}
|
|
@ -16,6 +16,11 @@ import (
|
||||||
|
|
||||||
func cmdSeed(cmd *cobra.Command, args []string) {
|
func cmdSeed(cmd *cobra.Command, args []string) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
if conf, err = initConf(); err != nil {
|
||||||
|
logger.Fatal().Err(err).Msg("failed to read config")
|
||||||
|
}
|
||||||
|
|
||||||
conf.UseAllowList = false
|
conf.UseAllowList = false
|
||||||
|
|
||||||
db, err = initDBPool(conf)
|
db, err = initDBPool(conf)
|
||||||
|
|
|
@ -7,6 +7,10 @@ import (
|
||||||
func cmdServ(cmd *cobra.Command, args []string) {
|
func cmdServ(cmd *cobra.Command, args []string) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
if conf, err = initConf(); err != nil {
|
||||||
|
logger.Fatal().Err(err).Msg("failed to read config")
|
||||||
|
}
|
||||||
|
|
||||||
db, err = initDBPool(conf)
|
db, err = initDBPool(conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatal().Err(err).Msg("failed to connect to database")
|
logger.Fatal().Err(err).Msg("failed to connect to database")
|
||||||
|
|
|
@ -40,6 +40,12 @@ func cmdNewMigration(cmd *cobra.Command, args []string) {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if conf, err = initConf(); err != nil {
|
||||||
|
logger.Fatal().Err(err).Msg("failed to read config")
|
||||||
|
}
|
||||||
|
|
||||||
name := args[0]
|
name := args[0]
|
||||||
|
|
||||||
m, err := migrate.FindMigrations(conf.MigrationsPath)
|
m, err := migrate.FindMigrations(conf.MigrationsPath)
|
||||||
|
@ -64,10 +70,16 @@ func cmdNewMigration(cmd *cobra.Command, args []string) {
|
||||||
fmt.Fprintln(os.Stderr, err)
|
fmt.Fprintln(os.Stderr, err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
logger.Info().Msgf("created migration '%s'\n", mpath)
|
logger.Info().Msgf("created migration '%s'", mpath)
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmdMigrate(cmd *cobra.Command, args []string) {
|
func cmdMigrate(cmd *cobra.Command, args []string) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if conf, err = initConf(); err != nil {
|
||||||
|
logger.Fatal().Err(err).Msg("failed to read config")
|
||||||
|
}
|
||||||
|
|
||||||
conn, err := initDB(conf)
|
conn, err := initDB(conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatal().Err(err).Msg("failed to connect to database")
|
logger.Fatal().Err(err).Msg("failed to connect to database")
|
||||||
|
@ -157,6 +169,12 @@ func cmdMigrate(cmd *cobra.Command, args []string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmdStatus(cmd *cobra.Command, args []string) {
|
func cmdStatus(cmd *cobra.Command, args []string) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if conf, err = initConf(); err != nil {
|
||||||
|
logger.Fatal().Err(err).Msg("failed to read config")
|
||||||
|
}
|
||||||
|
|
||||||
conn, err := initDB(conf)
|
conn, err := initDB(conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatal().Err(err).Msg("failed to connect to database")
|
logger.Fatal().Err(err).Msg("failed to connect to database")
|
||||||
|
|
|
@ -30,7 +30,7 @@ func initPreparedList() {
|
||||||
for k, v := range _allowList.list {
|
for k, v := range _allowList.list {
|
||||||
err := prepareStmt(k, v.gql, v.vars)
|
err := prepareStmt(k, v.gql, v.vars)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
logger.Fatal().Err(err).Send()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,7 +161,7 @@ func Do(log func(string, ...interface{}), additional ...dir) error {
|
||||||
func ReExec() {
|
func ReExec() {
|
||||||
err := syscall.Exec(binSelf, append([]string{binSelf}, os.Args[1:]...), os.Environ())
|
err := syscall.Exec(binSelf, append([]string{binSelf}, os.Args[1:]...), os.Environ())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("cannot restart: %v", err))
|
logger.Fatal().Err(err).Msg("cannot restart")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
11
serv/serv.go
11
serv/serv.go
|
@ -9,6 +9,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
rice "github.com/GeertJohan/go.rice"
|
||||||
"github.com/dosco/super-graph/psql"
|
"github.com/dosco/super-graph/psql"
|
||||||
"github.com/dosco/super-graph/qcode"
|
"github.com/dosco/super-graph/qcode"
|
||||||
)
|
)
|
||||||
|
@ -38,22 +39,22 @@ func initCompilers(c *config) (*qcode.Compiler, *psql.Compiler, error) {
|
||||||
return qc, pc, nil
|
return qc, pc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func initWatcher(path string) {
|
func initWatcher(cpath string) {
|
||||||
if conf.WatchAndReload == false {
|
if conf.WatchAndReload == false {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var d dir
|
var d dir
|
||||||
if len(path) == 0 || path == "./" {
|
if len(cpath) == 0 || cpath == "./" {
|
||||||
d = Dir("./config", ReExec)
|
d = Dir("./config", ReExec)
|
||||||
} else {
|
} else {
|
||||||
d = Dir(path, ReExec)
|
d = Dir(cpath, ReExec)
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
err := Do(logger.Printf, d)
|
err := Do(logger.Printf, d)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
logger.Fatal().Err(err).Send()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
@ -109,7 +110,7 @@ func routeHandler() http.Handler {
|
||||||
|
|
||||||
mux.Handle("/api/v1/graphql", withAuth(apiv1Http))
|
mux.Handle("/api/v1/graphql", withAuth(apiv1Http))
|
||||||
if conf.WebUI {
|
if conf.WebUI {
|
||||||
mux.Handle("/", http.FileServer(_escFS(false)))
|
mux.Handle("/", http.FileServer(rice.MustFindBox("../web/build").HTTPBox()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn := func(w http.ResponseWriter, r *http.Request) {
|
fn := func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
app_name: Test App
|
||||||
|
auth:
|
||||||
|
cookie: _app_session
|
||||||
|
header: X-User-ID
|
||||||
|
rails:
|
||||||
|
max_active: 12000
|
||||||
|
max_idle: 80
|
||||||
|
secret_key_base: 0a248500a64c01184edb4d7ad3a805488f8097ac761b76aaa6c17c01dcb7af03a2f18ba61b2868134b9c7b79a122bc0dadff4367414a2d173297bfea92be5566
|
||||||
|
version: 5.2
|
||||||
|
type: rails
|
||||||
|
auth_fail_block: never
|
||||||
|
database:
|
||||||
|
dbname: app_development
|
||||||
|
defaults:
|
||||||
|
blocklist:
|
||||||
|
- ar_internal_metadata
|
||||||
|
- schema_migrations
|
||||||
|
- secret
|
||||||
|
- password
|
||||||
|
- encrypted
|
||||||
|
- token
|
||||||
|
host: db
|
||||||
|
password: ""
|
||||||
|
port: 5432
|
||||||
|
schema: public
|
||||||
|
tables:
|
||||||
|
- name: users
|
||||||
|
- filter: none
|
||||||
|
name: customers
|
||||||
|
remotes:
|
||||||
|
- id: stripe_id
|
||||||
|
name: payments
|
||||||
|
pass_headers:
|
||||||
|
- cookie
|
||||||
|
path: data
|
||||||
|
set_headers:
|
||||||
|
- name: Host
|
||||||
|
value: 0.0.0.0
|
||||||
|
url: http://rails_app:3000/stripe/$id
|
||||||
|
- filter:
|
||||||
|
- '{ id: { eq: $user_id } }'
|
||||||
|
name: me
|
||||||
|
table: users
|
||||||
|
type: postgres
|
||||||
|
user: postgres
|
||||||
|
variables:
|
||||||
|
account_id: (select account_id from users where id = $user_id)
|
||||||
|
enable_tracing: true
|
||||||
|
env: development
|
||||||
|
host_port: 0.0.0.0:8080
|
||||||
|
log_level: debug
|
||||||
|
migrations_path: ./config/migrations
|
||||||
|
port: "8080"
|
||||||
|
reload_on_config_change: true
|
||||||
|
seed_file: seed.js
|
||||||
|
use_allow_list: false
|
||||||
|
web_ui: true
|
|
@ -0,0 +1,21 @@
|
||||||
|
-- Write your migrate up statements here
|
||||||
|
|
||||||
|
CREATE DATABASE {{ .app_name_slug }}_database
|
||||||
|
|
||||||
|
-- CREATE TABLE public.users (
|
||||||
|
-- id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||||
|
-- full_name text
|
||||||
|
-- email text UNIQUE NOT NULL CHECK (length(email) < 255),
|
||||||
|
-- encrypted_password text,
|
||||||
|
-- created_at timestamptz NOT NULL NOT NULL DEFAULT NOW(),
|
||||||
|
-- updated_at timestamptz NOT NULL NOT NULL DEFAULT NOW()
|
||||||
|
-- );
|
||||||
|
|
||||||
|
---- create above / drop below ----
|
||||||
|
|
||||||
|
-- Write your migrate down statements here. If this migration is irreversible
|
||||||
|
-- Then delete the separator line above.
|
||||||
|
|
||||||
|
-- DROP TABLE public.users
|
||||||
|
|
||||||
|
DROP DATABASE IF EXISTS {{ .app_name_slug }}_database
|
|
@ -0,0 +1,152 @@
|
||||||
|
app_name: "{{ .app_name }} Development"
|
||||||
|
host_port: 0.0.0.0:8080
|
||||||
|
web_ui: true
|
||||||
|
|
||||||
|
# debug, info, warn, error, fatal, panic
|
||||||
|
log_level: "debug"
|
||||||
|
|
||||||
|
# Disable this in development to get a list of
|
||||||
|
# queries used. When enabled super graph
|
||||||
|
# will only allow queries from this list
|
||||||
|
# List saved to ./config/allow.list
|
||||||
|
use_allow_list: false
|
||||||
|
|
||||||
|
# Throw a 401 on auth failure for queries that need auth
|
||||||
|
# valid values: always, per_query, never
|
||||||
|
auth_fail_block: never
|
||||||
|
|
||||||
|
# Latency tracing for database queries and remote joins
|
||||||
|
# the resulting latency information is returned with the
|
||||||
|
# response
|
||||||
|
enable_tracing: true
|
||||||
|
|
||||||
|
# Watch the config folder and reload Super Graph
|
||||||
|
# with the new configs when a change is detected
|
||||||
|
reload_on_config_change: true
|
||||||
|
|
||||||
|
# File that points to the database seeding script
|
||||||
|
# seed_file: seed.js
|
||||||
|
|
||||||
|
# Path pointing to where the migrations can be found
|
||||||
|
migrations_path: ./config/migrations
|
||||||
|
|
||||||
|
# Postgres related environment Variables
|
||||||
|
# SG_DATABASE_HOST
|
||||||
|
# SG_DATABASE_PORT
|
||||||
|
# SG_DATABASE_USER
|
||||||
|
# SG_DATABASE_PASSWORD
|
||||||
|
|
||||||
|
# Auth related environment Variables
|
||||||
|
# SG_AUTH_RAILS_COOKIE_SECRET_KEY_BASE
|
||||||
|
# SG_AUTH_RAILS_REDIS_URL
|
||||||
|
# SG_AUTH_RAILS_REDIS_PASSWORD
|
||||||
|
# SG_AUTH_JWT_PUBLIC_KEY_FILE
|
||||||
|
|
||||||
|
# inflections:
|
||||||
|
# person: people
|
||||||
|
# sheep: sheep
|
||||||
|
|
||||||
|
auth:
|
||||||
|
# Can be 'rails' or 'jwt'
|
||||||
|
type: rails
|
||||||
|
cookie: _app_session
|
||||||
|
|
||||||
|
# Comment this out if you want to disable setting
|
||||||
|
# the user_id via a header. Good for testing
|
||||||
|
header: X-User-ID
|
||||||
|
|
||||||
|
rails:
|
||||||
|
# Rails version this is used for reading the
|
||||||
|
# various cookies formats.
|
||||||
|
version: 5.2
|
||||||
|
|
||||||
|
# Found in 'Rails.application.config.secret_key_base'
|
||||||
|
secret_key_base: 0a248500a64c01184edb4d7ad3a805488f8097ac761b76aaa6c17c01dcb7af03a2f18ba61b2868134b9c7b79a122bc0dadff4367414a2d173297bfea92be5566
|
||||||
|
|
||||||
|
# Remote cookie store. (memcache or redis)
|
||||||
|
# url: redis://redis:6379
|
||||||
|
# password: ""
|
||||||
|
# max_idle: 80
|
||||||
|
# max_active: 12000
|
||||||
|
|
||||||
|
# In most cases you don't need these
|
||||||
|
# salt: "encrypted cookie"
|
||||||
|
# sign_salt: "signed encrypted cookie"
|
||||||
|
# auth_salt: "authenticated encrypted cookie"
|
||||||
|
|
||||||
|
# jwt:
|
||||||
|
# provider: auth0
|
||||||
|
# secret: abc335bfcfdb04e50db5bb0a4d67ab9
|
||||||
|
# public_key_file: /secrets/public_key.pem
|
||||||
|
# public_key_type: ecdsa #rsa
|
||||||
|
|
||||||
|
database:
|
||||||
|
type: postgres
|
||||||
|
host: db
|
||||||
|
port: 5432
|
||||||
|
dbname: {{ .app_name_slug }}_database
|
||||||
|
user: postgres
|
||||||
|
password: ''
|
||||||
|
|
||||||
|
#schema: "public"
|
||||||
|
#pool_size: 10
|
||||||
|
#max_retries: 0
|
||||||
|
#log_level: "debug"
|
||||||
|
|
||||||
|
# Define variables here that you want to use in filters
|
||||||
|
# sub-queries must be wrapped in ()
|
||||||
|
variables:
|
||||||
|
account_id: "(select account_id from users where id = $user_id)"
|
||||||
|
|
||||||
|
# Define defaults to for the field key and values below
|
||||||
|
defaults:
|
||||||
|
# filter: ["{ user_id: { eq: $user_id } }"]
|
||||||
|
|
||||||
|
# Field and table names that you wish to block
|
||||||
|
blocklist:
|
||||||
|
- ar_internal_metadata
|
||||||
|
- schema_migrations
|
||||||
|
- secret
|
||||||
|
- password
|
||||||
|
- encrypted
|
||||||
|
- token
|
||||||
|
|
||||||
|
tables:
|
||||||
|
- name: users
|
||||||
|
# This filter will overwrite defaults.filter
|
||||||
|
# filter: ["{ id: { eq: $user_id } }"]
|
||||||
|
|
||||||
|
# - name: products
|
||||||
|
# # Multiple filters are AND'd together
|
||||||
|
# filter: [
|
||||||
|
# "{ price: { gt: 0 } }",
|
||||||
|
# "{ price: { lt: 8 } }"
|
||||||
|
# ]
|
||||||
|
|
||||||
|
- name: customers
|
||||||
|
# No filter is used for this field not
|
||||||
|
# even defaults.filter
|
||||||
|
filter: none
|
||||||
|
|
||||||
|
remotes:
|
||||||
|
- name: payments
|
||||||
|
id: stripe_id
|
||||||
|
url: http://rails_app:3000/stripe/$id
|
||||||
|
path: data
|
||||||
|
# debug: true
|
||||||
|
pass_headers:
|
||||||
|
- cookie
|
||||||
|
set_headers:
|
||||||
|
- name: Host
|
||||||
|
value: 0.0.0.0
|
||||||
|
# - name: Authorization
|
||||||
|
# value: Bearer <stripe_api_key>
|
||||||
|
|
||||||
|
- # You can create new fields that have a
|
||||||
|
# real db table backing them
|
||||||
|
name: me
|
||||||
|
table: users
|
||||||
|
filter: ["{ id: { eq: $user_id } }"]
|
||||||
|
|
||||||
|
# - name: posts
|
||||||
|
# filter: ["{ account_id: { _eq: $account_id } }"]
|
|
@ -0,0 +1,17 @@
|
||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
db:
|
||||||
|
image: postgres
|
||||||
|
ports:
|
||||||
|
- "5432:5432"
|
||||||
|
|
||||||
|
{{ .app_name_slug }}_api:
|
||||||
|
image: dosco/super-graph:latest
|
||||||
|
environment:
|
||||||
|
GO_ENV: "development"
|
||||||
|
volumes:
|
||||||
|
- ./config:/config
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
|
depends_on:
|
||||||
|
- db
|
|
@ -0,0 +1,144 @@
|
||||||
|
app_name: "{{ .app_name }} Production"
|
||||||
|
host_port: 0.0.0.0:8080
|
||||||
|
web_ui: false
|
||||||
|
|
||||||
|
# debug, info, warn, error, fatal, panic, disable
|
||||||
|
log_level: "info"
|
||||||
|
|
||||||
|
# Disable this in development to get a list of
|
||||||
|
# queries used. When enabled super graph
|
||||||
|
# will only allow queries from this list
|
||||||
|
# List saved to ./config/allow.list
|
||||||
|
use_allow_list: true
|
||||||
|
|
||||||
|
# Throw a 401 on auth failure for queries that need auth
|
||||||
|
# valid values: always, per_query, never
|
||||||
|
auth_fail_block: always
|
||||||
|
|
||||||
|
# Latency tracing for database queries and remote joins
|
||||||
|
# the resulting latency information is returned with the
|
||||||
|
# response
|
||||||
|
enable_tracing: true
|
||||||
|
|
||||||
|
# File that points to the database seeding script
|
||||||
|
# seed_file: seed.js
|
||||||
|
|
||||||
|
# Path pointing to where the migrations can be found
|
||||||
|
# migrations_path: migrations
|
||||||
|
|
||||||
|
# Postgres related environment Variables
|
||||||
|
# SG_DATABASE_HOST
|
||||||
|
# SG_DATABASE_PORT
|
||||||
|
# SG_DATABASE_USER
|
||||||
|
# SG_DATABASE_PASSWORD
|
||||||
|
|
||||||
|
# Auth related environment Variables
|
||||||
|
# SG_AUTH_RAILS_COOKIE_SECRET_KEY_BASE
|
||||||
|
# SG_AUTH_RAILS_REDIS_URL
|
||||||
|
# SG_AUTH_RAILS_REDIS_PASSWORD
|
||||||
|
# SG_AUTH_JWT_PUBLIC_KEY_FILE
|
||||||
|
|
||||||
|
# inflections:
|
||||||
|
# person: people
|
||||||
|
# sheep: sheep
|
||||||
|
|
||||||
|
auth:
|
||||||
|
# Can be 'rails' or 'jwt'
|
||||||
|
type: rails
|
||||||
|
cookie: _app_session
|
||||||
|
|
||||||
|
# Comment this out if you want to disable setting
|
||||||
|
# the user_id via a header. Good for testing
|
||||||
|
header: X-User-ID
|
||||||
|
|
||||||
|
rails:
|
||||||
|
# Rails version this is used for reading the
|
||||||
|
# various cookies formats.
|
||||||
|
version: 5.2
|
||||||
|
|
||||||
|
# Found in 'Rails.application.config.secret_key_base'
|
||||||
|
secret_key_base: 0a248500a64c01184edb4d7ad3a805488f8097ac761b76aaa6c17c01dcb7af03a2f18ba61b2868134b9c7b79a122bc0dadff4367414a2d173297bfea92be5566
|
||||||
|
|
||||||
|
# Remote cookie store. (memcache or redis)
|
||||||
|
# url: redis://127.0.0.1:6379
|
||||||
|
# password: test
|
||||||
|
# max_idle: 80,
|
||||||
|
# max_active: 12000,
|
||||||
|
|
||||||
|
# In most cases you don't need these
|
||||||
|
# salt: "encrypted cookie"
|
||||||
|
# sign_salt: "signed encrypted cookie"
|
||||||
|
# auth_salt: "authenticated encrypted cookie"
|
||||||
|
|
||||||
|
# jwt:
|
||||||
|
# provider: auth0
|
||||||
|
# secret: abc335bfcfdb04e50db5bb0a4d67ab9
|
||||||
|
# public_key_file: /secrets/public_key.pem
|
||||||
|
# public_key_type: ecdsa #rsa
|
||||||
|
|
||||||
|
database:
|
||||||
|
type: postgres
|
||||||
|
host: db
|
||||||
|
port: 5432
|
||||||
|
dbname: {{ .app_name_slug }}_database
|
||||||
|
user: postgres
|
||||||
|
password: ''
|
||||||
|
#pool_size: 10
|
||||||
|
#max_retries: 0
|
||||||
|
#log_level: "debug"
|
||||||
|
|
||||||
|
# Define variables here that you want to use in filters
|
||||||
|
# sub-queries must be wrapped in ()
|
||||||
|
variables:
|
||||||
|
account_id: "(select account_id from users where id = $user_id)"
|
||||||
|
|
||||||
|
# Define defaults to for the field key and values below
|
||||||
|
defaults:
|
||||||
|
filter: ["{ user_id: { eq: $user_id } }"]
|
||||||
|
|
||||||
|
# Field and table names that you wish to block
|
||||||
|
blocklist:
|
||||||
|
- ar_internal_metadata
|
||||||
|
- schema_migrations
|
||||||
|
- secret
|
||||||
|
- password
|
||||||
|
- encrypted
|
||||||
|
- token
|
||||||
|
|
||||||
|
tables:
|
||||||
|
- name: users
|
||||||
|
# This filter will overwrite defaults.filter
|
||||||
|
filter: ["{ id: { eq: $user_id } }"]
|
||||||
|
|
||||||
|
- name: products
|
||||||
|
# Multiple filters are AND'd together
|
||||||
|
filter: [
|
||||||
|
"{ price: { gt: 0 } }",
|
||||||
|
"{ price: { lt: 8 } }"
|
||||||
|
]
|
||||||
|
|
||||||
|
- name: customers
|
||||||
|
# No filter is used for this field not
|
||||||
|
# even defaults.filter
|
||||||
|
filter: none
|
||||||
|
|
||||||
|
# remotes:
|
||||||
|
# - name: payments
|
||||||
|
# id: stripe_id
|
||||||
|
# url: http://rails_app:3000/stripe/$id
|
||||||
|
# path: data
|
||||||
|
# # pass_headers:
|
||||||
|
# # - cookie
|
||||||
|
# # - host
|
||||||
|
# set_headers:
|
||||||
|
# - name: Authorization
|
||||||
|
# value: Bearer <stripe_api_key>
|
||||||
|
|
||||||
|
- # You can create new fields that have a
|
||||||
|
# real db table backing them
|
||||||
|
name: me
|
||||||
|
table: users
|
||||||
|
filter: ["{ id: { eq: $user_id } }"]
|
||||||
|
|
||||||
|
# - name: posts
|
||||||
|
# filter: ["{ account_id: { _eq: $account_id } }"]
|
|
@ -0,0 +1,23 @@
|
||||||
|
// Example script to seed database
|
||||||
|
|
||||||
|
var users = [];
|
||||||
|
|
||||||
|
for (i = 0; i < 10; i++) {
|
||||||
|
var pwd = fake.password()
|
||||||
|
var data = {
|
||||||
|
first_name: fake.first_name(),
|
||||||
|
last_name: fake.last_name(),
|
||||||
|
email: fake.email(),
|
||||||
|
password: pwd,
|
||||||
|
password_confirmation: pwd
|
||||||
|
}
|
||||||
|
|
||||||
|
var res = graphql(" \
|
||||||
|
mutation { \
|
||||||
|
user(insert: $data) { \
|
||||||
|
id \
|
||||||
|
} \
|
||||||
|
}", { data: data })
|
||||||
|
|
||||||
|
users.push(res.user)
|
||||||
|
}
|
Loading…
Reference in New Issue