├── README.md ├── elixir ├── README.md └── phoenix_graphql │ ├── .gitignore │ ├── README.md │ ├── config │ ├── config.exs │ ├── dev.exs │ ├── prod.exs │ └── test.exs │ ├── lib │ ├── phoenix_graphql.ex │ └── phoenix_graphql │ │ ├── endpoint.ex │ │ └── repo.ex │ ├── mix.exs │ ├── mix.lock │ ├── priv │ ├── gettext │ │ ├── en │ │ │ └── LC_MESSAGES │ │ │ │ └── errors.po │ │ └── errors.pot │ ├── repo │ │ ├── migrations │ │ │ ├── 20160526044431_create_user.exs │ │ │ ├── 20160526044445_create_post.exs │ │ │ └── 20160526044513_create_comment.exs │ │ └── seeds.exs │ └── static │ │ ├── css │ │ └── app.css │ │ ├── favicon.ico │ │ ├── images │ │ └── phoenix.png │ │ ├── js │ │ ├── app.js │ │ └── phoenix.js │ │ └── robots.txt │ ├── test │ ├── models │ │ ├── comment_test.exs │ │ ├── post_test.exs │ │ └── user_test.exs │ ├── support │ │ ├── channel_case.ex │ │ ├── conn_case.ex │ │ └── model_case.ex │ ├── test_helper.exs │ └── views │ │ └── error_view_test.exs │ └── web │ ├── api │ ├── resolver.ex │ ├── schema.ex │ └── types │ │ ├── comment.ex │ │ ├── post.ex │ │ └── user.ex │ ├── channels │ └── user_socket.ex │ ├── context.ex │ ├── controllers │ └── page_controller.ex │ ├── gettext.ex │ ├── models │ ├── comment.ex │ ├── post.ex │ └── user.ex │ ├── router.ex │ ├── templates │ ├── layout │ │ └── app.html.eex │ └── page │ │ └── graphiql.html.eex │ ├── views │ ├── error_helpers.ex │ ├── error_view.ex │ ├── layout_view.ex │ └── page_view.ex │ └── web.ex ├── javascript ├── README.md ├── express_graphql │ ├── .babelrc │ ├── .gitignore │ ├── README.md │ ├── api │ │ ├── schema.js │ │ └── types │ │ │ ├── commentType.js │ │ │ ├── postType.js │ │ │ └── userType.js │ ├── app.js │ ├── bin │ │ └── www │ ├── config │ │ └── config.json │ ├── migrations │ │ ├── 20160521095312-create-user.js │ │ ├── 20160521095507-create-post.js │ │ └── 20160521100324-create-comment.js │ ├── models │ │ ├── comment.js │ │ ├── index.js │ │ ├── post.js │ │ └── user.js │ ├── package.json │ └── seeders │ │ ├── 20160521103212-user.js │ │ ├── 20160521111530-post.js │ │ └── 20160521111557-comment.js ├── koa_graphql │ ├── .babelrc │ ├── .editorconfig │ ├── .gitignore │ ├── .jshintrc │ ├── README.md │ ├── api │ │ ├── schema.js │ │ └── types │ │ │ ├── commentType.js │ │ │ ├── postType.js │ │ │ └── userType.js │ ├── app.js │ ├── bookshelf.js │ ├── migrations │ │ ├── 20160521155821_users.js │ │ ├── 20160521155829_posts.js │ │ └── 20160521155833_comments.js │ ├── models │ │ ├── comment.js │ │ ├── post.js │ │ └── user.js │ ├── package.json │ └── seeds │ │ ├── comments.js │ │ ├── posts.js │ │ └── users.js └── meteor_graphql │ ├── .gitignore │ ├── .meteor │ ├── .finished-upgraders │ ├── .gitignore │ ├── .id │ ├── packages │ ├── platforms │ ├── release │ └── versions │ ├── README.md │ ├── client │ └── main.html │ ├── imports │ ├── api │ │ └── schema.js │ └── collections │ │ ├── comments.js │ │ ├── posts.js │ │ ├── schemas.js │ │ └── users.js │ ├── package.json │ └── server │ ├── fixtures │ └── users.js │ ├── main.js │ ├── publications │ └── posts.js │ └── seeds.js ├── php ├── README.md └── laravel_graphql │ ├── .gitattributes │ ├── .gitignore │ ├── app │ ├── Comment.php │ ├── Console │ │ ├── Commands │ │ │ └── Inspire.php │ │ └── Kernel.php │ ├── Events │ │ └── Event.php │ ├── Exceptions │ │ └── Handler.php │ ├── GraphQL │ │ ├── Query │ │ │ ├── CommentsQuery.php │ │ │ ├── PostQuery.php │ │ │ ├── PostsQuery.php │ │ │ ├── UserQuery.php │ │ │ └── UsersQuery.php │ │ ├── Type │ │ │ ├── CommentType.php │ │ │ ├── PostType.php │ │ │ └── UserType.php │ │ └── mutation │ │ │ └── UpdateUserPasswordMutation.php │ ├── Http │ │ ├── Controllers │ │ │ ├── Auth │ │ │ │ ├── AuthController.php │ │ │ │ └── PasswordController.php │ │ │ ├── Controller.php │ │ │ └── PagesController.php │ │ ├── Kernel.php │ │ ├── Middleware │ │ │ ├── Authenticate.php │ │ │ ├── EncryptCookies.php │ │ │ ├── RedirectIfAuthenticated.php │ │ │ └── VerifyCsrfToken.php │ │ ├── Requests │ │ │ └── Request.php │ │ └── routes.php │ ├── Jobs │ │ └── Job.php │ ├── Listeners │ │ └── .gitkeep │ ├── Policies │ │ └── .gitkeep │ ├── Post.php │ ├── Providers │ │ ├── AppServiceProvider.php │ │ ├── AuthServiceProvider.php │ │ ├── EventServiceProvider.php │ │ └── RouteServiceProvider.php │ └── User.php │ ├── artisan │ ├── bootstrap │ ├── app.php │ ├── autoload.php │ └── cache │ │ └── .gitignore │ ├── composer.json │ ├── composer.lock │ ├── config │ ├── app.php │ ├── auth.php │ ├── broadcasting.php │ ├── cache.php │ ├── compile.php │ ├── database.php │ ├── filesystems.php │ ├── graphql.php │ ├── jwt.php │ ├── mail.php │ ├── queue.php │ ├── services.php │ ├── session.php │ └── view.php │ ├── database │ ├── .gitignore │ ├── factories │ │ └── ModelFactory.php │ ├── migrations │ │ ├── .gitkeep │ │ ├── 2014_10_12_000000_create_users_table.php │ │ ├── 2014_10_12_100000_create_password_resets_table.php │ │ ├── 2016_05_31_071858_create_posts_table.php │ │ └── 2016_05_31_071904_create_comments_table.php │ └── seeds │ │ ├── .gitkeep │ │ ├── CommentsTableSeeder.php │ │ ├── DatabaseSeeder.php │ │ ├── PostsTableSeeder.php │ │ └── UsersTableSeeder.php │ ├── gulpfile.js │ ├── package.json │ ├── phpunit.xml │ ├── public │ ├── .htaccess │ ├── favicon.ico │ ├── index.php │ ├── robots.txt │ └── web.config │ ├── readme.md │ ├── resources │ ├── assets │ │ └── sass │ │ │ └── app.scss │ ├── lang │ │ └── en │ │ │ ├── auth.php │ │ │ ├── pagination.php │ │ │ ├── passwords.php │ │ │ └── validation.php │ └── views │ │ ├── errors │ │ └── 503.blade.php │ │ ├── pages │ │ └── welcome.blade.php │ │ └── vendor │ │ └── .gitkeep │ ├── server.php │ └── storage │ ├── app │ ├── .gitignore │ └── public │ │ └── .gitignore │ ├── framework │ ├── .gitignore │ ├── cache │ │ └── .gitignore │ ├── sessions │ │ └── .gitignore │ └── views │ │ └── .gitignore │ └── logs │ └── .gitignore ├── python ├── README.md ├── django_graphql │ ├── README.md │ ├── blog │ │ ├── __init__.py │ │ ├── __init__.pyc │ │ ├── admin.py │ │ ├── admin.pyc │ │ ├── apps.py │ │ ├── fixtures │ │ │ └── seed.json │ │ ├── migrations │ │ │ ├── 0001_initial.py │ │ │ ├── 0001_initial.pyc │ │ │ ├── __init__.py │ │ │ └── __init__.pyc │ │ ├── models.py │ │ ├── models.pyc │ │ ├── schema.pyc │ │ ├── tests.py │ │ ├── urls.py │ │ ├── urls.pyc │ │ ├── views.py │ │ └── views.pyc │ ├── db.sqlite3 │ ├── django_graphql │ │ ├── __init__.py │ │ ├── __init__.pyc │ │ ├── schema.py │ │ ├── schema.pyc │ │ ├── settings.py │ │ ├── settings.pyc │ │ ├── urls.py │ │ ├── urls.pyc │ │ ├── wsgi.py │ │ └── wsgi.pyc │ ├── manage.py │ └── requirements.txt └── flask_graphql │ ├── README.md │ ├── __init__.py │ ├── app.py │ ├── app.pyc │ ├── config.py │ ├── config.pyc │ ├── manage.py │ ├── migrations │ ├── README │ ├── alembic.ini │ ├── env.py │ ├── env.pyc │ ├── script.py.mako │ └── versions │ │ ├── 11261ac968e5_.py │ │ └── 11261ac968e5_.pyc │ ├── models.py │ ├── models.pyc │ ├── requirements.txt │ ├── schema.py │ ├── schema.pyc │ └── seed.py ├── ruby ├── README.md ├── cuba_grapgql │ ├── .bundle │ │ └── config │ ├── .gitignore │ ├── Gemfile │ ├── Gemfile.lock │ ├── README.md │ ├── api │ │ ├── database.rb │ │ ├── schema.rb │ │ └── types │ │ │ ├── comment_type.rb │ │ │ ├── post_type.rb │ │ │ └── user_type.rb │ ├── config.ru │ ├── cuba_grapgql.rb │ ├── middlewares │ │ └── pass_auth_token.rb │ └── views │ │ ├── graphiql.erb │ │ └── layout.erb ├── rails_graphql │ ├── .gitignore │ ├── Gemfile │ ├── Gemfile.lock │ ├── README.md │ ├── Rakefile │ ├── app │ │ ├── api │ │ │ ├── node_identification.rb │ │ │ ├── schema.rb │ │ │ └── types │ │ │ │ ├── comment_type.rb │ │ │ │ ├── post_type.rb │ │ │ │ └── user_type.rb │ │ ├── controllers │ │ │ ├── application_controller.rb │ │ │ ├── concerns │ │ │ │ └── .keep │ │ │ └── graphql_controller.rb │ │ ├── models │ │ │ ├── application_record.rb │ │ │ ├── comment.rb │ │ │ ├── concerns │ │ │ │ └── .keep │ │ │ ├── post.rb │ │ │ └── user.rb │ │ └── views │ │ │ └── graphiql │ │ │ └── rails │ │ │ └── editors │ │ │ └── show.html.erb │ ├── bin │ │ ├── bundle │ │ ├── rails │ │ ├── rake │ │ ├── setup │ │ ├── spring │ │ └── update │ ├── config.ru │ ├── config │ │ ├── application.rb │ │ ├── boot.rb │ │ ├── database.yml │ │ ├── environment.rb │ │ ├── environments │ │ │ ├── development.rb │ │ │ ├── production.rb │ │ │ └── test.rb │ │ ├── initializers │ │ │ ├── active_record_belongs_to_required_by_default.rb │ │ │ ├── application_controller_renderer.rb │ │ │ ├── backtrace_silencers.rb │ │ │ ├── callback_terminator.rb │ │ │ ├── cookies_serializer.rb │ │ │ ├── filter_parameter_logging.rb │ │ │ ├── graphiql.rb │ │ │ ├── inflections.rb │ │ │ ├── mime_types.rb │ │ │ ├── per_form_csrf_tokens.rb │ │ │ ├── request_forgery_protection.rb │ │ │ ├── session_store.rb │ │ │ ├── ssl_options.rb │ │ │ ├── to_time_preserves_timezone.rb │ │ │ └── wrap_parameters.rb │ │ ├── locales │ │ │ └── en.yml │ │ ├── puma.rb │ │ ├── routes.rb │ │ ├── secrets.yml │ │ └── spring.rb │ ├── db │ │ ├── migrate │ │ │ ├── 20160524121108_create_users.rb │ │ │ ├── 20160524121211_create_posts.rb │ │ │ └── 20160524121235_create_comments.rb │ │ ├── schema.rb │ │ ├── seeds.rb │ │ └── structure.sql │ ├── lib │ │ ├── assets │ │ │ └── .keep │ │ ├── pass_auth_token.rb │ │ └── tasks │ │ │ └── .keep │ ├── log │ │ └── .keep │ ├── public │ │ ├── 404.html │ │ ├── 422.html │ │ ├── 500.html │ │ ├── apple-touch-icon-precomposed.png │ │ ├── apple-touch-icon.png │ │ ├── favicon.ico │ │ └── robots.txt │ └── tmp │ │ └── .keep ├── roda_graphql │ ├── .env │ ├── .gitignore │ ├── Gemfile │ ├── Gemfile.lock │ ├── README.md │ ├── Rakefile │ ├── api │ │ ├── models │ │ │ ├── comment.rb │ │ │ ├── post.rb │ │ │ └── user.rb │ │ ├── routes │ │ │ └── main.rb │ │ ├── schema.rb │ │ └── types │ │ │ ├── comment_type.rb │ │ │ ├── post_type.rb │ │ │ └── user_type.rb │ ├── assets │ │ ├── assets.rb │ │ ├── css │ │ │ ├── application.css │ │ │ ├── graphiql-0.7.0.css │ │ │ └── main.css │ │ └── js │ │ │ ├── application.js │ │ │ ├── fetch-0.10.1.js │ │ │ ├── graphiql-0.7.0.js │ │ │ ├── react-15.0.1.js │ │ │ └── react-dom-15.0.1.js │ ├── blog.db │ ├── config.ru │ ├── db │ │ ├── migrate │ │ │ ├── 1_user.rb │ │ │ ├── 2_post.rb │ │ │ └── 3_comment.rb │ │ └── seeds │ │ │ └── 20150928000000_seed.rb │ ├── middlewares │ │ └── pass_auth_token.rb │ ├── roda_graphql.rb │ └── views │ │ ├── graphiql.erb │ │ └── layout.erb └── sinatra_graphql │ ├── .gitignore │ ├── Gemfile │ ├── Gemfile.lock │ ├── README.md │ ├── Rakefile │ ├── config.ru │ ├── config │ ├── db.yml │ └── initializers │ │ └── database.rb │ ├── db │ ├── migrate │ │ ├── 1_user.rb │ │ ├── 2_post.rb │ │ └── 3_comment.rb │ └── seeds │ │ └── 20150928000000_seed.rb │ ├── lib │ ├── .gitkeep │ ├── api │ │ ├── node_identification.rb │ │ ├── schema.rb │ │ └── types │ │ │ ├── comment_type.rb │ │ │ ├── post_type.rb │ │ │ └── user_type.rb │ └── models │ │ ├── comment.rb │ │ ├── post.rb │ │ └── user.rb │ ├── logs │ ├── common.log │ └── output.log │ ├── middlewares │ └── pass_auth_token.rb │ ├── public │ ├── favicon.ico │ ├── images │ │ ├── .gitkeep │ │ ├── hazel_icon.png │ │ └── hazel_small.png │ ├── javascripts │ │ ├── .gitkeep │ │ ├── application.js │ │ ├── fetch-0.10.1.js │ │ ├── graphiql-0.7.0.js │ │ ├── react-15.0.1.js │ │ └── react-dom-15.0.1.js │ └── stylesheets │ │ ├── application.css │ │ ├── graphiql-0.7.0.css │ │ └── main.css │ ├── sinatra_graphql.rb │ └── views │ ├── graphiql.erb │ └── layout.erb └── scala ├── README.md └── play_grapgql ├── .gitignore ├── LICENSE ├── README ├── app ├── Filters.scala ├── Module.scala ├── controllers │ ├── AsyncController.scala │ ├── CountController.scala │ └── HomeController.scala ├── filters │ └── ExampleFilter.scala ├── services │ ├── ApplicationTimer.scala │ └── Counter.scala └── views │ ├── index.scala.html │ └── main.scala.html ├── bin └── activator ├── build.sbt ├── conf ├── application.conf ├── logback.xml └── routes ├── libexec └── activator-launch-1.3.10.jar ├── project ├── build.properties └── plugins.sbt ├── public ├── images │ └── favicon.png ├── javascripts │ └── hello.js └── stylesheets │ └── main.css └── test ├── ApplicationSpec.scala └── IntegrationSpec.scala /elixir/README.md: -------------------------------------------------------------------------------- 1 | # Elixir based web frameworks 2 | 3 | A set of GraphQL server implementation on popular Elixir web frameworks. 4 | 5 | ## Frameworks 6 | * Phoenix 7 | 8 | ```bash 9 | $ brew update 10 | $ brew install elixir 11 | ``` 12 | 13 | Then, follow the example readme to setup application locally. 14 | -------------------------------------------------------------------------------- /elixir/phoenix_graphql/.gitignore: -------------------------------------------------------------------------------- 1 | # App artifacts 2 | /_build 3 | /db 4 | /deps 5 | /*.ez 6 | 7 | # Generate on crash by the VM 8 | erl_crash.dump 9 | 10 | # The config/prod.secret.exs file by default contains sensitive 11 | # data and you should not commit it into version control. 12 | # 13 | # Alternatively, you may comment the line below and commit the 14 | # secrets file as long as you replace its contents by environment 15 | # variables. 16 | /config/prod.secret.exs -------------------------------------------------------------------------------- /elixir/phoenix_graphql/config/config.exs: -------------------------------------------------------------------------------- 1 | # This file is responsible for configuring your application 2 | # and its dependencies with the aid of the Mix.Config module. 3 | # 4 | # This configuration file is loaded before any dependency and 5 | # is restricted to this project. 6 | use Mix.Config 7 | 8 | # General application configuration 9 | config :phoenix_graphql, 10 | ecto_repos: [PhoenixGraphql.Repo] 11 | 12 | # Configures the endpoint 13 | config :phoenix_graphql, PhoenixGraphql.Endpoint, 14 | url: [host: "localhost"], 15 | secret_key_base: "guMYRuYOMq+olmZ4Vu6xBST4H/MfWRCQDyar85vGraQsw6rSKAHkqgSgTDTOO2zz", 16 | render_errors: [view: PhoenixGraphql.ErrorView, accepts: ~w(json)], 17 | pubsub: [name: PhoenixGraphql.PubSub, 18 | adapter: Phoenix.PubSub.PG2] 19 | 20 | # Configures Elixir's Logger 21 | config :logger, :console, 22 | format: "$time $metadata[$level] $message\n", 23 | metadata: [:request_id] 24 | 25 | # Import environment specific config. This must remain at the bottom 26 | # of this file so it overrides the configuration defined above. 27 | import_config "#{Mix.env}.exs" 28 | -------------------------------------------------------------------------------- /elixir/phoenix_graphql/config/dev.exs: -------------------------------------------------------------------------------- 1 | use Mix.Config 2 | 3 | # For development, we disable any cache and enable 4 | # debugging and code reloading. 5 | # 6 | # The watchers configuration can be used to run external 7 | # watchers to your application. For example, we use it 8 | # with brunch.io to recompile .js and .css sources. 9 | config :phoenix_graphql, PhoenixGraphql.Endpoint, 10 | http: [port: 4000], 11 | debug_errors: true, 12 | code_reloader: true, 13 | check_origin: false, 14 | watchers: [] 15 | 16 | 17 | # Do not include metadata nor timestamps in development logs 18 | config :logger, :console, format: "[$level] $message\n" 19 | 20 | # Set a higher stacktrace during development. Avoid configuring such 21 | # in production as building large stacktraces may be expensive. 22 | config :phoenix, :stacktrace_depth, 20 23 | 24 | # Configure your database 25 | config :phoenix_graphql, PhoenixGraphql.Repo, 26 | adapter: Ecto.Adapters.Postgres, 27 | username: "gaurav", 28 | database: "phoenix_graphql_dev", 29 | hostname: "localhost", 30 | pool_size: 10 31 | -------------------------------------------------------------------------------- /elixir/phoenix_graphql/config/test.exs: -------------------------------------------------------------------------------- 1 | use Mix.Config 2 | 3 | # We don't run a server during test. If one is required, 4 | # you can enable the server option below. 5 | config :phoenix_graphql, PhoenixGraphql.Endpoint, 6 | http: [port: 4001], 7 | server: false 8 | 9 | # Print only warnings and errors during test 10 | config :logger, level: :warn 11 | 12 | # Configure your database 13 | config :phoenix_graphql, PhoenixGraphql.Repo, 14 | adapter: Ecto.Adapters.Postgres, 15 | username: "postgres", 16 | password: "postgres", 17 | database: "phoenix_graphql_test", 18 | hostname: "localhost", 19 | pool: Ecto.Adapters.SQL.Sandbox 20 | -------------------------------------------------------------------------------- /elixir/phoenix_graphql/lib/phoenix_graphql.ex: -------------------------------------------------------------------------------- 1 | defmodule PhoenixGraphql do 2 | use Application 3 | 4 | # See http://elixir-lang.org/docs/stable/elixir/Application.html 5 | # for more information on OTP Applications 6 | def start(_type, _args) do 7 | import Supervisor.Spec 8 | 9 | # Define workers and child supervisors to be supervised 10 | children = [ 11 | # Start the Ecto repository 12 | supervisor(PhoenixGraphql.Repo, []), 13 | # Start the endpoint when the application starts 14 | supervisor(PhoenixGraphql.Endpoint, []), 15 | # Start your own worker by calling: PhoenixGraphql.Worker.start_link(arg1, arg2, arg3) 16 | # worker(PhoenixGraphql.Worker, [arg1, arg2, arg3]), 17 | ] 18 | 19 | # See http://elixir-lang.org/docs/stable/elixir/Supervisor.html 20 | # for other strategies and supported options 21 | opts = [strategy: :one_for_one, name: PhoenixGraphql.Supervisor] 22 | Supervisor.start_link(children, opts) 23 | end 24 | 25 | # Tell Phoenix to update the endpoint configuration 26 | # whenever the application is updated. 27 | def config_change(changed, _new, removed) do 28 | PhoenixGraphql.Endpoint.config_change(changed, removed) 29 | :ok 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /elixir/phoenix_graphql/lib/phoenix_graphql/repo.ex: -------------------------------------------------------------------------------- 1 | defmodule PhoenixGraphql.Repo do 2 | use Ecto.Repo, otp_app: :phoenix_graphql 3 | end 4 | -------------------------------------------------------------------------------- /elixir/phoenix_graphql/priv/repo/migrations/20160526044431_create_user.exs: -------------------------------------------------------------------------------- 1 | defmodule PhoenixGraphql.Repo.Migrations.CreateUser do 2 | use Ecto.Migration 3 | 4 | def change do 5 | create table(:users) do 6 | add :first_name, :string 7 | add :last_name, :string 8 | add :email, :string 9 | add :username, :string 10 | 11 | timestamps 12 | end 13 | 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /elixir/phoenix_graphql/priv/repo/migrations/20160526044445_create_post.exs: -------------------------------------------------------------------------------- 1 | defmodule PhoenixGraphql.Repo.Migrations.CreatePost do 2 | use Ecto.Migration 3 | 4 | def change do 5 | create table(:posts) do 6 | add :title, :string 7 | add :body, :text 8 | add :user_id, references(:users, on_delete: :nothing) 9 | 10 | timestamps 11 | end 12 | create index(:posts, [:user_id]) 13 | 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /elixir/phoenix_graphql/priv/repo/migrations/20160526044513_create_comment.exs: -------------------------------------------------------------------------------- 1 | defmodule PhoenixGraphql.Repo.Migrations.CreateComment do 2 | use Ecto.Migration 3 | 4 | def change do 5 | create table(:comments) do 6 | add :body, :text 7 | add :user_id, references(:users, on_delete: :nothing) 8 | add :post_id, references(:posts, on_delete: :nothing) 9 | 10 | timestamps 11 | end 12 | create index(:comments, [:user_id]) 13 | create index(:comments, [:post_id]) 14 | 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /elixir/phoenix_graphql/priv/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/elixir/phoenix_graphql/priv/static/favicon.ico -------------------------------------------------------------------------------- /elixir/phoenix_graphql/priv/static/images/phoenix.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/elixir/phoenix_graphql/priv/static/images/phoenix.png -------------------------------------------------------------------------------- /elixir/phoenix_graphql/priv/static/js/app.js: -------------------------------------------------------------------------------- 1 | // for phoenix_html support, including form and button helpers 2 | // copy the following scripts into your javascript bundle: 3 | // * https://raw.githubusercontent.com/phoenixframework/phoenix_html/v2.3.0/priv/static/phoenix_html.js -------------------------------------------------------------------------------- /elixir/phoenix_graphql/priv/static/robots.txt: -------------------------------------------------------------------------------- 1 | # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file 2 | # 3 | # To ban all spiders from the entire site uncomment the next two lines: 4 | # User-agent: * 5 | # Disallow: / 6 | -------------------------------------------------------------------------------- /elixir/phoenix_graphql/test/models/comment_test.exs: -------------------------------------------------------------------------------- 1 | defmodule PhoenixGraphql.CommentTest do 2 | use PhoenixGraphql.ModelCase 3 | 4 | alias PhoenixGraphql.Comment 5 | 6 | @valid_attrs %{body: "some content"} 7 | @invalid_attrs %{} 8 | 9 | test "changeset with valid attributes" do 10 | changeset = Comment.changeset(%Comment{}, @valid_attrs) 11 | assert changeset.valid? 12 | end 13 | 14 | test "changeset with invalid attributes" do 15 | changeset = Comment.changeset(%Comment{}, @invalid_attrs) 16 | refute changeset.valid? 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /elixir/phoenix_graphql/test/models/post_test.exs: -------------------------------------------------------------------------------- 1 | defmodule PhoenixGraphql.PostTest do 2 | use PhoenixGraphql.ModelCase 3 | 4 | alias PhoenixGraphql.Post 5 | 6 | @valid_attrs %{body: "some content", title: "some content"} 7 | @invalid_attrs %{} 8 | 9 | test "changeset with valid attributes" do 10 | changeset = Post.changeset(%Post{}, @valid_attrs) 11 | assert changeset.valid? 12 | end 13 | 14 | test "changeset with invalid attributes" do 15 | changeset = Post.changeset(%Post{}, @invalid_attrs) 16 | refute changeset.valid? 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /elixir/phoenix_graphql/test/models/user_test.exs: -------------------------------------------------------------------------------- 1 | defmodule PhoenixGraphql.UserTest do 2 | use PhoenixGraphql.ModelCase 3 | 4 | alias PhoenixGraphql.User 5 | 6 | @valid_attrs %{email: "some content", first_name: "some content", last_name: "some content", username: "some content"} 7 | @invalid_attrs %{} 8 | 9 | test "changeset with valid attributes" do 10 | changeset = User.changeset(%User{}, @valid_attrs) 11 | assert changeset.valid? 12 | end 13 | 14 | test "changeset with invalid attributes" do 15 | changeset = User.changeset(%User{}, @invalid_attrs) 16 | refute changeset.valid? 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /elixir/phoenix_graphql/test/support/channel_case.ex: -------------------------------------------------------------------------------- 1 | defmodule PhoenixGraphql.ChannelCase do 2 | @moduledoc """ 3 | This module defines the test case to be used by 4 | channel tests. 5 | 6 | Such tests rely on `Phoenix.ChannelTest` and also 7 | import other functionality to make it easier 8 | to build and query models. 9 | 10 | Finally, if the test case interacts with the database, 11 | it cannot be async. For this reason, every test runs 12 | inside a transaction which is reset at the beginning 13 | of the test unless the test case is marked as async. 14 | """ 15 | 16 | use ExUnit.CaseTemplate 17 | 18 | using do 19 | quote do 20 | # Import conveniences for testing with channels 21 | use Phoenix.ChannelTest 22 | 23 | alias PhoenixGraphql.Repo 24 | import Ecto 25 | import Ecto.Changeset 26 | import Ecto.Query 27 | 28 | 29 | # The default endpoint for testing 30 | @endpoint PhoenixGraphql.Endpoint 31 | end 32 | end 33 | 34 | setup tags do 35 | :ok = Ecto.Adapters.SQL.Sandbox.checkout(PhoenixGraphql.Repo) 36 | 37 | unless tags[:async] do 38 | Ecto.Adapters.SQL.Sandbox.mode(PhoenixGraphql.Repo, {:shared, self()}) 39 | end 40 | 41 | :ok 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /elixir/phoenix_graphql/test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start 2 | 3 | Ecto.Adapters.SQL.Sandbox.mode(PhoenixGraphql.Repo, :manual) 4 | 5 | -------------------------------------------------------------------------------- /elixir/phoenix_graphql/test/views/error_view_test.exs: -------------------------------------------------------------------------------- 1 | defmodule PhoenixGraphql.ErrorViewTest do 2 | use PhoenixGraphql.ConnCase, async: true 3 | 4 | # Bring render/3 and render_to_string/3 for testing custom views 5 | import Phoenix.View 6 | 7 | test "renders 404.json" do 8 | assert render(PhoenixGraphql.ErrorView, "404.json", []) == 9 | %{errors: %{detail: "Page not found"}} 10 | end 11 | 12 | test "render 500.json" do 13 | assert render(PhoenixGraphql.ErrorView, "500.json", []) == 14 | %{errors: %{detail: "Internal server error"}} 15 | end 16 | 17 | test "render any other" do 18 | assert render(PhoenixGraphql.ErrorView, "505.json", []) == 19 | %{errors: %{detail: "Internal server error"}} 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /elixir/phoenix_graphql/web/api/resolver.ex: -------------------------------------------------------------------------------- 1 | defmodule PhoenixGraphql.Api.Resolver do 2 | alias PhoenixGraphql.Repo 3 | 4 | def find(%{id: id, model: model, preloaders: preloaders}) do 5 | case model |> model.with_comments |> Repo.get!(id) do 6 | nil -> {:error, "No found"} 7 | object -> {:ok, object} 8 | end 9 | end 10 | 11 | def all(%{model: model, preloaders: preloaders}) do 12 | case Repo.all(model) |> Repo.preload(preloaders) do 13 | nil -> {:error, "No #{model} found"} 14 | collection -> {:ok, collection} 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /elixir/phoenix_graphql/web/api/types/comment.ex: -------------------------------------------------------------------------------- 1 | defmodule PhoenixGraphql.Api.Schema.Types.Comment do 2 | use Absinthe.Schema.Notation 3 | 4 | @desc """ 5 | A comment 6 | """ 7 | object :comment do 8 | field :id, :id 9 | field :body, 10 | type: :string, 11 | resolve: fn 12 | _, obj -> 13 | {:ok, obj.source.body |> Earmark.to_html} 14 | end 15 | field :inserted_at, :string 16 | field :user, :user 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /elixir/phoenix_graphql/web/api/types/post.ex: -------------------------------------------------------------------------------- 1 | defmodule PhoenixGraphql.Api.Schema.Types.Post do 2 | use Absinthe.Schema.Notation 3 | 4 | @desc """ 5 | A post 6 | """ 7 | object :post do 8 | field :id, :id 9 | field :title, :string 10 | field :body, 11 | type: :string, 12 | resolve: fn 13 | _, obj -> 14 | {:ok, obj.source.body |> Earmark.to_html} 15 | end 16 | field :user, :user 17 | field :comments, list_of(:comment) 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /elixir/phoenix_graphql/web/api/types/user.ex: -------------------------------------------------------------------------------- 1 | defmodule PhoenixGraphql.Api.Schema.Types.User do 2 | use Absinthe.Schema.Notation 3 | 4 | @desc """ 5 | A user 6 | """ 7 | object :user do 8 | field :id, :id 9 | field :first_name, :string 10 | field :last_name, :string 11 | field :email, :string 12 | field :username, :string 13 | field :posts, list_of(:post) 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /elixir/phoenix_graphql/web/context.ex: -------------------------------------------------------------------------------- 1 | defmodule PhoenixGraphql.Context do 2 | @moduledoc """ 3 | This module is just a regular plug that can look at the conn struct and build 4 | the appropriate absinthe context. 5 | """ 6 | 7 | @behaviour Plug 8 | 9 | def init(opts), do: opts 10 | def call(conn, _) do 11 | conn 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /elixir/phoenix_graphql/web/controllers/page_controller.ex: -------------------------------------------------------------------------------- 1 | defmodule PhoenixGraphql.PageController do 2 | use PhoenixGraphql.Web, :controller 3 | import Joken 4 | 5 | def graphiql(conn, _params) do 6 | # Pass to root route as we don't know the token 7 | # For real API you would use authentication or something 8 | auth_token = token() 9 | |> with_sub(1234567890) 10 | |> sign(hs256("secret")) 11 | |> get_compact 12 | 13 | render(conn, "graphiql.html", token: auth_token) 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /elixir/phoenix_graphql/web/gettext.ex: -------------------------------------------------------------------------------- 1 | defmodule PhoenixGraphql.Gettext do 2 | @moduledoc """ 3 | A module providing Internationalization with a gettext-based API. 4 | 5 | By using [Gettext](https://hexdocs.pm/gettext), 6 | your module gains a set of macros for translations, for example: 7 | 8 | import PhoenixGraphql.Gettext 9 | 10 | # Simple translation 11 | gettext "Here is the string to translate" 12 | 13 | # Plural translation 14 | ngettext "Here is the string to translate", 15 | "Here are the strings to translate", 16 | 3 17 | 18 | # Domain-based translation 19 | dgettext "errors", "Here is the error message to translate" 20 | 21 | See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage. 22 | """ 23 | use Gettext, otp_app: :phoenix_graphql 24 | end 25 | -------------------------------------------------------------------------------- /elixir/phoenix_graphql/web/models/comment.ex: -------------------------------------------------------------------------------- 1 | defmodule PhoenixGraphql.Comment do 2 | use PhoenixGraphql.Web, :model 3 | 4 | schema "comments" do 5 | field :body, :string 6 | belongs_to :user, PhoenixGraphql.User 7 | belongs_to :post, PhoenixGraphql.Post 8 | 9 | timestamps 10 | end 11 | 12 | @doc """ 13 | Builds a changeset based on the `struct` and `params`. 14 | """ 15 | def changeset(struct, params \\ %{}) do 16 | struct 17 | |> cast(params, [:body]) 18 | |> validate_required([:body]) 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /elixir/phoenix_graphql/web/models/post.ex: -------------------------------------------------------------------------------- 1 | defmodule PhoenixGraphql.Post do 2 | use PhoenixGraphql.Web, :model 3 | 4 | schema "posts" do 5 | field :title, :string 6 | field :body, :string 7 | belongs_to :user, PhoenixGraphql.User 8 | 9 | has_many :comments, PhoenixGraphql.Comment 10 | timestamps 11 | end 12 | 13 | @doc """ 14 | Builds a changeset based on the `struct` and `params`. 15 | """ 16 | def changeset(struct, params \\ %{}) do 17 | struct 18 | |> cast(params, [:title, :body]) 19 | |> validate_required([:title, :body]) 20 | end 21 | 22 | def with_comments(query) do 23 | from p in query, 24 | join: c in assoc(p, :comments), 25 | join: u in PhoenixGraphql.User, on: c.user_id == u.id, 26 | order_by: [desc: c.id], 27 | preload: [:user, comments: {c, user: u}] 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /elixir/phoenix_graphql/web/models/user.ex: -------------------------------------------------------------------------------- 1 | defmodule PhoenixGraphql.User do 2 | use PhoenixGraphql.Web, :model 3 | 4 | schema "users" do 5 | field :first_name, :string 6 | field :last_name, :string 7 | field :email, :string 8 | field :username, :string 9 | 10 | has_many :comments, PhoenixGraphql.Comment 11 | has_many :posts, PhoenixGraphql.Post 12 | 13 | timestamps 14 | end 15 | 16 | @doc """ 17 | Builds a changeset based on the `struct` and `params`. 18 | """ 19 | def changeset(struct, params \\ %{}) do 20 | struct 21 | |> cast(params, [:first_name, :last_name, :email, :username]) 22 | |> validate_required([:first_name, :last_name, :email, :username]) 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /elixir/phoenix_graphql/web/router.ex: -------------------------------------------------------------------------------- 1 | defmodule PhoenixGraphql.Router do 2 | use PhoenixGraphql.Web, :router 3 | import Joken 4 | 5 | @skip_token_verification %{joken_skip: true} 6 | 7 | pipeline :browser do 8 | plug :accepts, ["html"] 9 | plug :fetch_session 10 | plug :fetch_flash 11 | plug :protect_from_forgery 12 | plug :put_secure_browser_headers 13 | end 14 | 15 | pipeline :graphql do 16 | plug :accepts, ["json"] 17 | plug :fetch_session 18 | plug :fetch_flash 19 | plug :protect_from_forgery 20 | plug Joken.Plug, verify: &PhoenixGraphql.Router.verify_function/0 21 | plug PhoenixGraphql.Context 22 | end 23 | 24 | # Skip root route 25 | scope "/", PhoenixGraphql do 26 | pipe_through :browser 27 | get "/", PageController, :graphiql, private: @skip_token_verification 28 | end 29 | 30 | scope "/graphql" do 31 | pipe_through :graphql 32 | get "/", Absinthe.Plug, schema: PhoenixGraphql.Api.Schema 33 | post "/", Absinthe.Plug, schema: PhoenixGraphql.Api.Schema 34 | end 35 | 36 | def verify_function() do 37 | %Joken.Token{} 38 | |> with_json_module(Poison) 39 | |> with_signer(hs256("secret")) 40 | |> with_sub(1234567890) 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /elixir/phoenix_graphql/web/templates/layout/app.html.eex: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | <%= render @view_module, @view_template, assigns %> 25 | 26 | 27 | -------------------------------------------------------------------------------- /elixir/phoenix_graphql/web/views/error_helpers.ex: -------------------------------------------------------------------------------- 1 | defmodule PhoenixGraphql.ErrorHelpers do 2 | @moduledoc """ 3 | Conveniences for translating and building error messages. 4 | """ 5 | 6 | @doc """ 7 | Translates an error message using gettext. 8 | """ 9 | def translate_error({msg, opts}) do 10 | # Because error messages were defined within Ecto, we must 11 | # call the Gettext module passing our Gettext backend. We 12 | # also use the "errors" domain as translations are placed 13 | # in the errors.po file. 14 | # Ecto will pass the :count keyword if the error message is 15 | # meant to be pluralized. 16 | # On your own code and templates, depending on whether you 17 | # need the message to be pluralized or not, this could be 18 | # written simply as: 19 | # 20 | # dngettext "errors", "1 file", "%{count} files", count 21 | # dgettext "errors", "is invalid" 22 | # 23 | if count = opts[:count] do 24 | Gettext.dngettext(PhoenixGraphql.Gettext, "errors", msg, msg, count, opts) 25 | else 26 | Gettext.dgettext(PhoenixGraphql.Gettext, "errors", msg, opts) 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /elixir/phoenix_graphql/web/views/error_view.ex: -------------------------------------------------------------------------------- 1 | defmodule PhoenixGraphql.ErrorView do 2 | use PhoenixGraphql.Web, :view 3 | 4 | def render("404.json", _assigns) do 5 | %{errors: %{detail: "Page not found"}} 6 | end 7 | 8 | def render("500.json", _assigns) do 9 | %{errors: %{detail: "Internal server error"}} 10 | end 11 | 12 | # In case no render clause matches or no 13 | # template is found, let's render it as 500 14 | def template_not_found(_template, assigns) do 15 | render "500.json", assigns 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /elixir/phoenix_graphql/web/views/layout_view.ex: -------------------------------------------------------------------------------- 1 | defmodule PhoenixGraphql.LayoutView do 2 | use PhoenixGraphql.Web, :view 3 | end 4 | -------------------------------------------------------------------------------- /elixir/phoenix_graphql/web/views/page_view.ex: -------------------------------------------------------------------------------- 1 | defmodule PhoenixGraphql.PageView do 2 | use PhoenixGraphql.Web, :view 3 | end 4 | -------------------------------------------------------------------------------- /javascript/README.md: -------------------------------------------------------------------------------- 1 | # Node based web frameworks 2 | 3 | A set of GraphQL server implementation on popular Node web frameworks. 4 | 5 | ## Frameworks 6 | * Express 7 | * Koa 8 | * Meteor 9 | 10 | ```bash 11 | $ brew update 12 | $ brew install node # or download package from https://nodejs.org/en/download/ 13 | ``` 14 | 15 | Then, follow the example readme to setup application locally. 16 | -------------------------------------------------------------------------------- /javascript/express_graphql/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-0"] 3 | } 4 | -------------------------------------------------------------------------------- /javascript/express_graphql/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/* 2 | -------------------------------------------------------------------------------- /javascript/express_graphql/README.md: -------------------------------------------------------------------------------- 1 | # Express GraphQL Server 2 | 3 | ## Getting started locally 4 | 5 | ```bash 6 | git clone repo 7 | cd express_graphql 8 | npm install 9 | # Setup database 10 | createdb express_graphql_development 11 | node_modules/sequelize-cli/bin/sequelize db:migrate 12 | node_modules/sequelize-cli/bin/sequelize db:seed:all 13 | # Run server 14 | DEBUG=express_graphql:* npm start 15 | ``` 16 | 17 | [Visit browser](http://localhost:3000/) 18 | 19 | ### Supported API Queries 20 | 21 | ``` 22 | { 23 | allPosts { 24 | id, 25 | title 26 | body 27 | user { 28 | id 29 | first_name 30 | } 31 | comments{ 32 | id 33 | body 34 | } 35 | 36 | } 37 | } 38 | ``` 39 | 40 | ``` 41 | { 42 | post(id: 1) { 43 | id, 44 | title 45 | body 46 | user { 47 | id 48 | first_name 49 | } 50 | comments{ 51 | id 52 | body 53 | } 54 | 55 | } 56 | } 57 | ``` 58 | -------------------------------------------------------------------------------- /javascript/express_graphql/api/types/commentType.js: -------------------------------------------------------------------------------- 1 | import userType from './userType'; 2 | import models from '../../models'; 3 | import { resolver } from 'graphql-sequelize'; 4 | import { GraphQLObjectType, GraphQLNonNull, GraphQLList, GraphQLInt, GraphQLString} from 'graphql'; 5 | 6 | let commentType = new GraphQLObjectType({ 7 | name: 'Comment', 8 | description: 'A comment', 9 | fields: { 10 | id: { 11 | type: new GraphQLNonNull(GraphQLInt), 12 | description: 'The id of the comment.', 13 | }, 14 | body: { 15 | type: GraphQLString, 16 | description: 'The body of the comment' 17 | }, 18 | user: { 19 | type: userType, 20 | description: 'The user of the comment', 21 | resolve: resolver(models.User) 22 | }, 23 | } 24 | }); 25 | 26 | module.exports = commentType; 27 | -------------------------------------------------------------------------------- /javascript/express_graphql/api/types/postType.js: -------------------------------------------------------------------------------- 1 | import commentType from './commentType'; 2 | import userType from './userType'; 3 | import models from '../../models'; 4 | import { resolver } from 'graphql-sequelize'; 5 | import { GraphQLObjectType, GraphQLNonNull, GraphQLList, GraphQLInt, GraphQLString} from 'graphql'; 6 | 7 | let postType = new GraphQLObjectType({ 8 | name: 'Post', 9 | description: 'A post', 10 | fields: { 11 | id: { 12 | type: new GraphQLNonNull(GraphQLInt), 13 | description: 'The id of the post.', 14 | }, 15 | title: { 16 | type: GraphQLString, 17 | description: 'The title of the post' 18 | }, 19 | body: { 20 | type: GraphQLString, 21 | description: 'The body of the post' 22 | }, 23 | user: { 24 | type: userType, 25 | description: 'The user of the post', 26 | resolve: resolver(models.Post.User) 27 | }, 28 | comments: { 29 | type: new GraphQLList(commentType), 30 | resolve: resolver(models.Post.Comments) 31 | } 32 | } 33 | }); 34 | 35 | module.exports = postType; 36 | -------------------------------------------------------------------------------- /javascript/express_graphql/api/types/userType.js: -------------------------------------------------------------------------------- 1 | import postType from './postType'; 2 | import commentType from './commentType'; 3 | import models from '../../models'; 4 | import { resolver, attributeFields } from 'graphql-sequelize'; 5 | import { GraphQLObjectType, GraphQLNonNull, GraphQLList, GraphQLInt, GraphQLString} from 'graphql'; 6 | 7 | let userType = new GraphQLObjectType({ 8 | name: 'User', 9 | description: 'A user', 10 | fields: () => ({ 11 | id: { 12 | type: new GraphQLNonNull(GraphQLInt), 13 | description: 'The id of the user.', 14 | }, 15 | first_name: { 16 | type: GraphQLString, 17 | description: 'The first name of the user.', 18 | }, 19 | last_name: { 20 | type: GraphQLString, 21 | description: 'The last name of the user.', 22 | }, 23 | username: { 24 | type: GraphQLString, 25 | description: 'The username of the user.', 26 | }, 27 | 28 | email: { 29 | type: GraphQLString, 30 | description: 'The email of the user.', 31 | }, 32 | }) 33 | }); 34 | 35 | module.exports = userType; 36 | -------------------------------------------------------------------------------- /javascript/express_graphql/config/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "development": { 3 | "username": "gaurav", 4 | "password": null, 5 | "database": "express_graphql_development", 6 | "host": "127.0.0.1", 7 | "dialect": "postgres" 8 | }, 9 | "test": { 10 | "username": "gaurav", 11 | "password": null, 12 | "database": "express_graphql_test", 13 | "host": "127.0.0.1", 14 | "dialect": "postgres" 15 | }, 16 | "production": { 17 | "username": "gaurav", 18 | "password": null, 19 | "database": "express_graphql_production", 20 | "host": "127.0.0.1", 21 | "dialect": "postgres" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /javascript/express_graphql/migrations/20160521095312-create-user.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | module.exports = { 3 | up: function(queryInterface, Sequelize) { 4 | return queryInterface.createTable('Users', { 5 | id: { 6 | allowNull: false, 7 | autoIncrement: true, 8 | primaryKey: true, 9 | type: Sequelize.INTEGER 10 | }, 11 | first_name: { 12 | type: Sequelize.STRING 13 | }, 14 | last_name: { 15 | type: Sequelize.STRING 16 | }, 17 | email: { 18 | type: Sequelize.STRING, 19 | index: true 20 | }, 21 | username: { 22 | type: Sequelize.STRING, 23 | index: true 24 | }, 25 | createdAt: { 26 | allowNull: false, 27 | type: Sequelize.DATE 28 | }, 29 | updatedAt: { 30 | allowNull: false, 31 | type: Sequelize.DATE 32 | } 33 | }); 34 | }, 35 | down: function(queryInterface, Sequelize) { 36 | return queryInterface.dropTable('Users'); 37 | } 38 | }; 39 | -------------------------------------------------------------------------------- /javascript/express_graphql/migrations/20160521095507-create-post.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | module.exports = { 3 | up: function(queryInterface, Sequelize) { 4 | return queryInterface.createTable('Posts', { 5 | id: { 6 | allowNull: false, 7 | autoIncrement: true, 8 | primaryKey: true, 9 | type: Sequelize.INTEGER 10 | }, 11 | title: { 12 | type: Sequelize.STRING 13 | }, 14 | body: { 15 | type: Sequelize.TEXT 16 | }, 17 | UserId: { 18 | type: Sequelize.INTEGER, 19 | index: true, 20 | foreignKey: true 21 | }, 22 | createdAt: { 23 | allowNull: false, 24 | type: Sequelize.DATE 25 | }, 26 | updatedAt: { 27 | allowNull: false, 28 | type: Sequelize.DATE 29 | } 30 | }); 31 | }, 32 | down: function(queryInterface, Sequelize) { 33 | return queryInterface.dropTable('Posts'); 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /javascript/express_graphql/migrations/20160521100324-create-comment.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | module.exports = { 3 | up: function(queryInterface, Sequelize) { 4 | return queryInterface.createTable('Comments', { 5 | id: { 6 | allowNull: false, 7 | autoIncrement: true, 8 | primaryKey: true, 9 | type: Sequelize.INTEGER 10 | }, 11 | body: { 12 | type: Sequelize.TEXT 13 | }, 14 | PostId: { 15 | type: Sequelize.INTEGER, 16 | index: true, 17 | foreignKey: true 18 | }, 19 | UserId: { 20 | type: Sequelize.INTEGER, 21 | index: true, 22 | foreignKey: true 23 | }, 24 | createdAt: { 25 | allowNull: false, 26 | type: Sequelize.DATE 27 | }, 28 | updatedAt: { 29 | allowNull: false, 30 | type: Sequelize.DATE 31 | } 32 | }); 33 | }, 34 | down: function(queryInterface, Sequelize) { 35 | return queryInterface.dropTable('Comments'); 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /javascript/express_graphql/models/comment.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | module.exports = function(sequelize, DataTypes) { 3 | var Comment = sequelize.define('Comment', { 4 | body: DataTypes.TEXT, 5 | post_id: DataTypes.INTEGER, 6 | user_id: DataTypes.INTEGER 7 | }, { 8 | classMethods: { 9 | associate: function(models) { 10 | Comment.User = Comment.belongsTo(models.User, { 11 | onDelete: "CASCADE", 12 | foreignKey: { 13 | allowNull: false 14 | } 15 | }); 16 | 17 | Comment.Post = Comment.belongsTo(models.Post, { 18 | onDelete: "CASCADE", 19 | foreignKey: { 20 | allowNull: false 21 | } 22 | }); 23 | } 24 | } 25 | }); 26 | return Comment; 27 | }; 28 | -------------------------------------------------------------------------------- /javascript/express_graphql/models/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var fs = require('fs'); 4 | var path = require('path'); 5 | var Sequelize = require('sequelize'); 6 | var basename = path.basename(module.filename); 7 | var env = process.env.NODE_ENV || 'development'; 8 | var config = require(__dirname + '/../config/config.json')[env]; 9 | var db = {}; 10 | 11 | if (config.use_env_variable) { 12 | var sequelize = new Sequelize(process.env[config.use_env_variable]); 13 | } else { 14 | var sequelize = new Sequelize(config.database, config.username, config.password, config); 15 | } 16 | 17 | fs 18 | .readdirSync(__dirname) 19 | .filter(function(file) { 20 | return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js'); 21 | }) 22 | .forEach(function(file) { 23 | var model = sequelize['import'](path.join(__dirname, file)); 24 | db[model.name] = model; 25 | }); 26 | 27 | Object.keys(db).forEach(function(modelName) { 28 | if (db[modelName].associate) { 29 | db[modelName].associate(db); 30 | } 31 | }); 32 | 33 | db.sequelize = sequelize; 34 | db.Sequelize = Sequelize; 35 | 36 | module.exports = db; 37 | -------------------------------------------------------------------------------- /javascript/express_graphql/models/post.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | module.exports = function(sequelize, DataTypes) { 3 | var Post = sequelize.define('Post', { 4 | title: DataTypes.STRING, 5 | body: DataTypes.TEXT, 6 | user_id: DataTypes.INTEGER 7 | }, { 8 | classMethods: { 9 | associate: function(models) { 10 | Post.Comments = Post.hasMany(models.Comment); 11 | Post.User = Post.belongsTo(models.User, { 12 | onDelete: "CASCADE", 13 | foreignKey: { 14 | allowNull: false 15 | } 16 | }); 17 | } 18 | } 19 | }); 20 | return Post; 21 | }; 22 | -------------------------------------------------------------------------------- /javascript/express_graphql/models/user.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | module.exports = function(sequelize, DataTypes) { 3 | var User = sequelize.define('User', { 4 | first_name: DataTypes.STRING, 5 | last_name: DataTypes.STRING, 6 | email: DataTypes.STRING, 7 | username: DataTypes.STRING 8 | }, { 9 | classMethods: { 10 | associate: function(models) { 11 | User.Comments = User.hasMany(models.Comment); 12 | User.Posts = User.hasMany(models.Post); 13 | } 14 | } 15 | }); 16 | return User; 17 | }; 18 | -------------------------------------------------------------------------------- /javascript/express_graphql/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express_graphql", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "nodemon bin/www --exec babel-node --presets es2015,stage-2" 7 | }, 8 | "dependencies": { 9 | "babel-core": "^6.9.0", 10 | "babel-polyfill": "^6.9.0", 11 | "babel-preset-es2015": "^6.9.0", 12 | "babel-preset-stage-0": "^6.5.0", 13 | "body-parser": "~1.13.2", 14 | "cookie-parser": "~1.3.5", 15 | "debug": "~2.2.0", 16 | "express": "~4.13.1", 17 | "express-graphql": "^0.5.1", 18 | "graphql": "^0.5.0", 19 | "graphql-sequelize": "^2.0.0", 20 | "jade": "~1.11.0", 21 | "lodash": "^4.12.0", 22 | "morgan": "~1.6.1", 23 | "sequelize": "^3.23.2", 24 | "sequelize-cli": "^2.4.0", 25 | "serve-favicon": "~2.3.0", 26 | "sqlite3": "^3.1.4" 27 | }, 28 | "devDependencies": { 29 | "babel-cli": "^6.9.0", 30 | "nodemon": "^1.9.2" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /javascript/express_graphql/seeders/20160521103212-user.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | up: function (queryInterface, Sequelize) { 5 | return queryInterface.bulkInsert('Users', [{ 6 | first_name: 'John', 7 | last_name: 'Doe', 8 | email: 'john@doe.com', 9 | username: 'johndoe', 10 | createdAt: new Date((new Date()).getTime()), 11 | updatedAt: new Date((new Date()).getTime()) 12 | }, 13 | { 14 | first_name: 'Maggie', 15 | last_name: 'Turner', 16 | email: 'maggie@turner.com', 17 | username: 'maggie', 18 | createdAt: new Date((new Date()).getTime()), 19 | updatedAt: new Date((new Date()).getTime()) 20 | } 21 | ], {}); 22 | }, 23 | 24 | down: function (queryInterface, Sequelize) { 25 | return queryInterface.bulkDelete('Users', null, {}); 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /javascript/express_graphql/seeders/20160521111530-post.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | up: function (queryInterface, Sequelize) { 5 | return queryInterface.bulkInsert('Posts', [{ 6 | title: 'First post title', 7 | body: 'First post body', 8 | UserId: 1, 9 | createdAt: new Date((new Date()).getTime()), 10 | updatedAt: new Date((new Date()).getTime()) 11 | }, 12 | { 13 | title: 'Second post title', 14 | body: 'Second post body', 15 | UserId: 2, 16 | createdAt: new Date((new Date()).getTime()), 17 | updatedAt: new Date((new Date()).getTime()) 18 | } 19 | ], {}); 20 | }, 21 | 22 | down: function (queryInterface, Sequelize) { 23 | queryInterface.bulkDelete('Posts', null, {}); 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /javascript/express_graphql/seeders/20160521111557-comment.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | up: function (queryInterface, Sequelize) { 5 | return queryInterface.bulkInsert('Comments', [{ 6 | body: 'First post comment', 7 | UserId: 1, 8 | PostId: 1, 9 | createdAt: new Date((new Date()).getTime()), 10 | updatedAt: new Date((new Date()).getTime()) 11 | }, 12 | { 13 | body: 'First post second comment', 14 | UserId: 1, 15 | PostId: 1, 16 | createdAt: new Date((new Date()).getTime()), 17 | updatedAt: new Date((new Date()).getTime()) 18 | }, 19 | { 20 | body: 'Second post first comment', 21 | UserId: 2, 22 | PostId: 2, 23 | createdAt: new Date((new Date()).getTime()), 24 | updatedAt: new Date((new Date()).getTime()) 25 | } 26 | ], {}); 27 | }, 28 | 29 | down: function (queryInterface, Sequelize) { 30 | queryInterface.bulkDelete('Comments', null, {}); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /javascript/koa_graphql/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "development": { 4 | "presets": ["es2015", "stage-0"], 5 | "plugins": ["transform-async-to-generator"] 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /javascript/koa_graphql/.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /javascript/koa_graphql/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/* 2 | npm-debug.* 3 | -------------------------------------------------------------------------------- /javascript/koa_graphql/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "esnext": true, 4 | "bitwise": true, 5 | "camelcase": true, 6 | "curly": true, 7 | "eqeqeq": true, 8 | "immed": true, 9 | "indent": 2, 10 | "latedef": true, 11 | "newcap": true, 12 | "noarg": true, 13 | "quotmark": "single", 14 | "regexp": true, 15 | "undef": true, 16 | "unused": true, 17 | "strict": true, 18 | "trailing": true, 19 | "smarttabs": true, 20 | "white": true 21 | } 22 | -------------------------------------------------------------------------------- /javascript/koa_graphql/README.md: -------------------------------------------------------------------------------- 1 | # Koa GraphQL Server 2 | 3 | ## Getting started locally 4 | 5 | ```bash 6 | git clone repo 7 | cd express_graphql 8 | npm install 9 | 10 | # ORM for database interaction 11 | npm install bookshelf -g -s 12 | # Query building and schema/migration/seed generation 13 | npm install knex -g -s 14 | # Setup database 15 | createdb express_graphql_development 16 | # make sure knex installed globally or refer local installation 17 | knex migrate:latest 18 | knex seed:run 19 | # Run server 20 | DEBUG=koa_graphql:* npm start 21 | ``` 22 | 23 | [Visit browser](http://localhost:3000/) 24 | 25 | ### Supported API Queries 26 | 27 | ``` 28 | { 29 | allPosts { 30 | id, 31 | title 32 | body 33 | user { 34 | id 35 | first_name 36 | } 37 | comments{ 38 | id 39 | body 40 | } 41 | 42 | } 43 | } 44 | ``` 45 | 46 | ``` 47 | { 48 | post(id: 1) { 49 | id, 50 | title 51 | body 52 | user { 53 | id 54 | first_name 55 | } 56 | comments{ 57 | id 58 | body 59 | } 60 | 61 | } 62 | } 63 | ``` 64 | -------------------------------------------------------------------------------- /javascript/koa_graphql/api/types/commentType.js: -------------------------------------------------------------------------------- 1 | import PostType from './postType'; 2 | import UserType from './userType'; 3 | 4 | import { 5 | GraphQLBoolean, 6 | GraphQLID, 7 | GraphQLInt, 8 | GraphQLList, 9 | GraphQLNonNull, 10 | GraphQLObjectType, 11 | GraphQLSchema, 12 | GraphQLString, 13 | } from 'graphql'; 14 | 15 | const CommentType = new GraphQLObjectType({ 16 | name: 'CommentType', 17 | fields: () => ({ 18 | id: { type: new GraphQLNonNull(GraphQLID) }, 19 | body: { 20 | type: GraphQLString, 21 | resolve: (obj) => obj.body, 22 | }, 23 | post: { 24 | type: PostType, 25 | resolve: (obj) => obj.post, 26 | }, 27 | user: { 28 | type: UserType, 29 | resolve: (obj) => obj.user, 30 | }, 31 | }), 32 | }); 33 | 34 | export default CommentType; 35 | -------------------------------------------------------------------------------- /javascript/koa_graphql/api/types/postType.js: -------------------------------------------------------------------------------- 1 | import CommentType from './commentType'; 2 | import UserType from './userType'; 3 | 4 | import { 5 | GraphQLBoolean, 6 | GraphQLID, 7 | GraphQLInt, 8 | GraphQLList, 9 | GraphQLNonNull, 10 | GraphQLObjectType, 11 | GraphQLSchema, 12 | GraphQLString, 13 | } from 'graphql'; 14 | 15 | const PostType = new GraphQLObjectType({ 16 | name: 'PostType', 17 | fields: () => ({ 18 | id: { type: new GraphQLNonNull(GraphQLID) }, 19 | title: { 20 | type: GraphQLString, 21 | resolve: (obj) => obj.title, 22 | }, 23 | body: { 24 | type: GraphQLString, 25 | resolve: (obj) => obj.body, 26 | }, 27 | comments: { 28 | type: new GraphQLList(CommentType), 29 | resolve: (obj) => obj.comments, 30 | }, 31 | user: { 32 | type: UserType, 33 | resolve: (obj) => obj.user, 34 | }, 35 | }), 36 | }); 37 | 38 | export default PostType; 39 | -------------------------------------------------------------------------------- /javascript/koa_graphql/api/types/userType.js: -------------------------------------------------------------------------------- 1 | import PostType from './postType'; 2 | import CommentType from './commentType'; 3 | 4 | import { 5 | GraphQLBoolean, 6 | GraphQLID, 7 | GraphQLInt, 8 | GraphQLList, 9 | GraphQLNonNull, 10 | GraphQLObjectType, 11 | GraphQLSchema, 12 | GraphQLString, 13 | } from 'graphql'; 14 | 15 | const UserType = new GraphQLObjectType({ 16 | name: 'UserType', 17 | fields: () => ({ 18 | id: { type: new GraphQLNonNull(GraphQLID) }, 19 | first_name: { 20 | type: GraphQLString, 21 | resolve: (obj) => obj.first_name, 22 | }, 23 | last_name: { 24 | type: GraphQLString, 25 | resolve: (obj) => obj.last_name, 26 | }, 27 | username: { 28 | type: GraphQLString, 29 | resolve: (obj) => obj.username, 30 | }, 31 | email: { 32 | type: GraphQLString, 33 | resolve: (obj) => obj.email, 34 | }, 35 | posts: { 36 | type: new GraphQLList(PostType), 37 | resolve: (obj) => obj.posts 38 | }, 39 | comments: { 40 | type: new GraphQLList(CommentType), 41 | resolve: (obj) => obj.comments 42 | }, 43 | }), 44 | }); 45 | 46 | export default UserType; 47 | -------------------------------------------------------------------------------- /javascript/koa_graphql/app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const compress = require('koa-compress'); 3 | const logger = require('koa-logger'); 4 | const koa = require('koa'); 5 | const path = require('path'); 6 | var mount = require('koa-mount'); 7 | var convert = require('koa-convert'); 8 | var graphqlHTTP = require('koa-graphql'); 9 | var Schema = require('./api/schema'); 10 | 11 | const app = module.exports = koa(); 12 | 13 | // Logger 14 | app.use(logger()); 15 | app.use(mount('/', graphqlHTTP({ schema: Schema, graphiql: true }))); 16 | 17 | // Compress 18 | app.use(compress()); 19 | 20 | if (!module.parent) { 21 | app.listen(3000); 22 | console.log('listening on port 3000'); 23 | } 24 | -------------------------------------------------------------------------------- /javascript/koa_graphql/bookshelf.js: -------------------------------------------------------------------------------- 1 | // Update with your config settings. 2 | var knex = require('knex')({ 3 | client: 'postgres', 4 | connection: { 5 | host : '127.0.0.1', 6 | user : 'gaurav', 7 | database : 'koa_graphql_development' 8 | }, 9 | pool: { 10 | min: 2, 11 | max: 10 12 | }, 13 | migrations: { 14 | tableName: 'knex_migrations' 15 | } 16 | } 17 | ); 18 | 19 | var bookshelf = module.exports = require('bookshelf')(knex); 20 | -------------------------------------------------------------------------------- /javascript/koa_graphql/migrations/20160521155821_users.js: -------------------------------------------------------------------------------- 1 | exports.up = function(knex, Promise) { 2 | return knex.schema.createTable('users', function (table) { 3 | table.increments(); 4 | table.string('first_name'); 5 | table.string('last_name'); 6 | table.string('username'); 7 | table.string('email'); 8 | table.unique('email'); 9 | table.timestamps(); 10 | }); 11 | }; 12 | 13 | exports.down = function(knex, Promise) { 14 | return knex.schema.dropTable('users'); 15 | }; 16 | -------------------------------------------------------------------------------- /javascript/koa_graphql/migrations/20160521155829_posts.js: -------------------------------------------------------------------------------- 1 | exports.up = function(knex, Promise) { 2 | return knex.schema.createTable('posts', function (table) { 3 | table.increments(); 4 | table.string('title'); 5 | table.string('body'); 6 | table.integer('user_id'); 7 | table.foreign('user_id').references('user_id'); 8 | table.index('user_id'); 9 | table.timestamps(); 10 | }); 11 | }; 12 | 13 | exports.down = function(knex, Promise) { 14 | return knex.schema.dropTable('posts'); 15 | }; 16 | -------------------------------------------------------------------------------- /javascript/koa_graphql/migrations/20160521155833_comments.js: -------------------------------------------------------------------------------- 1 | exports.up = function(knex, Promise) { 2 | return knex.schema.createTable('comments', function (table) { 3 | table.increments(); 4 | table.string('body'); 5 | table.integer('user_id'); 6 | table.integer('post_id'); 7 | table.foreign(['user_id', 'post_id']).references(['user_id', 'post_id']); 8 | table.index(['user_id', 'post_id']); 9 | table.timestamps(); 10 | }); 11 | }; 12 | 13 | exports.down = function(knex, Promise) { 14 | return knex.schema.dropTable('comments'); 15 | }; 16 | -------------------------------------------------------------------------------- /javascript/koa_graphql/models/comment.js: -------------------------------------------------------------------------------- 1 | import bookshelf from '../bookshelf'; 2 | import Post from './post'; 3 | import User from './user'; 4 | 5 | const Comment = bookshelf.Model.extend({ 6 | tableName: 'comments', 7 | hasTimestamps: ['created_at', 'updated_at'], 8 | post: function() { 9 | return this.belongsTo(Post); 10 | }, 11 | user: function() { 12 | return this.belongsTo(User); 13 | } 14 | }); 15 | 16 | export default Comment; 17 | -------------------------------------------------------------------------------- /javascript/koa_graphql/models/post.js: -------------------------------------------------------------------------------- 1 | import bookshelf from '../bookshelf'; 2 | import Comment from './comment'; 3 | import User from './user'; 4 | 5 | const Post = bookshelf.Model.extend({ 6 | tableName: 'posts', 7 | hasTimestamps: ['created_at', 'updated_at'], 8 | comments: function() { 9 | return this.hasMany(Comment); 10 | }, 11 | user: function() { 12 | return this.belongsTo(User); 13 | } 14 | }); 15 | 16 | export default Post; 17 | -------------------------------------------------------------------------------- /javascript/koa_graphql/models/user.js: -------------------------------------------------------------------------------- 1 | import bookshelf from '../bookshelf'; 2 | import Comment from './comment'; 3 | import Post from './post'; 4 | 5 | const User = bookshelf.Model.extend({ 6 | tableName: 'users', 7 | hasTimestamps: ['created_at', 'updated_at'], 8 | comments: function() { 9 | return this.hasMany(Comment); 10 | }, 11 | posts: function() { 12 | return this.hasMany(Post); 13 | } 14 | }); 15 | 16 | export default User; 17 | -------------------------------------------------------------------------------- /javascript/koa_graphql/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "koa_graphql", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "start": "nodemon app.js --exec babel-node", 7 | "test": "mocha" 8 | }, 9 | "dependencies": { 10 | "bookshelf": "^0.9.5", 11 | "co-body": "^4.0.0", 12 | "co-views": "^2.1.0", 13 | "graphql": "^0.5.0", 14 | "knex": "^0.11.3", 15 | "koa": "^1.2.0", 16 | "koa-compress": "^1.0.6", 17 | "koa-convert": "^1.2.0", 18 | "koa-graphql": "^0.5.1", 19 | "koa-logger": "^1.2.0", 20 | "koa-mount": "^1.3.0", 21 | "koa-route": "^2.4.2", 22 | "koa-session": "^3.3.1", 23 | "koa-static": "^2.0.0", 24 | "nodemon": "^1.9.2", 25 | "pg": "^4.5.5", 26 | "swig": "^1.3.2" 27 | }, 28 | "devDependencies": { 29 | "babel-cli": "^6.9.0", 30 | "babel-core": "^6.9.0", 31 | "babel-plugin-transform-async-to-generator": "^6.8.0", 32 | "babel-preset-es2015": "^6.9.0", 33 | "babel-preset-es2015-node5": "^1.2.0", 34 | "babel-preset-stage-0": "^6.5.0", 35 | "mocha": "^2.4.5", 36 | "supertest": "^0.12.1" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /javascript/koa_graphql/seeds/comments.js: -------------------------------------------------------------------------------- 1 | 2 | exports.seed = function(knex, Promise) { 3 | return Promise.join( 4 | // Deletes ALL existing entries 5 | knex('comments').del(), 6 | 7 | // Inserts seed entries 8 | knex('comments').insert({ 9 | id: 1, 10 | body: 'First post comment', 11 | user_id: 1, 12 | post_id: 1, 13 | created_at: new Date((new Date()).getTime()), 14 | updated_at: new Date((new Date()).getTime()) 15 | }), 16 | knex('comments').insert({ 17 | id: 2, 18 | body: 'Second post comment', 19 | user_id: 2, 20 | post_id: 2, 21 | created_at: new Date((new Date()).getTime()), 22 | updated_at: new Date((new Date()).getTime()) 23 | }), 24 | knex('comments').insert({ 25 | id: 3, 26 | body: 'Third post comment', 27 | user_id: 3, 28 | post_id: 3, 29 | created_at: new Date((new Date()).getTime()), 30 | updated_at: new Date((new Date()).getTime()) 31 | }) 32 | ); 33 | }; 34 | -------------------------------------------------------------------------------- /javascript/koa_graphql/seeds/posts.js: -------------------------------------------------------------------------------- 1 | 2 | exports.seed = function(knex, Promise) { 3 | return Promise.join( 4 | // Deletes ALL existing entries 5 | knex('posts').del(), 6 | 7 | // Inserts seed entries 8 | knex('posts').insert({ 9 | id: 1, 10 | title: 'First post title', 11 | body: 'First post body', 12 | user_id: 1, 13 | created_at: new Date((new Date()).getTime()), 14 | updated_at: new Date((new Date()).getTime()) 15 | }), 16 | knex('posts').insert({ 17 | id: 2, 18 | title: 'Second post title', 19 | body: 'Second post body', 20 | user_id: 2, 21 | created_at: new Date((new Date()).getTime()), 22 | updated_at: new Date((new Date()).getTime()) 23 | }), 24 | knex('posts').insert({ 25 | id: 3, 26 | title: 'Third post title', 27 | body: 'Third post body', 28 | user_id: 3, 29 | created_at: new Date((new Date()).getTime()), 30 | updated_at: new Date((new Date()).getTime()) 31 | }) 32 | ); 33 | }; 34 | -------------------------------------------------------------------------------- /javascript/koa_graphql/seeds/users.js: -------------------------------------------------------------------------------- 1 | 2 | exports.seed = function(knex, Promise) { 3 | return Promise.join( 4 | // Deletes ALL existing entries 5 | knex('users').del(), 6 | 7 | // Inserts seed entries 8 | knex('users').insert({ 9 | id: 1, 10 | first_name: 'John', 11 | last_name: 'Doe', 12 | username: 'johndoe', 13 | email: 'john@doe.com', 14 | created_at: new Date((new Date()).getTime()), 15 | updated_at: new Date((new Date()).getTime()) 16 | }), 17 | knex('users').insert({ 18 | id: 2, 19 | first_name: 'Maggie', 20 | last_name: 'Turner', 21 | username: 'maggie', 22 | email: 'maggie@turner.com', 23 | created_at: new Date((new Date()).getTime()), 24 | updated_at: new Date((new Date()).getTime()) 25 | }), 26 | knex('users').insert({ 27 | id: 3, 28 | first_name: 'Sam', 29 | last_name: 'Smith', 30 | username: 'sam', 31 | email: 'sam@smith.com', 32 | created_at: new Date((new Date()).getTime()), 33 | updated_at: new Date((new Date()).getTime()) 34 | }) 35 | ); 36 | }; 37 | -------------------------------------------------------------------------------- /javascript/meteor_graphql/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /javascript/meteor_graphql/.meteor/.finished-upgraders: -------------------------------------------------------------------------------- 1 | # This file contains information which helps Meteor properly upgrade your 2 | # app when you run 'meteor update'. You should check it into version control 3 | # with your project. 4 | 5 | notices-for-0.9.0 6 | notices-for-0.9.1 7 | 0.9.4-platform-file 8 | notices-for-facebook-graph-api-2 9 | 1.2.0-standard-minifiers-package 10 | 1.2.0-meteor-platform-split 11 | 1.2.0-cordova-changes 12 | 1.2.0-breaking-changes 13 | 1.3.0-split-minifiers-package 14 | -------------------------------------------------------------------------------- /javascript/meteor_graphql/.meteor/.gitignore: -------------------------------------------------------------------------------- 1 | local 2 | -------------------------------------------------------------------------------- /javascript/meteor_graphql/.meteor/.id: -------------------------------------------------------------------------------- 1 | # This file contains a token that is unique to your project. 2 | # Check it into your repository along with the rest of this directory. 3 | # It can be used for purposes such as: 4 | # - ensuring you don't accidentally deploy one app on top of another 5 | # - providing package authors with aggregated statistics 6 | 7 | 183m4ka1p4y3rwjf3bvb 8 | -------------------------------------------------------------------------------- /javascript/meteor_graphql/.meteor/packages: -------------------------------------------------------------------------------- 1 | # Meteor packages used by this project, one per line. 2 | # Check this file (and the other files in this directory) into your repository. 3 | # 4 | # 'meteor add' and 'meteor remove' will edit this file for you, 5 | # but you can also edit it by hand. 6 | 7 | meteor-base # Packages every Meteor app needs to have 8 | mobile-experience # Packages for a great mobile UX 9 | mongo # The database Meteor supports right now 10 | blaze-html-templates # Compile .html files into Meteor Blaze views 11 | reactive-var # Reactive variable for tracker 12 | jquery # Helpful client-side library 13 | tracker # Meteor's client-side reactive programming library 14 | 15 | standard-minifier-css # CSS minifier run for production mode 16 | standard-minifier-js # JS minifier run for production mode 17 | es5-shim # ECMAScript 5 compatibility for older browsers. 18 | ecmascript # Enable ECMAScript2015+ syntax in app code 19 | 20 | autopublish # Publish all data to the clients (for prototyping) 21 | insecure # Allow all DB writes from clients (for prototyping) 22 | -------------------------------------------------------------------------------- /javascript/meteor_graphql/.meteor/platforms: -------------------------------------------------------------------------------- 1 | server 2 | browser 3 | -------------------------------------------------------------------------------- /javascript/meteor_graphql/.meteor/release: -------------------------------------------------------------------------------- 1 | METEOR@1.3.2.4 2 | -------------------------------------------------------------------------------- /javascript/meteor_graphql/README.md: -------------------------------------------------------------------------------- 1 | # Meteor GraphQL Server 2 | 3 | ## Getting started locally 4 | 5 | ```bash 6 | git clone repo 7 | cd express_graphql 8 | npm install 9 | 10 | meteor npm install 11 | meteor 12 | ``` 13 | 14 | [Visit browser](http://localhost:3000/graphql) 15 | 16 | ### Supported API Queries 17 | 18 | ``` 19 | { 20 | allPosts { 21 | _id, 22 | title 23 | body 24 | user { 25 | _id 26 | first_name 27 | } 28 | comments{ 29 | _id 30 | body 31 | } 32 | 33 | } 34 | } 35 | ``` 36 | 37 | ``` 38 | { 39 | post(id: "qEsSyu5wHec6e67AW") { 40 | _id, 41 | title 42 | body 43 | user { 44 | _id 45 | first_name 46 | } 47 | comments{ 48 | _id 49 | body 50 | } 51 | 52 | } 53 | } 54 | ``` 55 | 56 | ### Field aliases 57 | 58 | ``` 59 | { 60 | posts: allPosts { 61 | _id 62 | body 63 | comments { 64 | _id 65 | body 66 | user { 67 | first_name 68 | last_name 69 | } 70 | } 71 | user { 72 | first_name 73 | last_name 74 | } 75 | } 76 | } 77 | ``` 78 | -------------------------------------------------------------------------------- /javascript/meteor_graphql/client/main.html: -------------------------------------------------------------------------------- 1 | 2 | This is main page 3 | Go to editor 4 | 5 | -------------------------------------------------------------------------------- /javascript/meteor_graphql/imports/collections/comments.js: -------------------------------------------------------------------------------- 1 | import { Mongo } from 'meteor/mongo'; 2 | export const Comments = new Mongo.Collection('comments'); 3 | -------------------------------------------------------------------------------- /javascript/meteor_graphql/imports/collections/posts.js: -------------------------------------------------------------------------------- 1 | import { Mongo } from 'meteor/mongo'; 2 | export const Posts = new Mongo.Collection('posts'); 3 | -------------------------------------------------------------------------------- /javascript/meteor_graphql/imports/collections/schemas.js: -------------------------------------------------------------------------------- 1 | import Posts from './posts'; 2 | import Comments from './comments'; 3 | import Users from './users'; 4 | 5 | let Schema = {}; 6 | 7 | Schema.User = new SimpleSchema({ 8 | name: { 9 | first_name: String, 10 | last_name: String, 11 | username: String, 12 | email: String 13 | }, 14 | }); 15 | 16 | Schema.Post = new SimpleSchema({ 17 | title: { 18 | type: String, 19 | max: 140 20 | }, 21 | body: { 22 | type: String, 23 | max: 2000 24 | }, 25 | user: { 26 | type: Schema.User, 27 | }, 28 | }); 29 | 30 | Schema.Comment = new SimpleSchema({ 31 | body: { 32 | type: String, 33 | max: 2000 34 | }, 35 | user: { 36 | type: Schema.User, 37 | }, 38 | post: { 39 | type: Schema.Post, 40 | }, 41 | }); 42 | 43 | Users.attachSchema(Schema.User); 44 | Posts.attachSchema(Schema.Post); 45 | Comments.attachSchema(Schema.Comment); 46 | -------------------------------------------------------------------------------- /javascript/meteor_graphql/imports/collections/users.js: -------------------------------------------------------------------------------- 1 | import { Mongo } from 'meteor/mongo'; 2 | export const Users = new Mongo.Collection('users'); 3 | -------------------------------------------------------------------------------- /javascript/meteor_graphql/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "meteor_graphql", 3 | "private": true, 4 | "scripts": { 5 | "start": "meteor run" 6 | }, 7 | "dependencies": { 8 | "apollo-client": "^0.3.13", 9 | "apollo-server": "^0.1.3", 10 | "express": "^4.13.4", 11 | "graphql": "^0.6.0", 12 | "graphql-tools": "^0.6.0", 13 | "http-proxy-middleware": "^0.15.2", 14 | "invariant": "^2.2.1", 15 | "meteor-node-stubs": "~0.2.0", 16 | "react": "^15.1.0", 17 | "react-addons-pure-render-mixin": "^15.1.0", 18 | "react-apollo": "^0.3.8", 19 | "react-dom": "^15.1.0", 20 | "tracker-component": "^1.3.21" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /javascript/meteor_graphql/server/fixtures/users.js: -------------------------------------------------------------------------------- 1 | const UsersSeed = [ 2 | { 3 | first_name: 'John', 4 | last_name: 'Doe', 5 | username: 'johndoe', 6 | email: 'johndoe@doe.com' 7 | }, 8 | { 9 | first_name: 'Maggie', 10 | last_name: 'Turner', 11 | username: 'maggie', 12 | email: 'maggie@turner.com' 13 | } 14 | ]; 15 | 16 | export default UsersSeed; 17 | -------------------------------------------------------------------------------- /javascript/meteor_graphql/server/main.js: -------------------------------------------------------------------------------- 1 | import { Meteor } from 'meteor/meteor'; 2 | import { apolloServer } from 'apollo-server'; 3 | import express from 'express'; 4 | import proxyMiddleware from 'http-proxy-middleware'; 5 | import { check } from 'meteor/check'; 6 | import { Comments } from '../imports/collections/comments'; 7 | import { Posts } from '../imports/collections/posts'; 8 | 9 | import { schema, resolvers } from '/imports/api/schema'; 10 | 11 | const GRAPHQL_PORT = 4000; 12 | 13 | const graphQLServer = express(); 14 | 15 | graphQLServer.use('/', apolloServer(async (req) => { 16 | return { 17 | graphiql: true, 18 | pretty: true, 19 | schema, 20 | resolvers, 21 | }; 22 | })); 23 | 24 | graphQLServer.listen(GRAPHQL_PORT, () => console.log( 25 | `GraphQL Server is now running on http://localhost:${GRAPHQL_PORT}` 26 | )); 27 | 28 | WebApp.rawConnectHandlers.use(proxyMiddleware(`http://localhost:${GRAPHQL_PORT}/graphql`)); 29 | 30 | Meteor.startup(function () { 31 | Posts._ensureIndex({ "user": 1}); 32 | Comments._ensureIndex({ "post": 1}); 33 | Comments._ensureIndex({ "user": 1}); 34 | }); 35 | -------------------------------------------------------------------------------- /javascript/meteor_graphql/server/publications/posts.js: -------------------------------------------------------------------------------- 1 | import { Posts } from '../../imports/collections/posts'; 2 | -------------------------------------------------------------------------------- /javascript/meteor_graphql/server/seeds.js: -------------------------------------------------------------------------------- 1 | import { Posts } from '../imports/collections/posts'; 2 | import { Comments } from '../imports/collections/comments'; 3 | import { Users } from '../imports/collections/users'; 4 | 5 | import UsersSeed from './fixtures/users'; 6 | 7 | Meteor.methods({ 8 | 'Database.seed': function() { 9 | _.forEach(UsersSeed, function(user) { 10 | let userObj = Users.insert(user, function(error, result) { 11 | console.log('Users added', result); 12 | }); 13 | 14 | let postObject = Posts.insert({ 15 | title: 'this is post title', 16 | body: 'this is post body', 17 | user: userObj, 18 | }, function(error, result) { 19 | const Comment = { 20 | post: postObject, 21 | user: userObj, 22 | body: 'this is a comment for this post', 23 | }; 24 | Comments.insert(Comment, function(error, result) { 25 | console.log('Comment added for', postObject); 26 | }); 27 | }); 28 | }); 29 | } 30 | }); 31 | -------------------------------------------------------------------------------- /php/README.md: -------------------------------------------------------------------------------- 1 | # PHP based web frameworks 2 | 3 | A set of GraphQL server implementation on popular PHP web frameworks. 4 | 5 | ## Frameworks 6 | * Laravel 7 | 8 | ```bash 9 | $ brew update 10 | $ brew install homebrew/php/php70 --with-apache --with-mysql --with-postgresql --with-intl 11 | $ php -v 12 | PHP 7.0.7 (cli) (built: Jun 6 2016 18:09:34) ( NTS ) 13 | Copyright (c) 1997-2016 The PHP Group 14 | Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologie 15 | ``` 16 | 17 | Then, follow the example readme to setup application locally. 18 | -------------------------------------------------------------------------------- /php/laravel_graphql/.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.css linguist-vendored 3 | *.scss linguist-vendored 4 | -------------------------------------------------------------------------------- /php/laravel_graphql/.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | /node_modules 3 | /public/storage 4 | Homestead.yaml 5 | Homestead.json 6 | .env 7 | -------------------------------------------------------------------------------- /php/laravel_graphql/app/Comment.php: -------------------------------------------------------------------------------- 1 | belongsTo('App\User'); 15 | } 16 | 17 | public function post() { 18 | return $this->belongsTo('App\Post'); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /php/laravel_graphql/app/Console/Commands/Inspire.php: -------------------------------------------------------------------------------- 1 | comment(PHP_EOL.Inspiring::quote().PHP_EOL); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /php/laravel_graphql/app/Console/Kernel.php: -------------------------------------------------------------------------------- 1 | command('inspire') 28 | // ->hourly(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /php/laravel_graphql/app/Events/Event.php: -------------------------------------------------------------------------------- 1 | 'CommentsQuery' 11 | ]; 12 | 13 | public function type() 14 | { 15 | return Type::listOf(GraphQL::type('comment')); 16 | } 17 | 18 | public function resolve($root, $args) 19 | { 20 | return $root->comments; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /php/laravel_graphql/app/GraphQL/Query/PostQuery.php: -------------------------------------------------------------------------------- 1 | 'PostQuery' 11 | ]; 12 | 13 | public function type() 14 | { 15 | return GraphQL::type('post'); 16 | } 17 | 18 | public function resolve($root, $args) 19 | { 20 | return $root->post; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /php/laravel_graphql/app/GraphQL/Query/PostsQuery.php: -------------------------------------------------------------------------------- 1 | 'PostsQuery' 12 | ]; 13 | 14 | public function type() 15 | { 16 | return Type::listOf(GraphQL::type('post')); 17 | } 18 | 19 | public function args() 20 | { 21 | return [ 22 | 'id' => ['name' => 'id', 'type' => Type::Int()], 23 | ]; 24 | } 25 | 26 | public function resolve($root, $args) 27 | { 28 | if(isset($args['id'])) 29 | { 30 | return Post::where('id' , $args['id'])->with('user', 'comments')->get(); 31 | } 32 | else 33 | { 34 | $posts = Post::query(); 35 | return $posts->with('user', 'comments')->get(); 36 | } 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /php/laravel_graphql/app/GraphQL/Query/UserQuery.php: -------------------------------------------------------------------------------- 1 | 'UserQuery' 11 | ]; 12 | 13 | public function type() 14 | { 15 | return Type::nonNull(GraphQL::type('user')); 16 | } 17 | 18 | public function resolve($root, $args) 19 | { 20 | return $root->user; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /php/laravel_graphql/app/GraphQL/Query/UsersQuery.php: -------------------------------------------------------------------------------- 1 | 'Users query' 12 | ]; 13 | 14 | public function type() 15 | { 16 | return Type::listOf(GraphQL::type('user')); 17 | } 18 | 19 | public function args() 20 | { 21 | return [ 22 | 'id' => ['name' => 'id', 'type' => Type::string()] 23 | ]; 24 | } 25 | 26 | public function resolve($root, $args) 27 | { 28 | if(isset($args['id'])) 29 | { 30 | return User::where('id' , $args['id'])->get(); 31 | } 32 | else if(isset($args['email'])) 33 | { 34 | return User::where('email', $args['email'])->get(); 35 | } 36 | else 37 | { 38 | return User::all(); 39 | } 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /php/laravel_graphql/app/GraphQL/Type/CommentType.php: -------------------------------------------------------------------------------- 1 | 'Comment', 10 | 'description' => 'A Comment' 11 | ]; 12 | 13 | public function fields() 14 | { 15 | return [ 16 | 'id' => [ 17 | 'type' => Type::nonNull(Type::string()), 18 | 'description' => 'The id of the comment' 19 | ], 20 | 'body' => [ 21 | 'type' => Type::nonNull(Type::string()), 22 | 'description' => 'The body of the comment' 23 | ], 24 | 'user' => \App\GraphQL\Query\UserQuery::class, 25 | ]; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /php/laravel_graphql/app/GraphQL/Type/PostType.php: -------------------------------------------------------------------------------- 1 | 'Post', 10 | 'description' => 'A post' 11 | ]; 12 | 13 | public function fields() 14 | { 15 | return [ 16 | 'id' => [ 17 | 'type' => Type::nonNull(Type::string()), 18 | 'description' => 'The id of the post' 19 | ], 20 | 'title' => [ 21 | 'type' => Type::nonNull(Type::string()), 22 | 'description' => 'The title of the post' 23 | ], 24 | 'body' => [ 25 | 'type' => Type::nonNull(Type::string()), 26 | 'description' => 'The body of the post' 27 | ], 28 | 'user' => \App\GraphQL\Query\UserQuery::class, 29 | 'comments' => \App\GraphQL\Query\CommentsQuery::class, 30 | ]; 31 | } 32 | 33 | public function resolve($root, $args, ResolveInfo $info) 34 | { 35 | $posts = User::query(); 36 | 37 | $posts->with('user', 'comments'); 38 | 39 | return $posts->get(); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /php/laravel_graphql/app/GraphQL/Type/UserType.php: -------------------------------------------------------------------------------- 1 | 'User', 11 | 'description' => 'A user' 12 | ]; 13 | 14 | public function fields() 15 | { 16 | return [ 17 | 'id' => [ 18 | 'type' => Type::nonNull(Type::string()), 19 | 'description' => 'The id of the user' 20 | ], 21 | 'first_name' => [ 22 | 'type' => Type::nonNull(Type::string()), 23 | 'description' => 'The first name of the user' 24 | ], 25 | 'last_name' => [ 26 | 'type' => Type::nonNull(Type::string()), 27 | 'description' => 'The last name of the user' 28 | ], 29 | 'email' => [ 30 | 'type' => Type::string(), 31 | 'description' => 'The email of user' 32 | ], 33 | 'username' => [ 34 | 'type' => Type::nonNull(Type::string()), 35 | 'description' => 'The username of the user' 36 | ], 37 | ]; 38 | } 39 | 40 | protected function resolveEmailField($root, $args) 41 | { 42 | return strtolower($root->email); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /php/laravel_graphql/app/GraphQL/mutation/UpdateUserPasswordMutation.php: -------------------------------------------------------------------------------- 1 | 'UpdateUserPassword' 12 | ]; 13 | 14 | public function type() 15 | { 16 | return GraphQL::type('user'); 17 | } 18 | 19 | public function args() 20 | { 21 | return [ 22 | 'id' => ['name' => 'id', 'type' => Type::nonNull(Type::string())], 23 | 'password' => ['name' => 'password', 'type' => Type::nonNull(Type::string())] 24 | ]; 25 | } 26 | 27 | public function resolve($root, $args) 28 | { 29 | $user = User::find($args['id']); 30 | if(!$user) 31 | { 32 | return null; 33 | } 34 | 35 | $user->password = bcrypt($args['password']); 36 | $user->save(); 37 | return $user; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /php/laravel_graphql/app/Http/Controllers/Auth/PasswordController.php: -------------------------------------------------------------------------------- 1 | middleware('guest'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /php/laravel_graphql/app/Http/Controllers/Controller.php: -------------------------------------------------------------------------------- 1 | $token]); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /php/laravel_graphql/app/Http/Middleware/Authenticate.php: -------------------------------------------------------------------------------- 1 | guest()) { 21 | if ($request->ajax() || $request->wantsJson()) { 22 | return response('Unauthorized.', 401); 23 | } else { 24 | return redirect()->guest('login'); 25 | } 26 | } 27 | 28 | return $next($request); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /php/laravel_graphql/app/Http/Middleware/EncryptCookies.php: -------------------------------------------------------------------------------- 1 | check()) { 21 | return redirect('/'); 22 | } 23 | 24 | return $next($request); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /php/laravel_graphql/app/Http/Middleware/VerifyCsrfToken.php: -------------------------------------------------------------------------------- 1 | 'graphql.query', 18 | 'uses' => '\Folklore\GraphQL\GraphQLController@query' 19 | ))->middleware(['jwt.auth']); 20 | -------------------------------------------------------------------------------- /php/laravel_graphql/app/Jobs/Job.php: -------------------------------------------------------------------------------- 1 | belongsTo('App\User'); 21 | } 22 | 23 | public function comments() 24 | { 25 | return $this->hasMany('App\Comment'); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /php/laravel_graphql/app/Providers/AppServiceProvider.php: -------------------------------------------------------------------------------- 1 | 'App\Policies\ModelPolicy', 17 | ]; 18 | 19 | /** 20 | * Register any application authentication / authorization services. 21 | * 22 | * @param \Illuminate\Contracts\Auth\Access\Gate $gate 23 | * @return void 24 | */ 25 | public function boot(GateContract $gate) 26 | { 27 | $this->registerPolicies($gate); 28 | 29 | // 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /php/laravel_graphql/app/Providers/EventServiceProvider.php: -------------------------------------------------------------------------------- 1 | [ 17 | 'App\Listeners\EventListener', 18 | ], 19 | ]; 20 | 21 | /** 22 | * Register any other events for your application. 23 | * 24 | * @param \Illuminate\Contracts\Events\Dispatcher $events 25 | * @return void 26 | */ 27 | public function boot(DispatcherContract $events) 28 | { 29 | parent::boot($events); 30 | 31 | // 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /php/laravel_graphql/app/User.php: -------------------------------------------------------------------------------- 1 | hasMany('App\Comment'); 30 | } 31 | 32 | public function posts() 33 | { 34 | return $this->hasMany('App\Post'); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /php/laravel_graphql/bootstrap/autoload.php: -------------------------------------------------------------------------------- 1 | [ 17 | // 18 | ], 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Compiled File Providers 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may list service providers which define a "compiles" function 26 | | that returns additional files that should be compiled, providing an 27 | | easy way to get common files from any packages you are utilizing. 28 | | 29 | */ 30 | 31 | 'providers' => [ 32 | // 33 | ], 34 | 35 | ]; 36 | -------------------------------------------------------------------------------- /php/laravel_graphql/config/services.php: -------------------------------------------------------------------------------- 1 | [ 18 | 'domain' => env('MAILGUN_DOMAIN'), 19 | 'secret' => env('MAILGUN_SECRET'), 20 | ], 21 | 22 | 'ses' => [ 23 | 'key' => env('SES_KEY'), 24 | 'secret' => env('SES_SECRET'), 25 | 'region' => 'us-east-1', 26 | ], 27 | 28 | 'sparkpost' => [ 29 | 'secret' => env('SPARKPOST_SECRET'), 30 | ], 31 | 32 | 'stripe' => [ 33 | 'model' => App\User::class, 34 | 'key' => env('STRIPE_KEY'), 35 | 'secret' => env('STRIPE_SECRET'), 36 | ], 37 | 38 | ]; 39 | -------------------------------------------------------------------------------- /php/laravel_graphql/config/view.php: -------------------------------------------------------------------------------- 1 | [ 17 | realpath(base_path('resources/views')), 18 | ], 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Compiled View Path 23 | |-------------------------------------------------------------------------- 24 | | 25 | | This option determines where all the compiled Blade templates will be 26 | | stored for your application. Typically, this is within the storage 27 | | directory. However, as usual, you are free to change this value. 28 | | 29 | */ 30 | 31 | 'compiled' => realpath(storage_path('framework/views')), 32 | 33 | ]; 34 | -------------------------------------------------------------------------------- /php/laravel_graphql/database/.gitignore: -------------------------------------------------------------------------------- 1 | *.sqlite 2 | -------------------------------------------------------------------------------- /php/laravel_graphql/database/migrations/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /php/laravel_graphql/database/migrations/2014_10_12_000000_create_users_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 17 | $table->string('name'); 18 | $table->string('first_name'); 19 | $table->string('last_name'); 20 | $table->string('username')->unique(); 21 | $table->string('email')->unique(); 22 | $table->string('password'); 23 | $table->rememberToken(); 24 | $table->timestamps(); 25 | }); 26 | } 27 | 28 | /** 29 | * Reverse the migrations. 30 | * 31 | * @return void 32 | */ 33 | public function down() 34 | { 35 | Schema::drop('users'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /php/laravel_graphql/database/migrations/2014_10_12_100000_create_password_resets_table.php: -------------------------------------------------------------------------------- 1 | string('email')->index(); 17 | $table->string('token')->index(); 18 | $table->timestamp('created_at'); 19 | }); 20 | } 21 | 22 | /** 23 | * Reverse the migrations. 24 | * 25 | * @return void 26 | */ 27 | public function down() 28 | { 29 | Schema::drop('password_resets'); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /php/laravel_graphql/database/migrations/2016_05_31_071858_create_posts_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 17 | $table->string('title'); 18 | $table->longText('body'); 19 | $table->integer('user_id'); 20 | $table->foreign('user_id')->references('id')->on('users'); 21 | $table->timestamps(); 22 | }); 23 | } 24 | 25 | /** 26 | * Reverse the migrations. 27 | * 28 | * @return void 29 | */ 30 | public function down() 31 | { 32 | Schema::drop('posts'); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /php/laravel_graphql/database/migrations/2016_05_31_071904_create_comments_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 17 | $table->longText('body'); 18 | $table->integer('user_id'); 19 | $table->integer('post_id'); 20 | $table->foreign('user_id')->references('id')->on('users'); 21 | $table->foreign('post_id')->references('id')->on('posts'); 22 | $table->timestamps(); 23 | }); 24 | } 25 | 26 | /** 27 | * Reverse the migrations. 28 | * 29 | * @return void 30 | */ 31 | public function down() 32 | { 33 | Schema::drop('comments'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /php/laravel_graphql/database/seeds/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /php/laravel_graphql/database/seeds/CommentsTableSeeder.php: -------------------------------------------------------------------------------- 1 | create(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /php/laravel_graphql/database/seeds/DatabaseSeeder.php: -------------------------------------------------------------------------------- 1 | call(UsersTableSeeder::class); 15 | $this->call(PostsTableSeeder::class); 16 | $this->call(CommentsTableSeeder::class); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /php/laravel_graphql/database/seeds/PostsTableSeeder.php: -------------------------------------------------------------------------------- 1 | create(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /php/laravel_graphql/database/seeds/UsersTableSeeder.php: -------------------------------------------------------------------------------- 1 | create(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /php/laravel_graphql/gulpfile.js: -------------------------------------------------------------------------------- 1 | var elixir = require('laravel-elixir'); 2 | 3 | /* 4 | |-------------------------------------------------------------------------- 5 | | Elixir Asset Management 6 | |-------------------------------------------------------------------------- 7 | | 8 | | Elixir provides a clean, fluent API for defining some basic Gulp tasks 9 | | for your Laravel application. By default, we are compiling the Sass 10 | | file for our application, as well as publishing vendor resources. 11 | | 12 | */ 13 | 14 | elixir(function(mix) { 15 | mix.sass('app.scss'); 16 | }); 17 | -------------------------------------------------------------------------------- /php/laravel_graphql/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "prod": "gulp --production", 5 | "dev": "gulp watch" 6 | }, 7 | "devDependencies": { 8 | "gulp": "^3.9.1", 9 | "laravel-elixir": "^5.0.0", 10 | "bootstrap-sass": "^3.0.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /php/laravel_graphql/phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | ./tests 14 | 15 | 16 | 17 | 18 | ./app 19 | 20 | ./app/Http/routes.php 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /php/laravel_graphql/public/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | 3 | Options -MultiViews 4 | 5 | 6 | RewriteEngine On 7 | 8 | # Redirect Trailing Slashes If Not A Folder... 9 | RewriteCond %{REQUEST_FILENAME} !-d 10 | RewriteRule ^(.*)/$ /$1 [L,R=301] 11 | 12 | # Handle Front Controller... 13 | RewriteCond %{REQUEST_FILENAME} !-d 14 | RewriteCond %{REQUEST_FILENAME} !-f 15 | RewriteRule ^ index.php [L] 16 | 17 | # Handle Authorization Header 18 | RewriteCond %{HTTP:Authorization} . 19 | RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] 20 | 21 | -------------------------------------------------------------------------------- /php/laravel_graphql/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/php/laravel_graphql/public/favicon.ico -------------------------------------------------------------------------------- /php/laravel_graphql/public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /php/laravel_graphql/public/web.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /php/laravel_graphql/readme.md: -------------------------------------------------------------------------------- 1 | # Laravel Graphql Server 2 | 3 | ### Running locally 4 | 5 | ``` bash 6 | git clone repo 7 | cd repo 8 | createdb laravel_graphql 9 | php artisan migrate 10 | php artisan db:seed 11 | php artisan serve 12 | ``` 13 | [Visit browser](http://localhost:8000/) 14 | 15 | # Features 16 | * Graphql API 17 | * CSRF and SESSION 18 | * TOKEN AUTH 19 | 20 | ### Supported API queries 21 | 22 | ``` 23 | { 24 | posts { 25 | id, 26 | title, 27 | body, 28 | comments { 29 | id, 30 | body 31 | } 32 | user { 33 | id, 34 | first_name 35 | } 36 | } 37 | } 38 | ``` 39 | ``` 40 | { 41 | posts(id: 1) { 42 | id, 43 | title, 44 | body, 45 | comments { 46 | id, 47 | body 48 | } 49 | user { 50 | id, 51 | first_name 52 | } 53 | } 54 | } 55 | ``` 56 | 57 | ``` 58 | { 59 | posts(id: 1) { 60 | id, 61 | title, 62 | body, 63 | comments { 64 | id, 65 | body 66 | user { 67 | id 68 | first_name 69 | } 70 | } 71 | user { 72 | id, 73 | first_name 74 | } 75 | } 76 | } 77 | ``` 78 | -------------------------------------------------------------------------------- /php/laravel_graphql/resources/assets/sass/app.scss: -------------------------------------------------------------------------------- 1 | // @import "node_modules/bootstrap-sass/assets/stylesheets/bootstrap"; 2 | 3 | -------------------------------------------------------------------------------- /php/laravel_graphql/resources/lang/en/auth.php: -------------------------------------------------------------------------------- 1 | 'These credentials do not match our records.', 17 | 'throttle' => 'Too many login attempts. Please try again in :seconds seconds.', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /php/laravel_graphql/resources/lang/en/pagination.php: -------------------------------------------------------------------------------- 1 | '« Previous', 17 | 'next' => 'Next »', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /php/laravel_graphql/resources/lang/en/passwords.php: -------------------------------------------------------------------------------- 1 | 'Passwords must be at least six characters and match the confirmation.', 17 | 'reset' => 'Your password has been reset!', 18 | 'sent' => 'We have e-mailed your password reset link!', 19 | 'token' => 'This password reset token is invalid.', 20 | 'user' => "We can't find a user with that e-mail address.", 21 | 22 | ]; 23 | -------------------------------------------------------------------------------- /php/laravel_graphql/resources/views/vendor/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /php/laravel_graphql/server.php: -------------------------------------------------------------------------------- 1 | 8 | */ 9 | 10 | $uri = urldecode( 11 | parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) 12 | ); 13 | 14 | // This file allows us to emulate Apache's "mod_rewrite" functionality from the 15 | // built-in PHP web server. This provides a convenient way to test a Laravel 16 | // application without having installed a "real" web server software here. 17 | if ($uri !== '/' && file_exists(__DIR__.'/public'.$uri)) { 18 | return false; 19 | } 20 | 21 | require_once __DIR__.'/public/index.php'; 22 | -------------------------------------------------------------------------------- /php/laravel_graphql/storage/app/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !public/ 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /php/laravel_graphql/storage/app/public/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /php/laravel_graphql/storage/framework/.gitignore: -------------------------------------------------------------------------------- 1 | config.php 2 | routes.php 3 | schedule-* 4 | compiled.php 5 | services.json 6 | events.scanned.php 7 | routes.scanned.php 8 | down 9 | -------------------------------------------------------------------------------- /php/laravel_graphql/storage/framework/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /php/laravel_graphql/storage/framework/sessions/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /php/laravel_graphql/storage/framework/views/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /php/laravel_graphql/storage/logs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /python/README.md: -------------------------------------------------------------------------------- 1 | # Python based web frameworks 2 | 3 | A set of GraphQL server implementation on popular Python web frameworks. 4 | 5 | Make sure `Python >= 3.5` and `pip` is installed on your machine. 6 | 7 | ``` bash 8 | $ brew update 9 | $ brew install pyenv 10 | $ pyenv install 3.5.1 11 | $ sudo easy_install pip 12 | $ pyenv local 3.5.1 # Setup locally as standard python version 13 | ``` 14 | 15 | Then, follow the example readme to setup application locally. 16 | -------------------------------------------------------------------------------- /python/django_graphql/README.md: -------------------------------------------------------------------------------- 1 | # Flask Graphql 2 | 3 | Make sure `Python >= 3.5` and `pip` is installed on your machine. 4 | 5 | ```bash 6 | git clone repo 7 | cd folder 8 | sudo -H pip install -r requirements.md 9 | python ./manage.py loaddata seed 10 | python manage.py runserver 11 | ``` 12 | 13 | [Visit browser](http://127.0.0.1:8000/) 14 | 15 | ### Supported API Queries 16 | 17 | ``` 18 | { 19 | allPosts { 20 | id, 21 | title 22 | body 23 | user { 24 | id 25 | firstName 26 | } 27 | comments{ 28 | id 29 | body 30 | user{ 31 | id 32 | firstName 33 | } 34 | } 35 | 36 | } 37 | } 38 | ``` 39 | 40 | ``` 41 | { 42 | post(id: 1) { 43 | id, 44 | title 45 | body 46 | user { 47 | id 48 | firstName 49 | } 50 | comments{ 51 | id 52 | body 53 | user{ 54 | id 55 | firstName 56 | } 57 | } 58 | 59 | } 60 | } 61 | ``` 62 | 63 | ``` 64 | { 65 | user(id: 1) { 66 | id, 67 | firstName 68 | posts{ 69 | id 70 | body 71 | user{ 72 | id 73 | firstName 74 | } 75 | } 76 | 77 | } 78 | } 79 | ``` 80 | -------------------------------------------------------------------------------- /python/django_graphql/blog/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/python/django_graphql/blog/__init__.py -------------------------------------------------------------------------------- /python/django_graphql/blog/__init__.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/python/django_graphql/blog/__init__.pyc -------------------------------------------------------------------------------- /python/django_graphql/blog/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /python/django_graphql/blog/admin.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/python/django_graphql/blog/admin.pyc -------------------------------------------------------------------------------- /python/django_graphql/blog/apps.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | 3 | from django.apps import AppConfig 4 | 5 | 6 | class BlogConfig(AppConfig): 7 | name = 'blog' 8 | -------------------------------------------------------------------------------- /python/django_graphql/blog/migrations/0001_initial.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/python/django_graphql/blog/migrations/0001_initial.pyc -------------------------------------------------------------------------------- /python/django_graphql/blog/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/python/django_graphql/blog/migrations/__init__.py -------------------------------------------------------------------------------- /python/django_graphql/blog/migrations/__init__.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/python/django_graphql/blog/migrations/__init__.pyc -------------------------------------------------------------------------------- /python/django_graphql/blog/models.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | 3 | from django.db import models 4 | from django.contrib.auth.models import User 5 | 6 | 7 | class Post(models.Model): 8 | user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='posts') 9 | title = models.CharField(max_length=200) 10 | body = models.CharField(max_length=200) 11 | published_date = models.DateTimeField('date published') 12 | 13 | class Comment(models.Model): 14 | user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='comments') 15 | post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments') 16 | body = models.CharField(max_length=200) 17 | -------------------------------------------------------------------------------- /python/django_graphql/blog/models.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/python/django_graphql/blog/models.pyc -------------------------------------------------------------------------------- /python/django_graphql/blog/schema.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/python/django_graphql/blog/schema.pyc -------------------------------------------------------------------------------- /python/django_graphql/blog/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /python/django_graphql/blog/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url 2 | 3 | from . import views 4 | 5 | urlpatterns = [ 6 | url(r'^$', views.index, name='index'), 7 | ] 8 | -------------------------------------------------------------------------------- /python/django_graphql/blog/urls.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/python/django_graphql/blog/urls.pyc -------------------------------------------------------------------------------- /python/django_graphql/blog/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | 3 | from django.http import HttpResponse 4 | 5 | def index(request): 6 | return HttpResponse("Hello, world. You're at the blog index.") 7 | -------------------------------------------------------------------------------- /python/django_graphql/blog/views.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/python/django_graphql/blog/views.pyc -------------------------------------------------------------------------------- /python/django_graphql/db.sqlite3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/python/django_graphql/db.sqlite3 -------------------------------------------------------------------------------- /python/django_graphql/django_graphql/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/python/django_graphql/django_graphql/__init__.py -------------------------------------------------------------------------------- /python/django_graphql/django_graphql/__init__.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/python/django_graphql/django_graphql/__init__.pyc -------------------------------------------------------------------------------- /python/django_graphql/django_graphql/schema.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/python/django_graphql/django_graphql/schema.pyc -------------------------------------------------------------------------------- /python/django_graphql/django_graphql/settings.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/python/django_graphql/django_graphql/settings.pyc -------------------------------------------------------------------------------- /python/django_graphql/django_graphql/urls.py: -------------------------------------------------------------------------------- 1 | """django_graphql URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/1.9/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.conf.urls import url, include 14 | 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) 15 | """ 16 | from django.conf.urls import include, url 17 | from django.contrib import admin 18 | from django.views.decorators.csrf import csrf_exempt 19 | 20 | from graphene.contrib.django.views import GraphQLView 21 | 22 | from django_graphql.schema import schema 23 | 24 | urlpatterns = [ 25 | url(r'^graphql', csrf_exempt(GraphQLView.as_view(schema=schema))), 26 | url(r'^blog/', include('blog.urls')), 27 | url(r'^admin/', admin.site.urls), 28 | url(r'^', include('django_graphiql.urls')), 29 | ] 30 | -------------------------------------------------------------------------------- /python/django_graphql/django_graphql/urls.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/python/django_graphql/django_graphql/urls.pyc -------------------------------------------------------------------------------- /python/django_graphql/django_graphql/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for django_graphql project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.9/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_graphql.settings") 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /python/django_graphql/django_graphql/wsgi.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/python/django_graphql/django_graphql/wsgi.pyc -------------------------------------------------------------------------------- /python/django_graphql/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_graphql.settings") 7 | 8 | from django.core.management import execute_from_command_line 9 | 10 | execute_from_command_line(sys.argv) 11 | -------------------------------------------------------------------------------- /python/django_graphql/requirements.txt: -------------------------------------------------------------------------------- 1 | django>=1.9 2 | graphene[django] 3 | django_graphiql 4 | django-filter 5 | -------------------------------------------------------------------------------- /python/flask_graphql/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/python/flask_graphql/__init__.py -------------------------------------------------------------------------------- /python/flask_graphql/app.py: -------------------------------------------------------------------------------- 1 | from schema import schema 2 | from models import app 3 | from flask_graphql import GraphQLView 4 | 5 | app.add_url_rule('/', view_func=GraphQLView.as_view('graphql', schema=schema, graphiql=True)) 6 | 7 | if __name__ == '__main__': 8 | app.run() 9 | -------------------------------------------------------------------------------- /python/flask_graphql/app.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/python/flask_graphql/app.pyc -------------------------------------------------------------------------------- /python/flask_graphql/config.py: -------------------------------------------------------------------------------- 1 | import os 2 | basedir = os.path.abspath(os.path.dirname(__file__)) 3 | 4 | 5 | class Config(object): 6 | DEBUG = False 7 | TESTING = False 8 | CSRF_ENABLED = True 9 | SECRET_KEY = 'some-secret-key' 10 | SQLALCHEMY_DATABASE_URI = os.environ['DATABASE_URL'] 11 | 12 | 13 | class ProductionConfig(Config): 14 | DEBUG = False 15 | 16 | 17 | class StagingConfig(Config): 18 | DEVELOPMENT = True 19 | DEBUG = True 20 | 21 | 22 | class DevelopmentConfig(Config): 23 | DEVELOPMENT = True 24 | DEBUG = True 25 | 26 | 27 | class TestingConfig(Config): 28 | TESTING = True 29 | -------------------------------------------------------------------------------- /python/flask_graphql/config.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/python/flask_graphql/config.pyc -------------------------------------------------------------------------------- /python/flask_graphql/manage.py: -------------------------------------------------------------------------------- 1 | import os 2 | from flask.ext.script import Manager 3 | from flask.ext.migrate import Migrate, MigrateCommand 4 | 5 | from models import app, db 6 | 7 | 8 | app.config.from_object(os.environ['APP_SETTINGS']) 9 | 10 | migrate = Migrate(app, db) 11 | manager = Manager(app) 12 | 13 | manager.add_command('db', MigrateCommand) 14 | 15 | 16 | if __name__ == '__main__': 17 | manager.run() 18 | -------------------------------------------------------------------------------- /python/flask_graphql/migrations/README: -------------------------------------------------------------------------------- 1 | Generic single-database configuration. -------------------------------------------------------------------------------- /python/flask_graphql/migrations/alembic.ini: -------------------------------------------------------------------------------- 1 | # A generic, single database configuration. 2 | 3 | [alembic] 4 | # template used to generate migration files 5 | # file_template = %%(rev)s_%%(slug)s 6 | 7 | # set to 'true' to run the environment during 8 | # the 'revision' command, regardless of autogenerate 9 | # revision_environment = false 10 | 11 | 12 | # Logging configuration 13 | [loggers] 14 | keys = root,sqlalchemy,alembic 15 | 16 | [handlers] 17 | keys = console 18 | 19 | [formatters] 20 | keys = generic 21 | 22 | [logger_root] 23 | level = WARN 24 | handlers = console 25 | qualname = 26 | 27 | [logger_sqlalchemy] 28 | level = WARN 29 | handlers = 30 | qualname = sqlalchemy.engine 31 | 32 | [logger_alembic] 33 | level = INFO 34 | handlers = 35 | qualname = alembic 36 | 37 | [handler_console] 38 | class = StreamHandler 39 | args = (sys.stderr,) 40 | level = NOTSET 41 | formatter = generic 42 | 43 | [formatter_generic] 44 | format = %(levelname)-5.5s [%(name)s] %(message)s 45 | datefmt = %H:%M:%S 46 | -------------------------------------------------------------------------------- /python/flask_graphql/migrations/env.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/python/flask_graphql/migrations/env.pyc -------------------------------------------------------------------------------- /python/flask_graphql/migrations/script.py.mako: -------------------------------------------------------------------------------- 1 | """${message} 2 | 3 | Revision ID: ${up_revision} 4 | Revises: ${down_revision} 5 | Create Date: ${create_date} 6 | 7 | """ 8 | 9 | # revision identifiers, used by Alembic. 10 | revision = ${repr(up_revision)} 11 | down_revision = ${repr(down_revision)} 12 | 13 | from alembic import op 14 | import sqlalchemy as sa 15 | ${imports if imports else ""} 16 | 17 | def upgrade(): 18 | ${upgrades if upgrades else "pass"} 19 | 20 | 21 | def downgrade(): 22 | ${downgrades if downgrades else "pass"} 23 | -------------------------------------------------------------------------------- /python/flask_graphql/migrations/versions/11261ac968e5_.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/python/flask_graphql/migrations/versions/11261ac968e5_.pyc -------------------------------------------------------------------------------- /python/flask_graphql/models.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/python/flask_graphql/models.pyc -------------------------------------------------------------------------------- /python/flask_graphql/requirements.txt: -------------------------------------------------------------------------------- 1 | graphene[sqlalchemy] 2 | SQLAlchemy==1.0.11 3 | Flask==0.10.1 4 | Flask-GraphQL==1.3.0 5 | Flask-Migrate==1.8.0 6 | psycopg2==2.6.1 7 | -------------------------------------------------------------------------------- /python/flask_graphql/schema.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/python/flask_graphql/schema.pyc -------------------------------------------------------------------------------- /python/flask_graphql/seed.py: -------------------------------------------------------------------------------- 1 | from models import db 2 | from models import Post 3 | from models import Comment 4 | from models import User 5 | 6 | db.create_all() 7 | 8 | john = User(first_name='John', last_name='Doe', email="john@doe.com", username="johndoe") 9 | maggie = User(first_name='Maggie', last_name='Turner', email="maggie@turner.com", username="maggie") 10 | 11 | db.session.add(john) 12 | db.session.add(maggie) 13 | 14 | post1 = Post(title="First post title", body="First post body", user_id=1) 15 | post2 = Post(title="Second post title", body="Second post body", user_id=2) 16 | 17 | comment1 = Comment(body="first post comment", user_id=1, post_id=1) 18 | comment2 = Comment(body="second post comment", user_id=2, post_id=2) 19 | 20 | db.session.add(post1) 21 | db.session.add(post2) 22 | db.session.add(comment1) 23 | db.session.add(comment2) 24 | db.session.commit() 25 | -------------------------------------------------------------------------------- /ruby/README.md: -------------------------------------------------------------------------------- 1 | # Ruby based web frameworks 2 | 3 | A set of GraphQL server implementation on popular ruby web frameworks. 4 | 5 | ## Frameworks 6 | * Rails 7 | * Sinatra 8 | * Roda 9 | * Cuba 10 | 11 | ```bash 12 | $ brew update 13 | $ brew install rbenv 14 | # list all available versions: 15 | $ rbenv install -l 16 | 17 | # install a Ruby version: 18 | $ rbenv install 2.3.1 19 | ``` 20 | 21 | Then, follow the example readme to setup application locally. 22 | -------------------------------------------------------------------------------- /ruby/cuba_grapgql/.bundle/config: -------------------------------------------------------------------------------- 1 | --- 2 | BUNDLE_DISABLE_SHARED_GEMS: true 3 | -------------------------------------------------------------------------------- /ruby/cuba_grapgql/.gitignore: -------------------------------------------------------------------------------- 1 | .bundle 2 | vendor/bundle 3 | -------------------------------------------------------------------------------- /ruby/cuba_grapgql/Gemfile: -------------------------------------------------------------------------------- 1 | 2 | source "https://rubygems.org" 3 | 4 | gem 'cuba' 5 | gem 'puma' 6 | gem 'data_mapper' 7 | gem 'graphql' 8 | gem 'tilt' 9 | gem 'json' 10 | gem 'dm-postgres-adapter' 11 | gem 'rack-protection' 12 | 13 | # Token 14 | gem 'rack-jwt' 15 | -------------------------------------------------------------------------------- /ruby/cuba_grapgql/README.md: -------------------------------------------------------------------------------- 1 | # Sinatra Graphql Server 2 | 3 | ### Setup and Running locally 4 | 5 | ```bash 6 | git clone repo 7 | cd to folder 8 | bundle install 9 | # make sure postgres is installed 10 | createdb sinatra_graphql_development 11 | bundle exec rake db:migrate 12 | bundle exec rake db:seed 13 | # run the server 14 | bundle exec rackup -p 3000 15 | # Visit http://localhost:3000 16 | ``` 17 | 18 | [Visit browser](http://localhost:3000) 19 | 20 | # Features 21 | * Graphql API 22 | * CSRF and SESSION 23 | * TOKEN AUTH 24 | 25 | ### Supported API Queries 26 | ``` 27 | { 28 | all_posts { 29 | id, 30 | title, 31 | body, 32 | user { 33 | id, 34 | first_name 35 | } 36 | comments { 37 | id, 38 | body 39 | user { 40 | id, 41 | first_name 42 | } 43 | } 44 | 45 | } 46 | } 47 | ``` 48 | 49 | ``` 50 | { 51 | post(id: 2) { 52 | id, 53 | title, 54 | body, 55 | user { 56 | id, 57 | first_name 58 | } 59 | comments { 60 | id, 61 | body 62 | user { 63 | id, 64 | first_name 65 | } 66 | } 67 | 68 | } 69 | } 70 | ``` 71 | 72 | ### DB 73 | * Postgresql (with ruby Sequel ORM) 74 | -------------------------------------------------------------------------------- /ruby/cuba_grapgql/api/schema.rb: -------------------------------------------------------------------------------- 1 | require_relative 'types/post_type' 2 | QueryType = GraphQL::ObjectType.define do 3 | name "Query" 4 | description "The query root of this schema" 5 | 6 | field :post do 7 | type PostType 8 | argument :id, !types.ID 9 | resolve -> (obj, args, ctx) { Post.get(args["id"]) } 10 | end 11 | 12 | field :all_posts do 13 | type types[!PostType] 14 | resolve -> (obj, args, ctx) { Post.all } 15 | end 16 | end 17 | 18 | Schema = GraphQL::Schema.new(query: QueryType) 19 | -------------------------------------------------------------------------------- /ruby/cuba_grapgql/api/types/comment_type.rb: -------------------------------------------------------------------------------- 1 | CommentType = GraphQL::ObjectType.define do 2 | name "Comment" 3 | description "A comment" 4 | 5 | field :id, !types.ID 6 | field :body, !types.String 7 | field :user, -> { UserType } 8 | field :post, -> { PostType } 9 | end 10 | -------------------------------------------------------------------------------- /ruby/cuba_grapgql/api/types/post_type.rb: -------------------------------------------------------------------------------- 1 | PostType = GraphQL::ObjectType.define do 2 | name "Post" 3 | description "A post" 4 | 5 | field :id, !types.ID 6 | field :title, !types.String 7 | field :body, !types.String 8 | field :user, -> { UserType } 9 | field :comments, -> { types[!CommentType] } 10 | end 11 | -------------------------------------------------------------------------------- /ruby/cuba_grapgql/api/types/user_type.rb: -------------------------------------------------------------------------------- 1 | UserType = GraphQL::ObjectType.define do 2 | name "User" 3 | description "A user" 4 | 5 | field :id, !types.ID 6 | field :first_name, !types.String 7 | field :last_name, !types.String 8 | field :username, !types.String 9 | field :email, !types.String 10 | field :posts, -> { types[!PostType] } 11 | field :comments, -> { types[!CommentType] } 12 | end 13 | -------------------------------------------------------------------------------- /ruby/cuba_grapgql/config.ru: -------------------------------------------------------------------------------- 1 | $LOAD_PATH << File.expand_path(File.dirname(__FILE__)) 2 | require 'bundler' 3 | Bundler.require 4 | require 'cuba/render' 5 | require 'tilt/erb' 6 | 7 | Cuba.plugin Cuba::Render 8 | DataMapper::Logger.new(STDOUT, :debug, '[DataMapper] ') 9 | 10 | # Local config 11 | require "find" 12 | 13 | %w{api api/types middlewares}.each do |load_path| 14 | Find.find(load_path) { |f| 15 | require f unless f.match(/\/\..+$/) || File.directory?(f) 16 | } 17 | end 18 | 19 | require "./cuba_grapgql" 20 | run Cuba 21 | -------------------------------------------------------------------------------- /ruby/cuba_grapgql/cuba_grapgql.rb: -------------------------------------------------------------------------------- 1 | require 'rack/protection' 2 | Cuba.use Rack::Session::Cookie, secret: 'super_secret_key' 3 | Cuba.use Rack::Protection 4 | Cuba.use Rack::Protection::RemoteReferrer 5 | # Use middleware for demo (use authentication in real app) 6 | Cuba.use PassAuthToken 7 | # Verify token 8 | Cuba.use Rack::JWT::Auth, {secret: 'super_secret_key', options: { algorithm: 'HS256' }} 9 | 10 | Cuba.define do 11 | # Pass token to the view 12 | data = {user_id: 1} 13 | token = Rack::JWT::Token.encode(data, 'super_secret_key', 'HS256') 14 | 15 | on get do 16 | on root do 17 | res.write view("graphiql", token: token) 18 | end 19 | end 20 | 21 | on post do 22 | on "graphql" do 23 | params = JSON.parse(req.body.read) 24 | payload = Schema.execute( 25 | params["query"], 26 | variables: params["variables"] 27 | ).to_json 28 | 29 | res.headers["Content-Type"] = "application/json; charset=utf-8" 30 | res.write payload 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /ruby/cuba_grapgql/middlewares/pass_auth_token.rb: -------------------------------------------------------------------------------- 1 | # Inject authorization token for root route 2 | # Because we don't have it 3 | # For real app you would use generally some kind of authentication 4 | 5 | class PassAuthToken 6 | def initialize(app) 7 | @app = app 8 | end 9 | 10 | def call(env) 11 | data = {user_id: 1} # Anything you want to encode 12 | token = Rack::JWT::Token.encode(data, 'super_secret_key', 'HS256') 13 | if env['REQUEST_PATH'] == '/' 14 | env['HTTP_AUTHORIZATION'] = "Bearer #{token}" 15 | end 16 | @app.call(env) 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /ruby/rails_graphql/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files for more about ignoring files. 2 | # 3 | # If you find yourself ignoring temporary files generated by your text editor 4 | # or operating system, you probably want to add a global ignore instead: 5 | # git config --global core.excludesfile '~/.gitignore_global' 6 | 7 | # Ignore bundler config. 8 | /.bundle 9 | 10 | # Ignore all logfiles and tempfiles. 11 | /log/* 12 | /tmp/* 13 | !/log/.keep 14 | !/tmp/.keep 15 | 16 | # Ignore Byebug command history file. 17 | .byebug_history 18 | 19 | vendor/bundle 20 | -------------------------------------------------------------------------------- /ruby/rails_graphql/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' 3 | gem 'rails', '>= 5.0.0.rc1', '< 5.1' 4 | # Use postgresql as the database for Active Record 5 | gem 'pg', '~> 0.18' 6 | # Use Puma as the app server 7 | gem 'puma', '~> 3.0' 8 | # gem 'bcrypt', '~> 3.1.7' 9 | gem 'sprockets-rails' 10 | gem 'sass-rails' 11 | gem 'uglifier' 12 | gem 'graphql' 13 | gem 'graphql-relay' 14 | gem 'graphiql-rails' 15 | 16 | # Token auth 17 | gem 'rack-jwt' 18 | 19 | group :development, :test do 20 | # Call 'byebug' anywhere in the code to stop execution and get a debugger console 21 | gem 'byebug', platform: :mri 22 | end 23 | 24 | group :development do 25 | gem 'listen', '~> 3.0.5' 26 | # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring 27 | gem 'spring' 28 | gem 'spring-watcher-listen', '~> 2.0.0' 29 | end 30 | 31 | # Windows does not include zoneinfo files, so bundle the tzinfo-data gem 32 | gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] 33 | -------------------------------------------------------------------------------- /ruby/rails_graphql/README.md: -------------------------------------------------------------------------------- 1 | # Rails Graphql Server 2 | 3 | ### Setup and Running locally 4 | 5 | ```bash 6 | git clone repo 7 | cd to folder 8 | bundle install 9 | # make sure postgres is installed 10 | bundle exec rake db:create db:migrate 11 | bundle exec rake db:seed 12 | # run the server 13 | bundle exec rails s 14 | # Visit http://localhost:3000/ 15 | ``` 16 | 17 | [Visit browser](http://localhost:3000) 18 | 19 | # Features 20 | * Graphql API 21 | * CSRF and SESSION 22 | * TOKEN AUTH 23 | 24 | ### Supported API Queries 25 | ``` 26 | { 27 | all_posts { 28 | id, 29 | title, 30 | body, 31 | user { 32 | id, 33 | first_name 34 | } 35 | comments { 36 | id, 37 | body 38 | user { 39 | id, 40 | first_name 41 | } 42 | } 43 | 44 | } 45 | } 46 | ``` 47 | 48 | ``` 49 | { 50 | post(id: 2) { 51 | id, 52 | title, 53 | body, 54 | user { 55 | id, 56 | first_name 57 | } 58 | comments { 59 | id, 60 | body 61 | user { 62 | id, 63 | first_name 64 | } 65 | } 66 | 67 | } 68 | } 69 | ``` 70 | -------------------------------------------------------------------------------- /ruby/rails_graphql/Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require_relative 'config/application' 5 | 6 | Rails.application.load_tasks 7 | -------------------------------------------------------------------------------- /ruby/rails_graphql/app/api/node_identification.rb: -------------------------------------------------------------------------------- 1 | GraphQL::Relay::GlobalNodeIdentification.instance_variable_set(:@instance, nil) 2 | 3 | NodeIdentification = GraphQL::Relay::GlobalNodeIdentification.define do 4 | # Given a UUID & the query context, 5 | # return the corresponding application object 6 | object_from_id ->(id, _ctx) { resolve_object_from_id(id) } 7 | end 8 | 9 | private 10 | 11 | def resolve_object_from_id(id) 12 | # "User" -> User.find(id) 13 | type_name, id = NodeIdentification.from_global_id(id) 14 | type_name.constantize.find(id) 15 | end 16 | -------------------------------------------------------------------------------- /ruby/rails_graphql/app/api/schema.rb: -------------------------------------------------------------------------------- 1 | QueryType = GraphQL::ObjectType.define do 2 | name "Query" 3 | description "The query root of this schema" 4 | field :node, field: NodeIdentification.field 5 | 6 | field :post do 7 | type PostType 8 | argument :id, !types.ID 9 | resolve -> (obj, args, ctx) { Post.includes(:user, :comments).find(args["id"]) } 10 | end 11 | 12 | field :all_posts do 13 | type types[!PostType] 14 | resolve -> (obj, args, ctx) { Post.all.includes(:user, :comments) } 15 | end 16 | end 17 | 18 | Schema = GraphQL::Schema.define do 19 | query QueryType 20 | rescue_from(ActiveRecord::RecordInvalid) do |_error| 21 | 'Some data could not be saved' 22 | end 23 | 24 | rescue_from(ActiveRecord::RecordNotFound) do |_error| 25 | 'Could not find the record' 26 | end 27 | 28 | resolve_type -> (object, _ctx) { Schema.types[type_name(object)] } 29 | node_identification NodeIdentification 30 | end 31 | 32 | def type_name(object) 33 | object.class.name 34 | end 35 | -------------------------------------------------------------------------------- /ruby/rails_graphql/app/api/types/comment_type.rb: -------------------------------------------------------------------------------- 1 | CommentType = GraphQL::ObjectType.define do 2 | name "Comment" 3 | description "A comment" 4 | 5 | interfaces [NodeIdentification.interface] 6 | global_id_field :id 7 | 8 | field :body, !types.String 9 | field :user, -> { UserType } 10 | field :post, -> { PostType } 11 | end 12 | -------------------------------------------------------------------------------- /ruby/rails_graphql/app/api/types/post_type.rb: -------------------------------------------------------------------------------- 1 | PostType = GraphQL::ObjectType.define do 2 | name "Post" 3 | description "A post" 4 | 5 | interfaces [NodeIdentification.interface] 6 | global_id_field :id 7 | 8 | field :title, !types.String 9 | field :body, !types.String 10 | field :user, -> { UserType } 11 | field :comments do 12 | type types[!CommentType] 13 | resolve -> (obj, args, ctx) { obj.comments.includes(:user) } 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /ruby/rails_graphql/app/api/types/user_type.rb: -------------------------------------------------------------------------------- 1 | UserType = GraphQL::ObjectType.define do 2 | name "User" 3 | description "A user" 4 | 5 | interfaces [NodeIdentification.interface] 6 | global_id_field :id 7 | 8 | field :first_name, !types.String 9 | field :last_name, !types.String 10 | field :username, !types.String 11 | field :email, !types.String 12 | field :posts, types[!PostType] 13 | field :comments, types[!CommentType] 14 | end 15 | -------------------------------------------------------------------------------- /ruby/rails_graphql/app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | # Prevent CSRF attacks by raising an exception. 3 | # For APIs, you may want to use :null_session instead. 4 | protect_from_forgery with: :exception 5 | end 6 | -------------------------------------------------------------------------------- /ruby/rails_graphql/app/controllers/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/ruby/rails_graphql/app/controllers/concerns/.keep -------------------------------------------------------------------------------- /ruby/rails_graphql/app/controllers/graphql_controller.rb: -------------------------------------------------------------------------------- 1 | class GraphqlController < ApplicationController 2 | skip_before_action :verify_authenticity_token 3 | 4 | def create 5 | result = Schema.execute( 6 | params[:query], 7 | variables: params[:variables] 8 | ) 9 | render json: result 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /ruby/rails_graphql/app/models/application_record.rb: -------------------------------------------------------------------------------- 1 | class ApplicationRecord < ActiveRecord::Base 2 | self.abstract_class = true 3 | end 4 | -------------------------------------------------------------------------------- /ruby/rails_graphql/app/models/comment.rb: -------------------------------------------------------------------------------- 1 | class Comment < ApplicationRecord 2 | belongs_to :user 3 | belongs_to :post 4 | end 5 | -------------------------------------------------------------------------------- /ruby/rails_graphql/app/models/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/ruby/rails_graphql/app/models/concerns/.keep -------------------------------------------------------------------------------- /ruby/rails_graphql/app/models/post.rb: -------------------------------------------------------------------------------- 1 | class Post < ApplicationRecord 2 | belongs_to :user 3 | has_many :comments 4 | end 5 | -------------------------------------------------------------------------------- /ruby/rails_graphql/app/models/user.rb: -------------------------------------------------------------------------------- 1 | class User < ApplicationRecord 2 | has_many :comments 3 | has_many :posts 4 | end 5 | -------------------------------------------------------------------------------- /ruby/rails_graphql/bin/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) 3 | load Gem.bin_path('bundler', 'bundle') 4 | -------------------------------------------------------------------------------- /ruby/rails_graphql/bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | begin 3 | load File.expand_path('../spring', __FILE__) 4 | rescue LoadError => e 5 | raise unless e.message.include?('spring') 6 | end 7 | APP_PATH = File.expand_path('../config/application', __dir__) 8 | require_relative '../config/boot' 9 | require 'rails/commands' 10 | -------------------------------------------------------------------------------- /ruby/rails_graphql/bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | begin 3 | load File.expand_path('../spring', __FILE__) 4 | rescue LoadError => e 5 | raise unless e.message.include?('spring') 6 | end 7 | require_relative '../config/boot' 8 | require 'rake' 9 | Rake.application.run 10 | -------------------------------------------------------------------------------- /ruby/rails_graphql/bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'pathname' 3 | require 'fileutils' 4 | include FileUtils 5 | 6 | # path to your application root. 7 | APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) 8 | 9 | def system!(*args) 10 | system(*args) || abort("\n== Command #{args} failed ==") 11 | end 12 | 13 | chdir APP_ROOT do 14 | # This script is a starting point to setup your application. 15 | # Add necessary setup steps to this file. 16 | 17 | puts '== Installing dependencies ==' 18 | system! 'gem install bundler --conservative' 19 | system('bundle check') || system!('bundle install') 20 | 21 | # puts "\n== Copying sample files ==" 22 | # unless File.exist?('config/database.yml') 23 | # cp 'config/database.yml.sample', 'config/database.yml' 24 | # end 25 | 26 | puts "\n== Preparing database ==" 27 | system! 'bin/rails db:setup' 28 | 29 | puts "\n== Removing old logs and tempfiles ==" 30 | system! 'bin/rails log:clear tmp:clear' 31 | 32 | puts "\n== Restarting application server ==" 33 | system! 'bin/rails restart' 34 | end 35 | -------------------------------------------------------------------------------- /ruby/rails_graphql/bin/spring: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # This file loads spring without using Bundler, in order to be fast. 4 | # It gets overwritten when you run the `spring binstub` command. 5 | 6 | unless defined?(Spring) 7 | require 'rubygems' 8 | require 'bundler' 9 | 10 | if (match = Bundler.default_lockfile.read.match(/^GEM$.*?^ (?: )*spring \((.*?)\)$.*?^$/m)) 11 | Gem.paths = { 'GEM_PATH' => [Bundler.bundle_path.to_s, *Gem.path].uniq.join(Gem.path_separator) } 12 | gem 'spring', match[1] 13 | require 'spring/binstub' 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /ruby/rails_graphql/bin/update: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'pathname' 3 | require 'fileutils' 4 | include FileUtils 5 | 6 | # path to your application root. 7 | APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) 8 | 9 | def system!(*args) 10 | system(*args) || abort("\n== Command #{args} failed ==") 11 | end 12 | 13 | chdir APP_ROOT do 14 | # This script is a way to update your development environment automatically. 15 | # Add necessary update steps to this file. 16 | 17 | puts '== Installing dependencies ==' 18 | system! 'gem install bundler --conservative' 19 | system('bundle check') || system!('bundle install') 20 | 21 | puts "\n== Updating database ==" 22 | system! 'bin/rails db:migrate' 23 | 24 | puts "\n== Removing old logs and tempfiles ==" 25 | system! 'bin/rails log:clear tmp:clear' 26 | 27 | puts "\n== Restarting application server ==" 28 | system! 'bin/rails restart' 29 | end 30 | -------------------------------------------------------------------------------- /ruby/rails_graphql/config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require_relative 'config/environment' 4 | 5 | run Rails.application 6 | -------------------------------------------------------------------------------- /ruby/rails_graphql/config/boot.rb: -------------------------------------------------------------------------------- 1 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) 2 | 3 | require 'bundler/setup' # Set up gems listed in the Gemfile. 4 | -------------------------------------------------------------------------------- /ruby/rails_graphql/config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require_relative 'application' 3 | 4 | # Initialize the Rails application. 5 | Rails.application.initialize! 6 | -------------------------------------------------------------------------------- /ruby/rails_graphql/config/initializers/active_record_belongs_to_required_by_default.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Require `belongs_to` associations by default. This is a new Rails 5.0 4 | # default, so it is introduced as a configuration option to ensure that apps 5 | # made on earlier versions of Rails are not affected when upgrading. 6 | Rails.application.config.active_record.belongs_to_required_by_default = true 7 | -------------------------------------------------------------------------------- /ruby/rails_graphql/config/initializers/application_controller_renderer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # ApplicationController.renderer.defaults.merge!( 4 | # http_host: 'example.org', 5 | # https: false 6 | # ) 7 | -------------------------------------------------------------------------------- /ruby/rails_graphql/config/initializers/backtrace_silencers.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. 4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } 5 | 6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. 7 | # Rails.backtrace_cleaner.remove_silencers! 8 | -------------------------------------------------------------------------------- /ruby/rails_graphql/config/initializers/callback_terminator.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Do not halt callback chains when a callback returns false. This is a new 4 | # Rails 5.0 default, so it is introduced as a configuration option to ensure 5 | # that apps made with earlier versions of Rails are not affected when upgrading. 6 | ActiveSupport.halt_callback_chains_on_return_false = false 7 | -------------------------------------------------------------------------------- /ruby/rails_graphql/config/initializers/cookies_serializer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Specify a serializer for the signed and encrypted cookie jars. 4 | # Valid options are :json, :marshal, and :hybrid. 5 | Rails.application.config.action_dispatch.cookies_serializer = :json 6 | -------------------------------------------------------------------------------- /ruby/rails_graphql/config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Configure sensitive parameters which will be filtered from the log file. 4 | Rails.application.config.filter_parameters += [:password] 5 | -------------------------------------------------------------------------------- /ruby/rails_graphql/config/initializers/graphiql.rb: -------------------------------------------------------------------------------- 1 | GraphiQL::Rails.config.query_params = false # if true, the GraphQL query string will be persisted the page's query params. 2 | GraphiQL::Rails.config.csrf = true 3 | -------------------------------------------------------------------------------- /ruby/rails_graphql/config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new inflection rules using the following format. Inflections 4 | # are locale specific, and you may define rules for as many different 5 | # locales as you wish. All of these examples are active by default: 6 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 7 | # inflect.plural /^(ox)$/i, '\1en' 8 | # inflect.singular /^(ox)en/i, '\1' 9 | # inflect.irregular 'person', 'people' 10 | # inflect.uncountable %w( fish sheep ) 11 | # end 12 | 13 | # These inflection rules are supported but not enabled by default: 14 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 15 | # inflect.acronym 'RESTful' 16 | # end 17 | -------------------------------------------------------------------------------- /ruby/rails_graphql/config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new mime types for use in respond_to blocks: 4 | # Mime::Type.register "text/richtext", :rtf 5 | -------------------------------------------------------------------------------- /ruby/rails_graphql/config/initializers/per_form_csrf_tokens.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Enable per-form CSRF tokens. 4 | Rails.application.config.action_controller.per_form_csrf_tokens = true 5 | -------------------------------------------------------------------------------- /ruby/rails_graphql/config/initializers/request_forgery_protection.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Enable origin-checking CSRF mitigation. 4 | Rails.application.config.action_controller.forgery_protection_origin_check = true 5 | -------------------------------------------------------------------------------- /ruby/rails_graphql/config/initializers/session_store.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | Rails.application.config.session_store :cookie_store, key: '_rails_graphql_session' 4 | -------------------------------------------------------------------------------- /ruby/rails_graphql/config/initializers/ssl_options.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Configure SSL options to enable HSTS with subdomains. 4 | Rails.application.config.ssl_options = { hsts: { subdomains: true } } 5 | -------------------------------------------------------------------------------- /ruby/rails_graphql/config/initializers/to_time_preserves_timezone.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Preserve the timezone of the receiver when calling to `to_time`. 4 | # Ruby 2.4 will change the behavior of `to_time` to preserve the timezone 5 | # when converting to an instance of `Time` instead of the previous behavior 6 | # of converting to the local system timezone. 7 | # 8 | # Rails 5.0 introduced this config option so that apps made with earlier 9 | # versions of Rails are not affected when upgrading. 10 | ActiveSupport.to_time_preserves_timezone = true 11 | -------------------------------------------------------------------------------- /ruby/rails_graphql/config/initializers/wrap_parameters.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # This file contains settings for ActionController::ParamsWrapper which 4 | # is enabled by default. 5 | 6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. 7 | ActiveSupport.on_load(:action_controller) do 8 | wrap_parameters format: [:json] 9 | end 10 | 11 | # To enable root element in JSON for ActiveRecord objects. 12 | # ActiveSupport.on_load(:active_record) do 13 | # self.include_root_in_json = true 14 | # end 15 | -------------------------------------------------------------------------------- /ruby/rails_graphql/config/locales/en.yml: -------------------------------------------------------------------------------- 1 | # Files in the config/locales directory are used for internationalization 2 | # and are automatically loaded by Rails. If you want to use locales other 3 | # than English, add the necessary files in this directory. 4 | # 5 | # To use the locales, use `I18n.t`: 6 | # 7 | # I18n.t 'hello' 8 | # 9 | # In views, this is aliased to just `t`: 10 | # 11 | # <%= t('hello') %> 12 | # 13 | # To use a different locale, set it with `I18n.locale`: 14 | # 15 | # I18n.locale = :es 16 | # 17 | # This would use the information in config/locales/es.yml. 18 | # 19 | # To learn more, please read the Rails Internationalization guide 20 | # available at http://guides.rubyonrails.org/i18n.html. 21 | 22 | en: 23 | hello: "Hello world" 24 | -------------------------------------------------------------------------------- /ruby/rails_graphql/config/routes.rb: -------------------------------------------------------------------------------- 1 | Rails.application.routes.draw do 2 | mount GraphiQL::Rails::Engine, at: "/", graphql_path: "/graphql" 3 | scope '/graphql' do 4 | post "/", to: "graphql#create" 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /ruby/rails_graphql/config/secrets.yml: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Your secret key is used for verifying the integrity of signed cookies. 4 | # If you change this key, all old signed cookies will become invalid! 5 | 6 | # Make sure the secret is at least 30 characters and all random, 7 | # no regular words or you'll be exposed to dictionary attacks. 8 | # You can use `rails secret` to generate a secure secret key. 9 | 10 | # Make sure the secrets in this file are kept private 11 | # if you're sharing your code publicly. 12 | 13 | development: 14 | secret_key_base: 5088c07c1ef37ea7460d95a371763e53ce119cd120accbafc979272c8275c4e263859d77cf26a83c8939ebb0d035dccfa750688530bc9a545dae16a33f5561cf 15 | 16 | test: 17 | secret_key_base: 95ea85eeb501176720c4ded6625a2160b8ca31fda9ad16e9d378ff31b74b086b43efbcbd3faa0af99efc28715060e1b86befe3231bf2e57522c6aaff7b48991a 18 | 19 | # Do not keep production secrets in the repository, 20 | # instead read values from the environment. 21 | production: 22 | secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> 23 | -------------------------------------------------------------------------------- /ruby/rails_graphql/config/spring.rb: -------------------------------------------------------------------------------- 1 | %w( 2 | .ruby-version 3 | .rbenv-vars 4 | tmp/restart.txt 5 | tmp/caching-dev.txt 6 | ).each { |path| Spring.watch(path) } 7 | -------------------------------------------------------------------------------- /ruby/rails_graphql/db/migrate/20160524121108_create_users.rb: -------------------------------------------------------------------------------- 1 | class CreateUsers < ActiveRecord::Migration[5.0] 2 | def change 3 | create_table :users do |t| 4 | t.string :first_name 5 | t.string :last_name 6 | t.string :email 7 | t.string :username 8 | 9 | t.timestamps 10 | end 11 | add_index :users, :email 12 | add_index :users, :username 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /ruby/rails_graphql/db/migrate/20160524121211_create_posts.rb: -------------------------------------------------------------------------------- 1 | class CreatePosts < ActiveRecord::Migration[5.0] 2 | def change 3 | create_table :posts do |t| 4 | t.string :title 5 | t.text :body 6 | t.references :user, foreign_key: true 7 | 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /ruby/rails_graphql/db/migrate/20160524121235_create_comments.rb: -------------------------------------------------------------------------------- 1 | class CreateComments < ActiveRecord::Migration[5.0] 2 | def change 3 | create_table :comments do |t| 4 | t.text :body 5 | t.references :user, foreign_key: true 6 | t.references :post, foreign_key: true 7 | 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /ruby/rails_graphql/db/seeds.rb: -------------------------------------------------------------------------------- 1 | # This file should contain all the record creation needed to seed the database with its default values. 2 | # The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup). 3 | # 4 | # Examples: 5 | # 6 | # movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }]) 7 | # Character.create(name: 'Luke', movie: movies.first) 8 | 9 | ActiveRecord::Base.transaction do 10 | john = User.create(first_name: 'John', last_name: 'Doe', email: 'john@doe.com', username: 'johndoe') 11 | maggie = User.create(first_name: 'Maggie', last_name: 'Turner', email: 'maggie@doe.com', username: 'maggie') 12 | 13 | 10.times do |index| 14 | Post.create(title: "This is #{index} post title", body: "This is #{index} post body", user: [john, maggie].sample) 15 | end 16 | 17 | Post.all.each do |post| 18 | 10.times do |index| 19 | Comment.create(body: "This is comment for post #{post.id}", user: [john, maggie].sample, post: post) 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /ruby/rails_graphql/lib/assets/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/ruby/rails_graphql/lib/assets/.keep -------------------------------------------------------------------------------- /ruby/rails_graphql/lib/pass_auth_token.rb: -------------------------------------------------------------------------------- 1 | # Inject authorization token for root route 2 | # Because we don't have it 3 | # For real app you would use generally some kind of authentication 4 | 5 | class PassAuthToken 6 | def initialize(app) 7 | @app = app 8 | end 9 | 10 | def call(env) 11 | data = {user_id: 1} # Anything you want to encode 12 | token = Rack::JWT::Token.encode(data, 'super_secret_key', 'HS256') 13 | if env['REQUEST_PATH'] == '/' 14 | env['HTTP_AUTHORIZATION'] = "Bearer #{token}" 15 | end 16 | @app.call(env) 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /ruby/rails_graphql/lib/tasks/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/ruby/rails_graphql/lib/tasks/.keep -------------------------------------------------------------------------------- /ruby/rails_graphql/log/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/ruby/rails_graphql/log/.keep -------------------------------------------------------------------------------- /ruby/rails_graphql/public/apple-touch-icon-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/ruby/rails_graphql/public/apple-touch-icon-precomposed.png -------------------------------------------------------------------------------- /ruby/rails_graphql/public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/ruby/rails_graphql/public/apple-touch-icon.png -------------------------------------------------------------------------------- /ruby/rails_graphql/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/ruby/rails_graphql/public/favicon.ico -------------------------------------------------------------------------------- /ruby/rails_graphql/public/robots.txt: -------------------------------------------------------------------------------- 1 | # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file 2 | # 3 | # To ban all spiders from the entire site uncomment the next two lines: 4 | # User-agent: * 5 | # Disallow: / 6 | -------------------------------------------------------------------------------- /ruby/rails_graphql/tmp/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/ruby/rails_graphql/tmp/.keep -------------------------------------------------------------------------------- /ruby/roda_graphql/.env: -------------------------------------------------------------------------------- 1 | ENVIRONMENT="development" 2 | 3 | RACK_COOKIE_KEY="roda_graphql" 4 | RACK_COOKIE_SECRET="oEwNzxGhy6Xpw81dPyVQc1GI1Tb49pn0vie+nwwHnyDBuu0IwKbcR9WoXBDTXNQAeso=" 5 | -------------------------------------------------------------------------------- /ruby/roda_graphql/.gitignore: -------------------------------------------------------------------------------- 1 | .bundle 2 | vendor/bundle 3 | -------------------------------------------------------------------------------- /ruby/roda_graphql/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | group :development do 4 | gem 'rake' 5 | end 6 | 7 | gem 'puma' 8 | gem 'roda' 9 | gem 'tilt' 10 | 11 | # Graphql 12 | gem 'graphql' 13 | 14 | # Database Stack 15 | gem 'sequel' 16 | gem 'sequel-seed' 17 | gem 'sqlite3' 18 | gem 'colorize' 19 | 20 | # Protection :) 21 | gem 'rack-protection' 22 | 23 | # Token :) 24 | gem 'rack-jwt' 25 | -------------------------------------------------------------------------------- /ruby/roda_graphql/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | colorize (0.7.7) 5 | dotenv (2.1.1) 6 | graphql (0.15.2) 7 | jwt (1.5.4) 8 | pg (0.18.4) 9 | puma (3.4.0) 10 | rack (1.6.4) 11 | rack-jwt (0.3.0) 12 | jwt (~> 1.5.2) 13 | rack (>= 1.6.0) 14 | rack-protection (1.5.3) 15 | rack 16 | rake (11.2.2) 17 | roda (2.15.0) 18 | rack 19 | sequel (4.35.0) 20 | sequel-seed (0.3.2) 21 | sequel (>= 4.0) 22 | sqlite3 (1.3.13) 23 | tilt (2.0.5) 24 | 25 | PLATFORMS 26 | ruby 27 | 28 | DEPENDENCIES 29 | colorize 30 | dotenv 31 | graphql 32 | pg 33 | puma 34 | rack-jwt 35 | rack-protection 36 | rake 37 | roda 38 | sequel 39 | sequel-seed 40 | sqlite3 41 | tilt 42 | 43 | BUNDLED WITH 44 | 1.15.3 45 | -------------------------------------------------------------------------------- /ruby/roda_graphql/README.md: -------------------------------------------------------------------------------- 1 | # Roda Graphql Server 2 | 3 | ### Setup and Running locally 4 | 5 | ```bash 6 | git clone repo 7 | cd to folder 8 | bundle install 9 | # make sure postgres is installed 10 | createdb roda_graphql 11 | bundle exec rake db:migrate 12 | bundle exec rake db:seed 13 | # run the server 14 | bundle exec rackup -p 3000 15 | # Visit http://localhost:3000 16 | ``` 17 | 18 | [Visit browser](http://localhost:3000) 19 | 20 | # Features 21 | * Graphql API 22 | * CSRF and SESSION 23 | * TOKEN AUTH 24 | 25 | ### Supported API Queries 26 | ``` 27 | { 28 | all_posts { 29 | id, 30 | title, 31 | body, 32 | user { 33 | id, 34 | first_name 35 | } 36 | comments { 37 | id, 38 | body 39 | user { 40 | id, 41 | first_name 42 | } 43 | } 44 | 45 | } 46 | } 47 | ``` 48 | 49 | ``` 50 | { 51 | post(id: 2) { 52 | id, 53 | title, 54 | body, 55 | user { 56 | id, 57 | first_name 58 | } 59 | comments { 60 | id, 61 | body 62 | user { 63 | id, 64 | first_name 65 | } 66 | } 67 | 68 | } 69 | } 70 | ``` 71 | 72 | ### DB 73 | * Postgresql (with ruby Sequel ORM) 74 | -------------------------------------------------------------------------------- /ruby/roda_graphql/Rakefile: -------------------------------------------------------------------------------- 1 | require 'sequel' 2 | require 'sequel/extensions/seed' 3 | 4 | namespace :db do 5 | task :environment do 6 | puts 'task environment' 7 | end 8 | desc "Run all migrations in db/migrate" 9 | task :migrate => :connect do 10 | Sequel.extension(:migration) 11 | Sequel::Migrator.apply(DB, "db/migrate") 12 | end 13 | 14 | task :seed => :connect do 15 | Sequel.extension(:seed) 16 | Sequel::Seeder.apply(DB, "db/seeds") 17 | end 18 | 19 | task :connect => :environment do 20 | DB = Sequel.connect("sqlite://blog.db") 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /ruby/roda_graphql/api/models/comment.rb: -------------------------------------------------------------------------------- 1 | class Comment < Sequel::Model 2 | many_to_one :post 3 | many_to_one :user 4 | end 5 | -------------------------------------------------------------------------------- /ruby/roda_graphql/api/models/post.rb: -------------------------------------------------------------------------------- 1 | class Post < Sequel::Model 2 | one_to_many :comments 3 | many_to_one :user 4 | end 5 | -------------------------------------------------------------------------------- /ruby/roda_graphql/api/models/user.rb: -------------------------------------------------------------------------------- 1 | class User < Sequel::Model 2 | one_to_many :comments 3 | one_to_many :posts 4 | end 5 | -------------------------------------------------------------------------------- /ruby/roda_graphql/api/routes/main.rb: -------------------------------------------------------------------------------- 1 | class RodaGraphql 2 | route do |r| 3 | r.root do 4 | data = {user_id: 1} 5 | token = Rack::JWT::Token.encode(data, ENV['RACK_COOKIE_SECRET'], 'HS256') 6 | set_layout_locals token: token 7 | view("graphiql") 8 | end 9 | 10 | r.on "graphql" do 11 | r.post do 12 | params = JSON.parse(request.body.read) 13 | result = Schema.execute( 14 | params["query"], 15 | variables: params["variables"] 16 | ) 17 | 18 | response['Content-Type'] = 'application/json; charset=utf-8' 19 | result.to_json 20 | end 21 | end 22 | 23 | r.assets 24 | r.multi_route 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /ruby/roda_graphql/api/schema.rb: -------------------------------------------------------------------------------- 1 | QueryType = GraphQL::ObjectType.define do 2 | name "Query" 3 | description "The query root of this schema" 4 | 5 | field :post do 6 | type PostType 7 | argument :id, !types.ID 8 | resolve -> (obj, args, ctx) { Post.find(id: args["id"]) } 9 | end 10 | 11 | field :all_posts do 12 | type types[!PostType] 13 | resolve -> (obj, args, ctx) { Post.all } 14 | end 15 | end 16 | 17 | Schema = GraphQL::Schema.new(query: QueryType) 18 | -------------------------------------------------------------------------------- /ruby/roda_graphql/api/types/comment_type.rb: -------------------------------------------------------------------------------- 1 | CommentType = GraphQL::ObjectType.define do 2 | name "Comment" 3 | description "A comment" 4 | 5 | field :id, !types.ID 6 | field :body, !types.String 7 | field :user, -> { UserType } 8 | field :post, -> { PostType } 9 | end 10 | -------------------------------------------------------------------------------- /ruby/roda_graphql/api/types/post_type.rb: -------------------------------------------------------------------------------- 1 | PostType = GraphQL::ObjectType.define do 2 | name "Post" 3 | description "A post" 4 | 5 | field :id, !types.ID 6 | field :title, !types.String 7 | field :body, !types.String 8 | field :user, -> { UserType } 9 | field :comments, -> { types[!CommentType] } 10 | end 11 | -------------------------------------------------------------------------------- /ruby/roda_graphql/api/types/user_type.rb: -------------------------------------------------------------------------------- 1 | UserType = GraphQL::ObjectType.define do 2 | name "User" 3 | description "A user" 4 | 5 | field :id, !types.ID 6 | field :first_name, !types.String 7 | field :last_name, !types.String 8 | field :username, !types.String 9 | field :email, !types.String 10 | field :posts, -> { types[!PostType] } 11 | field :comments, -> { types[!CommentType] } 12 | end 13 | -------------------------------------------------------------------------------- /ruby/roda_graphql/assets/assets.rb: -------------------------------------------------------------------------------- 1 | class RodaGraphql < Roda 2 | def self.css_files 3 | [].tap do |css| 4 | css << "graphiql-0.7.0.css" 5 | css << "main.css" 6 | css << "application.css" 7 | end 8 | end 9 | 10 | def self.js_files 11 | [].tap do |js| 12 | js << "react-15.0.1.js" 13 | js << "react-dom-15.0.1.js" 14 | js << "fetch-0.10.1.js" 15 | js << "graphiql-0.7.0.js" 16 | end 17 | end 18 | 19 | dependencies = Hash.new(Dir["assets/" "**/*.*"]) 20 | 21 | self.plugin :assets, css: css_files, js: js_files, dependencies: dependencies 22 | compile_assets if production? 23 | end 24 | -------------------------------------------------------------------------------- /ruby/roda_graphql/assets/css/application.css: -------------------------------------------------------------------------------- 1 | 2 | @import "graphiql-0.7.0.css"; 3 | @import "main.css"; 4 | 5 | html, body { 6 | height: 100%; 7 | margin: 0; 8 | overflow: hidden; 9 | width: 100%; 10 | } 11 | -------------------------------------------------------------------------------- /ruby/roda_graphql/assets/js/application.js: -------------------------------------------------------------------------------- 1 | //= require ./react-15.0.1 2 | //= require ./react-dom-15.0.1 3 | //= require ./fetch-0.10.1 4 | //= require ./graphiql-0.7.0 5 | -------------------------------------------------------------------------------- /ruby/roda_graphql/blog.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/ruby/roda_graphql/blog.db -------------------------------------------------------------------------------- /ruby/roda_graphql/config.ru: -------------------------------------------------------------------------------- 1 | # Load path and gems/bundler 2 | $LOAD_PATH << File.expand_path(File.dirname(__FILE__)) 3 | require 'tilt/erb' 4 | require 'bundler' 5 | require 'logger' 6 | Bundler.require 7 | 8 | # Local config 9 | require "find" 10 | 11 | %w{config/initializers api/types api/models middlewares}.each do |load_path| 12 | Find.find(load_path) { |f| 13 | require f unless f.match(/\/\..+$/) || File.directory?(f) 14 | } 15 | end 16 | 17 | logger = Logger.new(STDOUT) 18 | 19 | logger.level = Logger::DEBUG 20 | logger.formatter = proc do |severity, datetime, progname, msg| 21 | date_format = datetime.strftime("%Y-%m-%d %H:%M:%S") 22 | if severity == "INFO" 23 | "[#{date_format}] #{severity} (#{progname}): #{msg}\n".blue 24 | elsif severity == "WARN" 25 | "[#{date_format}] #{severity} (#{progname}): #{msg}\n".orange 26 | else 27 | "[#{date_format}] #{severity} (#{progname}): #{msg}\n".red 28 | end 29 | end 30 | 31 | DB.loggers << logger if logger 32 | 33 | require './roda_graphql' 34 | run RodaGraphql 35 | -------------------------------------------------------------------------------- /ruby/roda_graphql/db/migrate/1_user.rb: -------------------------------------------------------------------------------- 1 | Sequel.migration do 2 | up do 3 | create_table(:users) do 4 | primary_key :id 5 | String :first_name, :null=>false 6 | String :last_name, :null=>false 7 | String :email, :null=>false 8 | String :username, :null=>false 9 | end 10 | end 11 | 12 | down do 13 | drop_table(:users) 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /ruby/roda_graphql/db/migrate/2_post.rb: -------------------------------------------------------------------------------- 1 | Sequel.migration do 2 | up do 3 | create_table(:posts) do 4 | primary_key :id 5 | String :title, :null=>false 6 | String :body, :null=>false 7 | foreign_key :user_id, :users 8 | end 9 | end 10 | 11 | down do 12 | drop_table(:posts) 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /ruby/roda_graphql/db/migrate/3_comment.rb: -------------------------------------------------------------------------------- 1 | Sequel.migration do 2 | up do 3 | create_table(:comments) do 4 | primary_key :id 5 | String :body, :null=>false 6 | foreign_key :user_id, :users 7 | foreign_key :post_id, :posts 8 | end 9 | end 10 | 11 | down do 12 | drop_table(:comments) 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /ruby/roda_graphql/db/seeds/20150928000000_seed.rb: -------------------------------------------------------------------------------- 1 | Sequel.seed do # Applies only to "development" and "test" environments 2 | def run 3 | user = DB[:users] 4 | post = DB[:posts] 5 | comment = DB[:comments] 6 | 7 | [ 8 | ['John', 'Doe', 'john@doe.com', 'johndoe'], 9 | ['Maggie', 'Turner', 'maggie@turner.com', 'maggie'] 10 | ].each do |first_name, last_name, email, username| 11 | user.insert first_name: first_name, last_name: last_name, email: email, username: username 12 | end 13 | 14 | [ 15 | ['First post title', 'First post body', 1], 16 | ['Second Post title', 'Second post body', 2] 17 | ].each do |title, body, user_id| 18 | post.insert title: title, body: body, user_id: user_id 19 | end 20 | 21 | [ 22 | ['First post comment body', 1, 1], 23 | ['Second Post comment body', 2, 2] 24 | ].each do |body, post_id, user_id| 25 | comment.insert body: body, post_id: post_id, user_id: user_id 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /ruby/roda_graphql/middlewares/pass_auth_token.rb: -------------------------------------------------------------------------------- 1 | # Inject authorization token for root route 2 | # Because we don't have it 3 | # For real app you would use generally some kind of authentication 4 | 5 | class PassAuthToken 6 | def initialize(app) 7 | @app = app 8 | end 9 | 10 | def call(env) 11 | data = {user_id: 1} # Anything you want to encode 12 | token = Rack::JWT::Token.encode(data, ENV['RACK_COOKIE_SECRET'], 'HS256') 13 | if env['REQUEST_PATH'] == '/' 14 | env['HTTP_AUTHORIZATION'] = "Bearer #{token}" 15 | end 16 | @app.call(env) 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /ruby/roda_graphql/roda_graphql.rb: -------------------------------------------------------------------------------- 1 | require './api/schema' 2 | 3 | Dotenv.load 4 | 5 | class RodaGraphql < Roda 6 | use Rack::Session::Cookie, key: ENV['RACK_COOKIE_KEY'], secret: ENV['RACK_COOKIE_SECRET'] 7 | use Rack::Protection 8 | use Rack::Protection::RemoteReferrer 9 | use PassAuthToken 10 | use Rack::JWT::Auth, {secret: ENV['RACK_COOKIE_SECRET'], exclude: %w(/assets), options: { algorithm: 'HS256' }} 11 | 12 | plugin :environments 13 | self.environment = ENV['ENVIRONMENT'] 14 | 15 | plugin :flash 16 | plugin :json 17 | plugin :json_parser 18 | plugin :render, engine: 'erb' 19 | plugin :view_options 20 | plugin :assets 21 | plugin :multi_route 22 | 23 | require './assets/assets' 24 | 25 | require './api/routes/main.rb' 26 | Dir['./routes/*.rb'].each{|f| require f} 27 | end 28 | -------------------------------------------------------------------------------- /ruby/roda_graphql/views/layout.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Roda Graphql 13 | 14 | <%= assets(:css) %> 15 | <%= assets(:js) %> 16 | 17 | 21 | 22 | 23 | <%= yield %> 24 | 25 | -------------------------------------------------------------------------------- /ruby/sinatra_graphql/.gitignore: -------------------------------------------------------------------------------- 1 | .bundle 2 | vendor/bundle 3 | -------------------------------------------------------------------------------- /ruby/sinatra_graphql/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org/' 2 | 3 | # App Stack 4 | gem 'sinatra', '>= 1.4' 5 | 6 | # Database Stack 7 | gem 'sequel' 8 | gem 'sequel-seed' 9 | gem 'pg' 10 | gem 'puma' 11 | gem 'colorize' 12 | gem 'rack-protection' 13 | 14 | # Graphql 15 | gem 'graphql' 16 | gem 'json' 17 | 18 | # Token 19 | gem 'rack-jwt' 20 | 21 | group :development do 22 | gem 'rake', '~> 10.0' 23 | gem 'minitest', '~> 5.2' 24 | gem 'rack-test', '~> 0.6' 25 | end 26 | -------------------------------------------------------------------------------- /ruby/sinatra_graphql/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | colorize (0.8.1) 5 | graphql (0.18.11) 6 | json (2.0.2) 7 | jwt (1.5.5) 8 | minitest (5.9.0) 9 | pg (0.18.4) 10 | puma (3.6.0) 11 | rack (1.6.4) 12 | rack-jwt (0.3.0) 13 | jwt (~> 1.5.2) 14 | rack (>= 1.6.0) 15 | rack-protection (1.5.3) 16 | rack 17 | rack-test (0.6.3) 18 | rack (>= 1.0) 19 | rake (10.5.0) 20 | sequel (4.38.0) 21 | sequel-seed (1.0.0) 22 | sequel (>= 4.0) 23 | sinatra (1.4.7) 24 | rack (~> 1.5) 25 | rack-protection (~> 1.4) 26 | tilt (>= 1.3, < 3) 27 | tilt (2.0.5) 28 | 29 | PLATFORMS 30 | ruby 31 | 32 | DEPENDENCIES 33 | colorize 34 | graphql 35 | json 36 | minitest (~> 5.2) 37 | pg 38 | puma 39 | rack-jwt 40 | rack-protection 41 | rack-test (~> 0.6) 42 | rake (~> 10.0) 43 | sequel 44 | sequel-seed 45 | sinatra (>= 1.4) 46 | 47 | BUNDLED WITH 48 | 1.12.5 49 | -------------------------------------------------------------------------------- /ruby/sinatra_graphql/README.md: -------------------------------------------------------------------------------- 1 | # Sinatra Graphql Server 2 | 3 | ### Setup and Running locally 4 | 5 | ```bash 6 | git clone repo 7 | cd to folder 8 | bundle install 9 | # make sure postgres is installed 10 | createdb sinatra_graphql_development 11 | bundle exec rake db:migrate 12 | bundle exec rake db:seed 13 | # run the server 14 | bundle exec rackup -p 3000 15 | # Visit http://localhost:3000 16 | ``` 17 | 18 | [Visit browser](http://localhost:3000) 19 | 20 | # Features 21 | * Graphql API 22 | * CSRF and SESSION 23 | * TOKEN AUTH 24 | 25 | ### Supported API Queries 26 | ``` 27 | { 28 | all_posts { 29 | id, 30 | title, 31 | body, 32 | user { 33 | id, 34 | first_name 35 | } 36 | comments { 37 | id, 38 | body 39 | user { 40 | id, 41 | first_name 42 | } 43 | } 44 | 45 | } 46 | } 47 | ``` 48 | 49 | ``` 50 | { 51 | post(id: 2) { 52 | id, 53 | title, 54 | body, 55 | user { 56 | id, 57 | first_name 58 | } 59 | comments { 60 | id, 61 | body 62 | user { 63 | id, 64 | first_name 65 | } 66 | } 67 | 68 | } 69 | } 70 | ``` 71 | 72 | ### DB 73 | * Postgresql (with ruby Sequel ORM) 74 | -------------------------------------------------------------------------------- /ruby/sinatra_graphql/Rakefile: -------------------------------------------------------------------------------- 1 | %w{ bundler find rake/testtask}.each { |lib| require lib } 2 | require 'sequel' 3 | 4 | task :default => :spec 5 | 6 | Rake::TestTask.new(:spec) do |t| 7 | t.test_files = FileList['spec/*_spec.rb'] 8 | end 9 | 10 | namespace :db do 11 | task :environment do 12 | puts 'task environment' 13 | end 14 | desc "Run all migrations in db/migrate" 15 | task :migrate => :connect do 16 | Sequel.extension(:migration) 17 | Sequel::Migrator.apply(DB, "db/migrate") 18 | end 19 | 20 | task :seed => :connect do 21 | Sequel.extension(:seed) 22 | Sequel::Seeder.apply(DB, "db/seeds") 23 | end 24 | 25 | task :connect => :environment do 26 | require "./config/initializers/database" 27 | Dir.glob('./lib/{models}/*.rb').each { |file| require file } 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /ruby/sinatra_graphql/config.ru: -------------------------------------------------------------------------------- 1 | # Load path and gems/bundler 2 | $LOAD_PATH << File.expand_path(File.dirname(__FILE__)) 3 | require 'tilt/erb' 4 | require 'bundler' 5 | require 'logger' 6 | require 'colorize' 7 | Bundler.require 8 | # Local config 9 | require "find" 10 | 11 | %w{config/initializers lib middlewares}.each do |load_path| 12 | Find.find(load_path) { |f| 13 | require f unless f.match(/\/\..+$/) || File.directory?(f) 14 | } 15 | end 16 | 17 | logger = Logger.new(STDOUT) 18 | 19 | logger.level = Logger::DEBUG 20 | logger.formatter = proc do |severity, datetime, progname, msg| 21 | date_format = datetime.strftime("%Y-%m-%d %H:%M:%S") 22 | if severity == "INFO" 23 | "[#{date_format}] #{severity} (#{progname}): #{msg}\n".blue 24 | elsif severity == "WARN" 25 | "[#{date_format}] #{severity} (#{progname}): #{msg}\n".orange 26 | else 27 | "[#{date_format}] #{severity} (#{progname}): #{msg}\n".red 28 | end 29 | end 30 | 31 | DB << "SET CLIENT_ENCODING TO 'UTF8';" 32 | DB.loggers << logger if logger 33 | 34 | # Load app 35 | require "sinatra_graphql" 36 | run SinatraGraphql 37 | -------------------------------------------------------------------------------- /ruby/sinatra_graphql/config/db.yml: -------------------------------------------------------------------------------- 1 | # Sequel Database Configuration 2 | 3 | development: "postgres://gaurav@localhost/sinatra_graphql_development" 4 | test: "postgres://gaurav@localhost/sinatra_graphql_test" 5 | production: "postgres://gaurav@localhost/sinatra_graphql_production" 6 | 7 | -------------------------------------------------------------------------------- /ruby/sinatra_graphql/config/initializers/database.rb: -------------------------------------------------------------------------------- 1 | require "yaml" 2 | settings = YAML::load_file("config/db.yml") 3 | # Sequel Configuration 4 | DB = Sequel.connect(settings[ENV['RACK_ENV']]) 5 | -------------------------------------------------------------------------------- /ruby/sinatra_graphql/db/migrate/1_user.rb: -------------------------------------------------------------------------------- 1 | Sequel.migration do 2 | up do 3 | create_table(:users) do 4 | primary_key :id 5 | String :first_name, :null=>false 6 | String :last_name, :null=>false 7 | String :email, :null=>false 8 | String :username, :null=>false 9 | end 10 | end 11 | 12 | down do 13 | drop_table(:users) 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /ruby/sinatra_graphql/db/migrate/2_post.rb: -------------------------------------------------------------------------------- 1 | Sequel.migration do 2 | up do 3 | create_table(:posts) do 4 | primary_key :id 5 | String :title, :null=>false 6 | String :body, :null=>false 7 | foreign_key :user_id, :users 8 | end 9 | end 10 | 11 | down do 12 | drop_table(:posts) 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /ruby/sinatra_graphql/db/migrate/3_comment.rb: -------------------------------------------------------------------------------- 1 | Sequel.migration do 2 | up do 3 | create_table(:comments) do 4 | primary_key :id 5 | String :body, :null=>false 6 | foreign_key :user_id, :users 7 | foreign_key :post_id, :posts 8 | end 9 | end 10 | 11 | down do 12 | drop_table(:comments) 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /ruby/sinatra_graphql/db/seeds/20150928000000_seed.rb: -------------------------------------------------------------------------------- 1 | Sequel.seed do # Applies only to "development" and "test" environments 2 | def run 3 | [ 4 | ['John', 'Doe', 'john@doe.com', 'johndoe'], 5 | ['Maggie', 'Turner', 'maggie@turner.com', 'maggie'] 6 | ].each do |first_name, last_name, email, username| 7 | User.create first_name: first_name, last_name: last_name, email: email, username: username 8 | end 9 | 10 | [ 11 | ['First post title', 'First post body', 1], 12 | ['Second Post title', 'Second post body', 2] 13 | ].each do |title, body, user_id| 14 | Post.create title: title, body: body, user_id: user_id 15 | end 16 | 17 | [ 18 | ['First post comment body', 1, 1], 19 | ['Second Post comment body', 2, 2] 20 | ].each do |body, post_id, user_id| 21 | Comment.create body: body, post_id: post_id, user_id: user_id 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /ruby/sinatra_graphql/lib/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/ruby/sinatra_graphql/lib/.gitkeep -------------------------------------------------------------------------------- /ruby/sinatra_graphql/lib/api/node_identification.rb: -------------------------------------------------------------------------------- 1 | NodeIdentification = GraphQL::Relay::GlobalNodeIdentification.define do 2 | object_from_id -> (id, ctx) do 3 | type_name, id = NodeIdentification.from_global_id(id) 4 | Object.const_get(type_name).find(id) 5 | end 6 | 7 | type_from_object -> (object) do 8 | Schema.types[type_name(object)] 9 | end 10 | end 11 | 12 | def type_name(object) 13 | object.class.name 14 | end 15 | -------------------------------------------------------------------------------- /ruby/sinatra_graphql/lib/api/schema.rb: -------------------------------------------------------------------------------- 1 | require_relative 'types/post_type' 2 | require_relative 'node_identification' 3 | 4 | QueryType = GraphQL::ObjectType.define do 5 | name "Query" 6 | description "The query root of this schema" 7 | field :node, field: NodeIdentification.field 8 | 9 | field :post do 10 | type PostType 11 | argument :id, !types.ID 12 | resolve -> (obj, args, ctx) { Post.find(id: args["id"]) } 13 | end 14 | 15 | field :all_posts do 16 | type types[!PostType] 17 | resolve -> (obj, args, ctx) { Post.all } 18 | end 19 | end 20 | 21 | Schema = GraphQL::Schema.new( 22 | query: QueryType 23 | ) 24 | 25 | Schema.node_identification = NodeIdentification 26 | -------------------------------------------------------------------------------- /ruby/sinatra_graphql/lib/api/types/comment_type.rb: -------------------------------------------------------------------------------- 1 | CommentType = GraphQL::ObjectType.define do 2 | name "Comment" 3 | description "A comment" 4 | interfaces [NodeIdentification.interface] 5 | global_id_field :id 6 | 7 | field :id, !types.ID 8 | field :body, !types.String 9 | field :user, -> { UserType } 10 | field :post, -> { PostType } 11 | end 12 | -------------------------------------------------------------------------------- /ruby/sinatra_graphql/lib/api/types/post_type.rb: -------------------------------------------------------------------------------- 1 | PostType = GraphQL::ObjectType.define do 2 | name "Post" 3 | description "A post" 4 | interfaces [NodeIdentification.interface] 5 | global_id_field :id 6 | 7 | field :title, !types.String 8 | field :body, !types.String 9 | field :user, -> { UserType } 10 | field :comments, -> { types[!CommentType] } 11 | end 12 | -------------------------------------------------------------------------------- /ruby/sinatra_graphql/lib/api/types/user_type.rb: -------------------------------------------------------------------------------- 1 | UserType = GraphQL::ObjectType.define do 2 | name "User" 3 | description "A user" 4 | interfaces [NodeIdentification.interface] 5 | global_id_field :id 6 | 7 | field :first_name, !types.String 8 | field :last_name, !types.String 9 | field :username, !types.String 10 | field :email, !types.String 11 | field :posts, -> { types[!PostType] } 12 | field :comments, -> { types[!CommentType] } 13 | end 14 | -------------------------------------------------------------------------------- /ruby/sinatra_graphql/lib/models/comment.rb: -------------------------------------------------------------------------------- 1 | class Comment < Sequel::Model 2 | many_to_one :post 3 | many_to_one :user 4 | end 5 | -------------------------------------------------------------------------------- /ruby/sinatra_graphql/lib/models/post.rb: -------------------------------------------------------------------------------- 1 | class Post < Sequel::Model 2 | one_to_many :comments 3 | many_to_one :user 4 | end 5 | -------------------------------------------------------------------------------- /ruby/sinatra_graphql/lib/models/user.rb: -------------------------------------------------------------------------------- 1 | class User < Sequel::Model 2 | one_to_many :comments 3 | one_to_many :posts 4 | end 5 | -------------------------------------------------------------------------------- /ruby/sinatra_graphql/logs/common.log: -------------------------------------------------------------------------------- 1 | # Logfile created on 2016-06-01 10:43:07 +0100 by logger.rb/54362 2 | -------------------------------------------------------------------------------- /ruby/sinatra_graphql/logs/output.log: -------------------------------------------------------------------------------- 1 | [2016-06-01 10:43:08] INFO WEBrick 1.3.1 2 | [2016-06-01 10:43:08] INFO ruby 2.3.1 (2016-04-26) [x86_64-darwin15] 3 | [2016-06-01 10:43:08] INFO WEBrick::HTTPServer#start: pid=23992 port=3000 4 | [2016-06-01 10:44:07] INFO going to shutdown ... 5 | [2016-06-01 10:44:07] INFO WEBrick::HTTPServer#start done. 6 | -------------------------------------------------------------------------------- /ruby/sinatra_graphql/middlewares/pass_auth_token.rb: -------------------------------------------------------------------------------- 1 | # Inject authorization token for root route 2 | # Because we don't have it 3 | # For real app you would use generally some kind of authentication 4 | 5 | class PassAuthToken 6 | def initialize(app) 7 | @app = app 8 | end 9 | 10 | def call(env) 11 | data = {user_id: 1} # Anything you want to encode 12 | token = Rack::JWT::Token.encode(data, 'super_secret_key', 'HS256') 13 | if env['REQUEST_PATH'] == '/' 14 | env['HTTP_AUTHORIZATION'] = "Bearer #{token}" 15 | end 16 | @app.call(env) 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /ruby/sinatra_graphql/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/ruby/sinatra_graphql/public/favicon.ico -------------------------------------------------------------------------------- /ruby/sinatra_graphql/public/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/ruby/sinatra_graphql/public/images/.gitkeep -------------------------------------------------------------------------------- /ruby/sinatra_graphql/public/images/hazel_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/ruby/sinatra_graphql/public/images/hazel_icon.png -------------------------------------------------------------------------------- /ruby/sinatra_graphql/public/images/hazel_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/ruby/sinatra_graphql/public/images/hazel_small.png -------------------------------------------------------------------------------- /ruby/sinatra_graphql/public/javascripts/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/ruby/sinatra_graphql/public/javascripts/.gitkeep -------------------------------------------------------------------------------- /ruby/sinatra_graphql/public/javascripts/application.js: -------------------------------------------------------------------------------- 1 | //= require ./react-15.0.1 2 | //= require ./react-dom-15.0.1 3 | //= require ./fetch-0.10.1 4 | //= require ./graphiql-0.7.0 5 | -------------------------------------------------------------------------------- /ruby/sinatra_graphql/public/stylesheets/application.css: -------------------------------------------------------------------------------- 1 | 2 | @import "graphiql-0.7.0.css"; 3 | @import "main.css"; 4 | 5 | html, body { 6 | height: 100%; 7 | margin: 0; 8 | overflow: hidden; 9 | width: 100%; 10 | } 11 | -------------------------------------------------------------------------------- /ruby/sinatra_graphql/sinatra_graphql.rb: -------------------------------------------------------------------------------- 1 | require 'rack/protection' 2 | 3 | class SinatraGraphql < Sinatra::Base 4 | set public_folder: 'public', static: true 5 | use Rack::Session::Cookie, secret: 'super_secret_key' 6 | use Rack::Protection 7 | use Rack::Protection::RemoteReferrer 8 | use PassAuthToken 9 | use Rack::JWT::Auth, {secret: 'super_secret_key', exclude: %w(/javascripts /stylesheets), options: { algorithm: 'HS256' }} 10 | 11 | get '/' do 12 | data = {user_id: 1} 13 | token = Rack::JWT::Token.encode(data, 'super_secret_key', 'HS256') 14 | puts token 15 | erb :graphiql, locals: {token: token} 16 | end 17 | 18 | post '/graphql' do 19 | params = JSON.parse(request.body.read) 20 | result = Schema.execute( 21 | params['query'], 22 | variables: params['variables'] 23 | ) 24 | content_type :json 25 | result.to_json 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /scala/README.md: -------------------------------------------------------------------------------- 1 | # Scala based web frameworks 2 | 3 | A set of GraphQL server implementation on popular Scala web frameworks. 4 | -------------------------------------------------------------------------------- /scala/play_grapgql/.gitignore: -------------------------------------------------------------------------------- 1 | logs 2 | target 3 | /.idea 4 | /.idea_modules 5 | /.classpath 6 | /.project 7 | /.settings 8 | /RUNNING_PID 9 | -------------------------------------------------------------------------------- /scala/play_grapgql/LICENSE: -------------------------------------------------------------------------------- 1 | This software is licensed under the Apache 2 license, quoted below. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use this project except in compliance with 4 | the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. 5 | 6 | Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 7 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific 8 | language governing permissions and limitations under the License. -------------------------------------------------------------------------------- /scala/play_grapgql/README: -------------------------------------------------------------------------------- 1 | This is your new Play application 2 | ================================= 3 | 4 | This file will be packaged with your application when using `activator dist`. 5 | 6 | There are several demonstration files available in this template. 7 | 8 | Controllers 9 | =========== 10 | 11 | - HomeController.scala: 12 | 13 | Shows how to handle simple HTTP requests. 14 | 15 | - AsyncController.scala: 16 | 17 | Shows how to do asynchronous programming when handling a request. 18 | 19 | - CountController.scala: 20 | 21 | Shows how to inject a component into a controller and use the component when 22 | handling requests. 23 | 24 | Components 25 | ========== 26 | 27 | - Module.scala: 28 | 29 | Shows how to use Guice to bind all the components needed by your application. 30 | 31 | - Counter.scala: 32 | 33 | An example of a component that contains state, in this case a simple counter. 34 | 35 | - ApplicationTimer.scala: 36 | 37 | An example of a component that starts when the application starts and stops 38 | when the application stops. 39 | 40 | Filters 41 | ======= 42 | 43 | - Filters.scala: 44 | 45 | Creates the list of HTTP filters used by your application. 46 | 47 | - ExampleFilter.scala 48 | 49 | A simple filter that adds a header to every response. -------------------------------------------------------------------------------- /scala/play_grapgql/app/Filters.scala: -------------------------------------------------------------------------------- 1 | import javax.inject._ 2 | import play.api._ 3 | import play.api.http.HttpFilters 4 | import play.api.mvc._ 5 | 6 | import filters.ExampleFilter 7 | 8 | /** 9 | * This class configures filters that run on every request. This 10 | * class is queried by Play to get a list of filters. 11 | * 12 | * Play will automatically use filters from any class called 13 | * `Filters` that is placed the root package. You can load filters 14 | * from a different class by adding a `play.http.filters` setting to 15 | * the `application.conf` configuration file. 16 | * 17 | * @param env Basic environment settings for the current application. 18 | * @param exampleFilter A demonstration filter that adds a header to 19 | * each response. 20 | */ 21 | @Singleton 22 | class Filters @Inject() ( 23 | env: Environment, 24 | exampleFilter: ExampleFilter) extends HttpFilters { 25 | 26 | override val filters = { 27 | // Use the example filter if we're running development mode. If 28 | // we're running in production or test mode then don't use any 29 | // filters at all. 30 | if (env.mode == Mode.Dev) Seq(exampleFilter) else Seq.empty 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /scala/play_grapgql/app/Module.scala: -------------------------------------------------------------------------------- 1 | import com.google.inject.AbstractModule 2 | import java.time.Clock 3 | 4 | import services.{ApplicationTimer, AtomicCounter, Counter} 5 | 6 | /** 7 | * This class is a Guice module that tells Guice how to bind several 8 | * different types. This Guice module is created when the Play 9 | * application starts. 10 | 11 | * Play will automatically use any class called `Module` that is in 12 | * the root package. You can create modules in other locations by 13 | * adding `play.modules.enabled` settings to the `application.conf` 14 | * configuration file. 15 | */ 16 | class Module extends AbstractModule { 17 | 18 | override def configure() = { 19 | // Use the system clock as the default implementation of Clock 20 | bind(classOf[Clock]).toInstance(Clock.systemDefaultZone) 21 | // Ask Guice to create an instance of ApplicationTimer when the 22 | // application starts. 23 | bind(classOf[ApplicationTimer]).asEagerSingleton() 24 | // Set AtomicCounter as the implementation for Counter. 25 | bind(classOf[Counter]).to(classOf[AtomicCounter]) 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /scala/play_grapgql/app/controllers/CountController.scala: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import javax.inject._ 4 | import play.api._ 5 | import play.api.mvc._ 6 | 7 | import services.Counter 8 | 9 | /** 10 | * This controller demonstrates how to use dependency injection to 11 | * bind a component into a controller class. The class creates an 12 | * `Action` that shows an incrementing count to users. The [[Counter]] 13 | * object is injected by the Guice dependency injection system. 14 | */ 15 | @Singleton 16 | class CountController @Inject() (counter: Counter) extends Controller { 17 | 18 | /** 19 | * Create an action that responds with the [[Counter]]'s current 20 | * count. The result is plain text. This `Action` is mapped to 21 | * `GET /count` requests by an entry in the `routes` config file. 22 | */ 23 | def count = Action { Ok(counter.nextCount().toString) } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /scala/play_grapgql/app/controllers/HomeController.scala: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import javax.inject._ 4 | import play.api._ 5 | import play.api.mvc._ 6 | 7 | /** 8 | * This controller creates an `Action` to handle HTTP requests to the 9 | * application's home page. 10 | */ 11 | @Singleton 12 | class HomeController @Inject() extends Controller { 13 | 14 | /** 15 | * Create an Action to render an HTML page with a welcome message. 16 | * The configuration in the `routes` file means that this method 17 | * will be called when the application receives a `GET` request with 18 | * a path of `/`. 19 | */ 20 | def index = Action { 21 | Ok(views.html.index("Your new application is ready.")) 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /scala/play_grapgql/app/filters/ExampleFilter.scala: -------------------------------------------------------------------------------- 1 | package filters 2 | 3 | import akka.stream.Materializer 4 | import javax.inject._ 5 | import play.api.mvc._ 6 | import scala.concurrent.{ExecutionContext, Future} 7 | 8 | /** 9 | * This is a simple filter that adds a header to all requests. It's 10 | * added to the application's list of filters by the 11 | * [[ExampleFilters]] class. 12 | * 13 | * @param mat This object is needed to handle streaming of requests 14 | * and responses. 15 | * @param exec This class is needed to execute code asynchronously. 16 | * It is used below by the `map` method. 17 | */ 18 | @Singleton 19 | class ExampleFilter @Inject()( 20 | implicit override val mat: Materializer, 21 | exec: ExecutionContext) extends Filter { 22 | 23 | override def apply(nextFilter: RequestHeader => Future[Result]) 24 | (requestHeader: RequestHeader): Future[Result] = { 25 | // Run the next filter in the chain. This will call other filters 26 | // and eventually call the action. Take the result and modify it 27 | // by adding a new header. 28 | nextFilter(requestHeader).map { result => 29 | result.withHeaders("X-ExampleFilter" -> "foo") 30 | } 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /scala/play_grapgql/app/services/Counter.scala: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | import java.util.concurrent.atomic.AtomicInteger 4 | import javax.inject._ 5 | 6 | /** 7 | * This trait demonstrates how to create a component that is injected 8 | * into a controller. The trait represents a counter that returns a 9 | * incremented number each time it is called. 10 | */ 11 | trait Counter { 12 | def nextCount(): Int 13 | } 14 | 15 | /** 16 | * This class is a concrete implementation of the [[Counter]] trait. 17 | * It is configured for Guice dependency injection in the [[Module]] 18 | * class. 19 | * 20 | * This class has a `Singleton` annotation because we need to make 21 | * sure we only use one counter per application. Without this 22 | * annotation we would get a new instance every time a [[Counter]] is 23 | * injected. 24 | */ 25 | @Singleton 26 | class AtomicCounter extends Counter { 27 | private val atomicCounter = new AtomicInteger() 28 | override def nextCount(): Int = atomicCounter.getAndIncrement() 29 | } 30 | -------------------------------------------------------------------------------- /scala/play_grapgql/app/views/index.scala.html: -------------------------------------------------------------------------------- 1 | @* 2 | * This template takes a single argument, a String containing a 3 | * message to display. 4 | *@ 5 | @(message: String) 6 | 7 | @* 8 | * Call the `main` template with two arguments. The first 9 | * argument is a `String` with the title of the page, the second 10 | * argument is an `Html` object containing the body of the page. 11 | *@ 12 | @main("Welcome to Play") { 13 | 14 | @* 15 | * Get an `Html` object by calling the built-in Play welcome 16 | * template and passing a `String` message. 17 | *@ 18 | @play20.welcome(message, style = "Scala") 19 | 20 | } 21 | -------------------------------------------------------------------------------- /scala/play_grapgql/app/views/main.scala.html: -------------------------------------------------------------------------------- 1 | @* 2 | * This template is called from the `index` template. This template 3 | * handles the rendering of the page header and body tags. It takes 4 | * two arguments, a `String` for the title of the page and an `Html` 5 | * object to insert into the body of the page. 6 | *@ 7 | @(title: String)(content: Html) 8 | 9 | 10 | 11 | 12 | @* Here's where we render the page title `String`. *@ 13 | @title 14 | 15 | 16 | 17 | 18 | 19 | @* And here's where we render the `Html` object containing 20 | * the page content. *@ 21 | @content 22 | 23 | 24 | -------------------------------------------------------------------------------- /scala/play_grapgql/build.sbt: -------------------------------------------------------------------------------- 1 | name := """play_grapgql""" 2 | 3 | version := "1.0-SNAPSHOT" 4 | 5 | lazy val root = (project in file(".")).enablePlugins(PlayScala) 6 | 7 | scalaVersion := "2.11.7" 8 | 9 | libraryDependencies ++= Seq( 10 | jdbc, 11 | cache, 12 | ws, 13 | "org.sangria-graphql" %% "sangria" % "0.6.3", 14 | "org.scalatestplus.play" %% "scalatestplus-play" % "1.5.1" % Test 15 | ) 16 | 17 | resolvers += "scalaz-bintray" at "http://dl.bintray.com/scalaz/releases" 18 | -------------------------------------------------------------------------------- /scala/play_grapgql/conf/routes: -------------------------------------------------------------------------------- 1 | # Routes 2 | # This file defines all application routes (Higher priority routes first) 3 | # ~~~~ 4 | 5 | # An example controller showing a sample home page 6 | GET / controllers.HomeController.index 7 | # An example controller showing how to use dependency injection 8 | GET /count controllers.CountController.count 9 | # An example controller showing how to write asynchronous code 10 | GET /message controllers.AsyncController.message 11 | 12 | # Map static resources from the /public folder to the /assets URL path 13 | GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset) 14 | -------------------------------------------------------------------------------- /scala/play_grapgql/libexec/activator-launch-1.3.10.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/scala/play_grapgql/libexec/activator-launch-1.3.10.jar -------------------------------------------------------------------------------- /scala/play_grapgql/project/build.properties: -------------------------------------------------------------------------------- 1 | #Activator-generated Properties 2 | #Mon May 23 04:30:52 BST 2016 3 | template.uuid=15c371e1-78e0-429a-84ff-11b1d09dd4a2 4 | sbt.version=0.13.11 5 | -------------------------------------------------------------------------------- /scala/play_grapgql/project/plugins.sbt: -------------------------------------------------------------------------------- 1 | // The Play plugin 2 | addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.5.3") 3 | 4 | // web plugins 5 | 6 | addSbtPlugin("com.typesafe.sbt" % "sbt-coffeescript" % "1.0.0") 7 | 8 | addSbtPlugin("com.typesafe.sbt" % "sbt-less" % "1.1.0") 9 | 10 | addSbtPlugin("com.typesafe.sbt" % "sbt-jshint" % "1.0.3") 11 | 12 | addSbtPlugin("com.typesafe.sbt" % "sbt-rjs" % "1.0.7") 13 | 14 | addSbtPlugin("com.typesafe.sbt" % "sbt-digest" % "1.1.0") 15 | 16 | addSbtPlugin("com.typesafe.sbt" % "sbt-mocha" % "1.1.0") 17 | 18 | addSbtPlugin("org.irundaia.sbt" % "sbt-sassify" % "1.4.2") 19 | -------------------------------------------------------------------------------- /scala/play_grapgql/public/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/scala/play_grapgql/public/images/favicon.png -------------------------------------------------------------------------------- /scala/play_grapgql/public/javascripts/hello.js: -------------------------------------------------------------------------------- 1 | if (window.console) { 2 | console.log("Welcome to your Play application's JavaScript!"); 3 | } 4 | -------------------------------------------------------------------------------- /scala/play_grapgql/public/stylesheets/main.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravtiwari/graphql-server-examples/8f993d4507c5738ab5d1d81c3d43b74f748c8d05/scala/play_grapgql/public/stylesheets/main.css -------------------------------------------------------------------------------- /scala/play_grapgql/test/ApplicationSpec.scala: -------------------------------------------------------------------------------- 1 | import org.scalatestplus.play._ 2 | import play.api.test._ 3 | import play.api.test.Helpers._ 4 | 5 | /** 6 | * Add your spec here. 7 | * You can mock out a whole application including requests, plugins etc. 8 | * For more information, consult the wiki. 9 | */ 10 | class ApplicationSpec extends PlaySpec with OneAppPerTest { 11 | 12 | "Routes" should { 13 | 14 | "send 404 on a bad request" in { 15 | route(app, FakeRequest(GET, "/boum")).map(status(_)) mustBe Some(NOT_FOUND) 16 | } 17 | 18 | } 19 | 20 | "HomeController" should { 21 | 22 | "render the index page" in { 23 | val home = route(app, FakeRequest(GET, "/")).get 24 | 25 | status(home) mustBe OK 26 | contentType(home) mustBe Some("text/html") 27 | contentAsString(home) must include ("Your new application is ready.") 28 | } 29 | 30 | } 31 | 32 | "CountController" should { 33 | 34 | "return an increasing count" in { 35 | contentAsString(route(app, FakeRequest(GET, "/count")).get) mustBe "0" 36 | contentAsString(route(app, FakeRequest(GET, "/count")).get) mustBe "1" 37 | contentAsString(route(app, FakeRequest(GET, "/count")).get) mustBe "2" 38 | } 39 | 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /scala/play_grapgql/test/IntegrationSpec.scala: -------------------------------------------------------------------------------- 1 | import org.scalatestplus.play._ 2 | import play.api.test._ 3 | import play.api.test.Helpers._ 4 | 5 | /** 6 | * add your integration spec here. 7 | * An integration test will fire up a whole play application in a real (or headless) browser 8 | */ 9 | class IntegrationSpec extends PlaySpec with OneServerPerTest with OneBrowserPerTest with HtmlUnitFactory { 10 | 11 | "Application" should { 12 | 13 | "work from within a browser" in { 14 | 15 | go to ("http://localhost:" + port) 16 | 17 | pageSource must include ("Your new application is ready.") 18 | } 19 | } 20 | } 21 | --------------------------------------------------------------------------------