Add initialization command to setup new apps
This commit is contained in:
parent
5e86b445c5
commit
ecec2968e9
3
.gitignore
vendored
3
.gitignore
vendored
@ -26,4 +26,5 @@
|
||||
.vscode
|
||||
main
|
||||
.DS_Store
|
||||
.swp
|
||||
.swp
|
||||
main
|
||||
|
13
Dockerfile
13
Dockerfile
@ -12,7 +12,9 @@ RUN apk update && \
|
||||
apk add --no-cache upx=3.95-r2
|
||||
|
||||
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
|
||||
COPY . /app
|
||||
@ -22,10 +24,13 @@ COPY --from=react-build /web/build/ ./web/build/
|
||||
|
||||
ENV GO111MODULE=on
|
||||
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 ./... && \
|
||||
CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o super-graph && \
|
||||
upx --ultra-brute -qq super-graph && \
|
||||
upx -t super-graph
|
||||
CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o super-graph
|
||||
|
||||
# stage: 3
|
||||
FROM alpine:latest
|
||||
|
@ -80,7 +80,7 @@ database:
|
||||
type: postgres
|
||||
host: db
|
||||
port: 5432
|
||||
dbname: app_development
|
||||
dbname: {{app_name_slug}}_development
|
||||
user: postgres
|
||||
password: ''
|
||||
#pool_size: 10
|
||||
|
@ -11,16 +11,16 @@ services:
|
||||
# ports:
|
||||
# - "6379:6379"
|
||||
|
||||
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'"
|
||||
volumes:
|
||||
- ./rails-app:/app
|
||||
- /app/tmp
|
||||
ports:
|
||||
- "3000:3000"
|
||||
depends_on:
|
||||
- db
|
||||
# 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'"
|
||||
# volumes:
|
||||
# - ./rails-app:/app
|
||||
# - /app/tmp
|
||||
# ports:
|
||||
# - "3000:3000"
|
||||
# depends_on:
|
||||
# - db
|
||||
|
||||
super_graph:
|
||||
build:
|
||||
@ -34,9 +34,9 @@ services:
|
||||
volumes:
|
||||
- .:/app
|
||||
working_dir: /app
|
||||
command: fresh -c fresh.conf
|
||||
command: wu -pattern="*.go" go run main.go serv
|
||||
depends_on:
|
||||
- db
|
||||
- rails_app
|
||||
#- rails_app
|
||||
|
||||
# - 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
|
||||
|
||||
require (
|
||||
github.com/GeertJohan/go.rice v1.0.0
|
||||
github.com/Masterminds/semver v1.4.2
|
||||
github.com/OneOfOne/xxhash v1.2.5 // indirect
|
||||
github.com/adjust/gorails v0.0.0-20171013043634-2786ed0c03d3
|
||||
@ -35,6 +36,9 @@ require (
|
||||
github.com/valyala/fasttemplate v1.0.1
|
||||
github.com/vaughan0/go-ini v0.0.0-20130923145212-a98ad7ee00ec
|
||||
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
|
||||
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/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
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/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
||||
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/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/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/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
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/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/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.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
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/tern v1.8.2 h1:+d9eK83fRS0dbf6nt+2tjILYF4FKG1O5xTFB8Lzc66U=
|
||||
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/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
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/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/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.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
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-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-20190813141303-74dc4d7220e7 h1:fHDIZ2oxGnUZRN6WgWFCbYBjH9uqVPRCUVUDhs0wnbA=
|
||||
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-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
|
152
hello/config/dev.yml
Normal file
152
hello/config/dev.yml
Normal file
@ -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 } }"]
|
21
hello/config/migrations/100_init.sql
Normal file
21
hello/config/migrations/100_init.sql
Normal file
@ -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
|
144
hello/config/prod.yml
Normal file
144
hello/config/prod.yml
Normal file
@ -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 } }"]
|
17
hello/docker-compose.yml
Normal file
17
hello/docker-compose.yml
Normal file
@ -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
|
17
hello/seed.js
Normal file
17
hello/seed.js
Normal file
@ -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
|
||||
}
|
||||
|
||||
func (c *compilerContext) renderJoinTable(sel *qcode.Select) {
|
||||
func (c *compilerContext) renderJoinTable(sel *qcode.Select) error {
|
||||
parent := &c.s[sel.ParentID]
|
||||
|
||||
rel, err := c.schema.GetRel(sel.Table, parent.Table)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return err
|
||||
}
|
||||
|
||||
if rel.Type != RelOneToManyThrough {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
pt, err := c.schema.GetTable(parent.Table)
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
//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(`) = (`)
|
||||
colWithTableID(c.w, pt.Name, parent.ID, rel.Col1)
|
||||
c.w.WriteString(`))`)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *compilerContext) renderColumns(sel *qcode.Select) {
|
||||
@ -537,10 +539,15 @@ func (c *compilerContext) renderBaseSelect(sel *qcode.Select, ti *DBTableInfo,
|
||||
}
|
||||
|
||||
if !isRoot {
|
||||
c.renderJoinTable(sel)
|
||||
if err := c.renderJoinTable(sel); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.w.WriteString(` WHERE (`)
|
||||
c.renderRelationship(sel)
|
||||
|
||||
if err := c.renderRelationship(sel); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if isFil {
|
||||
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]
|
||||
|
||||
rel, err := c.schema.GetRel(sel.Table, parent.Table)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return err
|
||||
}
|
||||
|
||||
switch rel.Type {
|
||||
@ -646,6 +653,8 @@ func (c *compilerContext) renderRelationship(sel *qcode.Select) {
|
||||
colWithTable(c.w, rel.Through, rel.Col2)
|
||||
c.w.WriteString(`))`)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *compilerContext) renderWhere(sel *qcode.Select, ti *DBTableInfo) error {
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
@ -31,20 +32,20 @@ type allowList struct {
|
||||
active bool
|
||||
}
|
||||
|
||||
func initAllowList(path string) {
|
||||
func initAllowList(cpath string) {
|
||||
_allowList = allowList{
|
||||
list: make(map[string]*allowItem),
|
||||
saveChan: make(chan *allowItem),
|
||||
active: true,
|
||||
}
|
||||
|
||||
if len(path) != 0 {
|
||||
fp := fmt.Sprintf("%s/allow.list", path)
|
||||
if len(cpath) != 0 {
|
||||
fp := path.Join(cpath, "allow.list")
|
||||
|
||||
if _, err := os.Stat(fp); err == nil {
|
||||
_allowList.filepath = fp
|
||||
} 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 {
|
||||
_allowList.filepath = fp
|
||||
} 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 {
|
||||
_allowList.filepath = fp
|
||||
} else if !os.IsNotExist(err) {
|
||||
panic(err)
|
||||
logger.Fatal().Err(err).Send()
|
||||
}
|
||||
}
|
||||
|
||||
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() {
|
||||
for v := range _allowList.saveChan {
|
||||
@ -182,7 +193,7 @@ func (al *allowList) save(item *allowItem) {
|
||||
|
||||
f, err := os.Create(al.filepath)
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ func jwtHandler(next http.HandlerFunc) http.HandlerFunc {
|
||||
case len(publicKeyFile) != 0:
|
||||
kd, err := ioutil.ReadFile(publicKeyFile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
logger.Fatal().Err(err).Send()
|
||||
}
|
||||
|
||||
switch conf.Auth.JWT.PubKeyType {
|
||||
@ -51,7 +51,7 @@ func jwtHandler(next http.HandlerFunc) http.HandlerFunc {
|
||||
}
|
||||
|
||||
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) {
|
||||
c, err := redis.DialURL(conf.Auth.Rails.URL)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
logger.Fatal().Err(err).Send()
|
||||
}
|
||||
|
||||
pwd := conf.Auth.Rails.Password
|
||||
if len(pwd) != 0 {
|
||||
if _, err := c.Do("AUTH", pwd); err != nil {
|
||||
panic(err)
|
||||
logger.Fatal().Err(err).Send()
|
||||
}
|
||||
}
|
||||
return c, err
|
||||
|
17
serv/cmd.go
17
serv/cmd.go
@ -17,8 +17,6 @@ import (
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
//go:generate esc -o static.go -ignore \\.DS_Store -prefix ../web/build -private -pkg serv ../web/build
|
||||
|
||||
const (
|
||||
serverName = "Super Graph"
|
||||
|
||||
@ -42,11 +40,10 @@ var (
|
||||
migrateCmd *cobra.Command
|
||||
statusCmd *cobra.Command
|
||||
newMigrationCmd *cobra.Command
|
||||
initCmd *cobra.Command
|
||||
)
|
||||
|
||||
func Init() {
|
||||
var err error
|
||||
|
||||
rootCmd = &cobra.Command{
|
||||
Use: "super-graph",
|
||||
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,
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
rootCmd.Flags().StringVar(&confPath,
|
||||
@ -118,16 +122,13 @@ e.g. tern migrate -d last
|
||||
//cmdMigrate.Flags().StringVarP(&cliOptions.destinationVersion,
|
||||
// "destination", "d", "last", "destination migration version")
|
||||
|
||||
rootCmd.AddCommand(initCmd)
|
||||
rootCmd.AddCommand(servCmd)
|
||||
rootCmd.AddCommand(seedCmd)
|
||||
rootCmd.AddCommand(migrateCmd)
|
||||
rootCmd.AddCommand(statusCmd)
|
||||
rootCmd.AddCommand(newMigrationCmd)
|
||||
|
||||
if conf, err = initConf(); err != nil {
|
||||
logger.Fatal().Err(err).Msg("failed to read config")
|
||||
}
|
||||
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
logger.Fatal().Err(err).Send()
|
||||
}
|
||||
|
132
serv/cmd_init.go
Normal file
132
serv/cmd_init.go
Normal file
@ -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) {
|
||||
var err error
|
||||
|
||||
if conf, err = initConf(); err != nil {
|
||||
logger.Fatal().Err(err).Msg("failed to read config")
|
||||
}
|
||||
|
||||
conf.UseAllowList = false
|
||||
|
||||
db, err = initDBPool(conf)
|
||||
|
@ -7,6 +7,10 @@ import (
|
||||
func cmdServ(cmd *cobra.Command, args []string) {
|
||||
var err error
|
||||
|
||||
if conf, err = initConf(); err != nil {
|
||||
logger.Fatal().Err(err).Msg("failed to read config")
|
||||
}
|
||||
|
||||
db, err = initDBPool(conf)
|
||||
if err != nil {
|
||||
logger.Fatal().Err(err).Msg("failed to connect to database")
|
||||
|
@ -40,6 +40,12 @@ func cmdNewMigration(cmd *cobra.Command, args []string) {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
if conf, err = initConf(); err != nil {
|
||||
logger.Fatal().Err(err).Msg("failed to read config")
|
||||
}
|
||||
|
||||
name := args[0]
|
||||
|
||||
m, err := migrate.FindMigrations(conf.MigrationsPath)
|
||||
@ -64,10 +70,16 @@ func cmdNewMigration(cmd *cobra.Command, args []string) {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
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) {
|
||||
var err error
|
||||
|
||||
if conf, err = initConf(); err != nil {
|
||||
logger.Fatal().Err(err).Msg("failed to read config")
|
||||
}
|
||||
|
||||
conn, err := initDB(conf)
|
||||
if err != nil {
|
||||
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) {
|
||||
var err error
|
||||
|
||||
if conf, err = initConf(); err != nil {
|
||||
logger.Fatal().Err(err).Msg("failed to read config")
|
||||
}
|
||||
|
||||
conn, err := initDB(conf)
|
||||
if err != nil {
|
||||
logger.Fatal().Err(err).Msg("failed to connect to database")
|
||||
|
@ -30,7 +30,7 @@ func initPreparedList() {
|
||||
for k, v := range _allowList.list {
|
||||
err := prepareStmt(k, v.gql, v.vars)
|
||||
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() {
|
||||
err := syscall.Exec(binSelf, append([]string{binSelf}, os.Args[1:]...), os.Environ())
|
||||
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"
|
||||
"time"
|
||||
|
||||
rice "github.com/GeertJohan/go.rice"
|
||||
"github.com/dosco/super-graph/psql"
|
||||
"github.com/dosco/super-graph/qcode"
|
||||
)
|
||||
@ -38,22 +39,22 @@ func initCompilers(c *config) (*qcode.Compiler, *psql.Compiler, error) {
|
||||
return qc, pc, nil
|
||||
}
|
||||
|
||||
func initWatcher(path string) {
|
||||
func initWatcher(cpath string) {
|
||||
if conf.WatchAndReload == false {
|
||||
return
|
||||
}
|
||||
|
||||
var d dir
|
||||
if len(path) == 0 || path == "./" {
|
||||
if len(cpath) == 0 || cpath == "./" {
|
||||
d = Dir("./config", ReExec)
|
||||
} else {
|
||||
d = Dir(path, ReExec)
|
||||
d = Dir(cpath, ReExec)
|
||||
}
|
||||
|
||||
go func() {
|
||||
err := Do(logger.Printf, d)
|
||||
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))
|
||||
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) {
|
||||
|
57
test.yml
Normal file
57
test.yml
Normal file
@ -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
|
21
tmpl/100_init.sql
Normal file
21
tmpl/100_init.sql
Normal file
@ -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
|
152
tmpl/dev.yml
Normal file
152
tmpl/dev.yml
Normal file
@ -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 } }"]
|
17
tmpl/docker-compose.yml
Normal file
17
tmpl/docker-compose.yml
Normal file
@ -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
|
144
tmpl/prod.yml
Normal file
144
tmpl/prod.yml
Normal file
@ -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 } }"]
|
23
tmpl/seed.js
Normal file
23
tmpl/seed.js
Normal file
@ -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
Block a user