{"id":13879755,"url":"https://github.com/yuki24/artemis","last_synced_at":"2025-05-15T07:06:32.648Z","repository":{"id":33150560,"uuid":"150367928","full_name":"yuki24/artemis","owner":"yuki24","description":"Ruby GraphQL client on Rails that actually makes you more productive","archived":false,"fork":false,"pushed_at":"2024-12-04T23:10:21.000Z","size":2574,"stargazers_count":207,"open_issues_count":11,"forks_count":15,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-05-09T02:47:49.033Z","etag":null,"topics":["graphql","graphql-client","http2","rails","ruby"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yuki24.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-09-26T04:19:30.000Z","updated_at":"2025-04-23T13:14:51.000Z","dependencies_parsed_at":"2023-01-14T23:45:34.687Z","dependency_job_id":"b8cef973-0bd4-40c3-91db-7319110babdf","html_url":"https://github.com/yuki24/artemis","commit_stats":{"total_commits":239,"total_committers":9,"mean_commits":"26.555555555555557","dds":"0.20083682008368198","last_synced_commit":"936cdaab0bee1071a6a7dde464b48281057d42be"},"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yuki24%2Fartemis","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yuki24%2Fartemis/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yuki24%2Fartemis/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yuki24%2Fartemis/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yuki24","download_url":"https://codeload.github.com/yuki24/artemis/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254292042,"owners_count":22046426,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["graphql","graphql-client","http2","rails","ruby"],"created_at":"2024-08-06T08:02:31.679Z","updated_at":"2025-05-15T07:06:27.638Z","avatar_url":"https://github.com/yuki24.png","language":"Ruby","funding_links":[],"categories":["Ruby"],"sub_categories":[],"readme":"# Artemis [![build](https://github.com/yuki24/artemis/actions/workflows/ruby.yml/badge.svg)](https://github.com/yuki24/artemis/actions/workflows/ruby.yml) [![Gem Version](https://badge.fury.io/rb/artemis.svg)](https://rubygems.org/gems/artemis)\n\nArtemis is a GraphQL client that is designed to fit well on Rails.\n\n * **Convention over Configuration**: You'll never have to make trivial decisions or spend time on boring setup. Start\n  making a GraphQL request in literally 30s.\n * **Performant by default**: You can't do wrong when it comes to performance. All GraphQL files are pre-loaded only\n  once in production and it'll never affect runtime performance. Comes with options that enable persistent connections\n   and even HTTP/2, the next-gen high-performance protocol.\n * **First-class support for testing**: Testing and stubbing GraphQL requests couldn't be simpler. No need to add\n  external dependencies to test well.\n\n\u003cimg width=\"24\" height=\"24\" src=\"https://avatars1.githubusercontent.com/u/541332?s=48\u0026amp;v=4\"\u003e Battle-tested at [Artsy](https://www.artsy.net)\n\n![graphql-client vs Artemis](https://raw.githubusercontent.com/yuki24/artemis/master/banner.png \"graphql-client vs Artemis\")\n\n## Getting started\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'artemis'\n```\n\nOnce you run `bundle install` on your Rails app, run the install command:\n\n\n```sh\n$ rails g artemis:install artsy https://metaphysics-production.artsy.net/\n\n# or if you need to specify the `--authorization` header:\n$ rails g artemis:install github https://api.github.com/graphql --authorization 'token ...'\n```\n\n### Generating your first query\n\nArtemis comes with a query generator. For exmaple, you could use the query generator to generate a query stub for `artist`:\n\n```sh\n$ rails g artemis:query artist\n```\n\nThen this will generate:\n\n```graphql\n# app/operations/artist.graphql\nquery($id: String!) {\n  artist(id: $id) {\n    # Add fields here...\n  }\n}\n```\n\nThen you could call the class method that has the matching name `artist`:\n\n```ruby\nArtsy.artist(id: \"pablo-picasso\")\n# =\u003e makes a GraphQL query that's in app/operations/artist.graphql\n```\n\nYou can also specify a file name:\n\n```sh\n$ rails g artemis:query artist artist_details_on_artwork\n# =\u003e generates app/operations/artist_details_on_artwork.graphql\n```\n\nThen you can make a query in `artist_details_on_artwork.graphql` with:\n\n```ruby\nArtsy.artist_details_on_artwork(id: \"pablo-picasso\")\n```\n\n## The convention\n\nArtemis assumes that the files related to GraphQL are organized in a certain way. For example, a service that talks to Artsy's GraphQL API could have the following structure:\n\n```\n├──app/operations\n│   ├── artsy\n│   │   ├── _artist_fragment.graphql\n│   │   ├── artwork.graphql\n│   │   ├── artist.graphql\n│   │   └── artists.graphql\n│   └── artsy.rb\n├──config/graphql.yml\n├──test/fixtures/graphql\n│   └── artsy\n│       ├── artwork.yml\n│       ├── artist.yml\n│       └── artists.yml\n└──vendor/graphql/schema/artsy.json\n```\n\n### Fragments\nFragments are defined in defined in a standard way in a file named `_artwork_fragment.graphql` with the standard convention:\n\n```graphql\nfragment on Artwork {\n  id,\n  name,\n  artist_id\n  # other artwork fields here\n}\n```\n\nThe way of calling an Artemis fragment on other queries or models is with a **Rails convention**. Let us suppose we have the Artist model and its corresponding artwork. The way of nesting or calling the artwork on the artist model would look like this:\n\n```graphql\nfragment on Artist {\n  id,\n  name,\n  artworks {\n    ...Artsy::ArtworkFragment\n  }\n}\n```\n\nWhere `Artsy` is the name of the folder/module.\n\n## Callbacks\n\nYou can use the `before_execute` callback to intercept outgoing requests and the `after_execute` callback to observe the\nresponse. A common operation that's done in the `before_execute` hook is assigning a token to the header:\n\n```ruby\nclass Artsy \u003c Artemis::Client\n  before_execute do |document, operation_name, variables, context|\n    context[:headers] = {\n      Authorization: \"token ...\"\n    }\n  end\nend\n```\n\nHere the `:headers` key is a special context type. The hash object assigned to the `context[:headers]` will be sent as\nthe HTTP headers of the request.\n\nAnother common thing when receiving a response is to check if there's any error in the response and throw and error\naccordingly:\n\n```ruby\nclass Artsy \u003c Artemis::Client\n  after_execute do |data, errors, extensions|\n    raise \"GraphQL error: #{errors.to_json}\" if errors.present?\n  end\nend\n```\n\n## Multi domain support\n\nServices like Shopify provide\n[a different endpoint per customer](https://shopify.dev/api/admin/graphql/reference#graphql-endpoint) (e.g.\n`https://{shop}.myshopify.com`). In order to switch the endpoint on a per-request basis, you will have to use the\n`:multi_domain` adapter. This is a wrapper adapter that relies on an actual HTTP adapter such as `:net_http` and\n`:curb` so that e.g. it can maintain multiple connections for each endpoint if necessary. This could be configured\nas shown below:\n\n```yaml\ndefault: \u0026default\n  # Specify the :multi_domain adapter:\n  adapter: :multi_domain\n\n  # Other configurations such as `timeout` and `pool_size` are passed down to the underlying adapter:\n  timeout: 10\n  pool_size: 25\n\n  # Additional adapter-specific configurations could be configured as `adapter_options`:\n  adapter_options:\n    # Here you can configure the actual adapter to use. By default, it is set to :net_http. Available adapters are\n    # :net_http, :net_http_persistent, :curb, and :test. You can not nest the use of the `:multi_domain` adapter.\n    adapter: :net_http\n\ndevelopment:\n  shopify:\n    \u003c\u003c: *default\n\n...\n```\n\nUpon making a request you will also have to specify the `url` option:\n\n```ruby\n# Makes a request to https://myawesomeshop.myshopify.com:\nShopify.with_context(url: \"https://myawesomeshop.myshopify.com\").product(id: \"...\")\n```\n\n## Configuration\n\nYou can configure the GraphQL client using the following options. Those configurations are found in the\n`config/graphql.yml`.\n\n| Name          | Required? | Default     | Description |\n| ------------- | --------- | ------------| ----------- |\n| `adapter`     | No        | `:net_http` | The underlying client library that actually makes an HTTP request. See Adapters for available options.\n| `pool_size`   | No        | 25          | The number of keep-alive connections. The `:net_http` adapter will ignore this option.\n| `schema_path` | No        | See above   | The path to the GrapQL schema. Setting an empty value to this will force the client to download the schema upon the first request.\n| `timeout`     | No        | 10          | HTTP timeout set for the adapter in seconds. This will be set to both `read_timeout` and `write_timeout` and there is no way to configure them with a different value as of writing (PRs welcome!)\n| `url`         | Yes       | N/A         | The URL for the GraphQL endpoint.\n\n### Adapters\n\nThere are four adapter options available. Choose the adapter that best fits on your use case.\n\n| Adapter                | Protocol                 | Keep-alive  | Performance | Dependencies |\n| ---------------------- | ------------------------ | ----------- | ----------- | ------------ |\n| `:curb`                | HTTP/1.1, **HTTP/2**     | **Yes**     | **Fastest** | [`curb 0.9.6+`][curb]\u003cbr\u003e[`libcurl 7.64.0+`][curl]\u003cbr\u003e[`nghttp2 1.0.0+`][nghttp]\n| `:net_http` (default)  | HTTP/1.1 only            | No          | Slow        | **None**\n| `:net_http_persistent` | HTTP/1.1 only            | **Yes**     | **Fast**    | [`net-http-persistent 3.0.0+`][nhp]\n| `:multi_domain`        | See [multi domain support](#multi-domain-support)\n| `:test`                | See [Testing](#testing)\n\n#### Third-party adapters\n\nThis is a comminuty-maintained adapter. Want to add yours? Send us a pull request!\n\n| Adapter                | Description |\n| ---------------------- | ------------|\n| [`:net_http_hmac`](https://github.com/JanStevens/artemis-api-auth/tree/master)      | provides a new Adapter for the Artemis GraphQL ruby client to support HMAC Authentication using [ApiAuth](https://github.com/mgomes/api_auth). |\n\n#### Writing your own adapter\n\nWhen the built-in adapters do not satisfy your needs, you may want to implement your own adapter. You could do so by following the steps below. Let's implement the [`:net_http_hmac`](https://github.com/JanStevens/artemis-api-auth/tree/master) adapter as an example.\n\n 1. Define `NetHttpHmacAdapter` under the `Artemis::Adapters` namespace and implement [the `#execute` method](https://github.com/github/graphql-client/blob/master/guides/remote-queries.md):\n\n    ```ruby\n    # lib/artemis/adapters/net_http_hmac_adapter.rb\n    module Artemis::Adapters\n      class NetHttpHmacAdapter\n        def execute(document:, operation_name: nil, variables: {}, context: {})\n          # Makes an HTTP request for GraphQL query.\n        end\n      end\n    end\n    ```\n\n 2. Load the adapter in `config/initializers/artemis.rb` (or any place that gets loaded before Rails runs initializers):\n\n    ```ruby\n    require 'artemis/adapters/net_http_hmac_adapter'\n    ```\n\n 3. Specify the adapter name in `config/graphql.yml`:\n\n    ```yml\n    default: \u0026default\n      adapter: :net_http_hmac\n    ```\n\n## Rake tasks\n\nArtemis also adds a useful `rake graphql:schema:update` rake task that downloads the GraphQL schema using the\n`Introspection` query.\n\n### `graphql:schema:update`\n\nDownloads and saves the GraphQL schema.\n\n| Option Name        | Description |\n| ------------------ | ------------|\n| `SERVICE`          | Service name the schema is downloaded from.| \n| `AUTHORIZATION`    | HTTP `Authorization` header value used to download the schema with.|\n\n\n#### Examples\n\n```\n$ rake graphql:schema:update\n# =\u003e downloads schema from the service. fails if there are multiple services in config/graphql.yml.\n\n$ rake graphql:schema:update SERVICE=github AUTHORIZATION=\"token ...\"\n# =\u003e downloads schema from the `github` service using the HTTP header \"AUTHORIZATION: token ...\"\n```\n\n## Testing\n\nGiven that you have `app/operations/artsy/artist.graphql` and fixture file for the `artist.yml`:\n\n```yml\n# test/fixtures/graphql/artist.yml:\nleonardo_da_vinci:\n  data:\n    artist:\n      name: Leonardo da Vinci\n      birthday: 1452/04/15\n\nyayoi_kusama:\n  data:\n    artist:\n      name: Yayoi Kusama\n      birthday: 1929/03/22\n```\n\nThen you can stub the request with the `stub_graphql` DSL:\n\n```ruby\nstub_graphql(Artsy, :artist, id: \"yayoi-kusama\").to_return(:yayoi_kusama)\nstub_graphql(Artsy, :artist, id: \"leonardo-da-vinci\").to_return(:leonardo_da_vinci)\n\nyayoi_kusama = Artsy.artist(id: \"yayoi-kusama\")\nyayoi_kusama.data.artist.name     # =\u003e \"Yayoi Kusama\"\nyayoi_kusama.data.artist.birthday # =\u003e \"1452/04/15\"\n\nda_vinci = Artsy.artist(id: \"leonardo-da-vinci\")\nda_vinci.data.artist.name     # =\u003e \"Leonardo da Vinci\"\nda_vinci.data.artist.birthday # =\u003e \"1452/04/15\"\n```\n\nYou can also use JSON instead of YAML. See [example fixtures](https://github.com/yuki24/artemis/tree/master/spec/fixtures/responses)\nand [test cases](https://github.com/yuki24/artemis/blob/master/spec/test_helper_spec.rb#L16-L51).\n\n### MiniTest\n\nSetting up the test helper with Artemis is very easy and simple. Just add the following code to the\n`test/test_helper.rb` in your app:\n\n```ruby\n# spec/test_helper.rb\nrequire 'artemis/test_helper'\n\nclass ActiveSupport::TestCase\n  setup do\n    graphql_requests.clear\n    graphql_responses.clear\n  end\nend\n```\n\n### RSpec\n\nArtemis also comes with a script that wires up helper methods on Rspec. Because it is more common to use the `spec/`\ndirectory to organize spec files in RSpec, the `config.artemis.fixture_path` config needs to point to\n`spec/fixtures/graphql`. Other than that, it is very straightforward to set it up:\n\n```ruby\n# config/application.rb\nconfig.artemis.fixture_path = 'spec/fixtures/graphql'\n```\n\n```ruby\n# Add this to your spec/rails_helper.rb or spec_helper.rb if you don't have rails_helper.rb\nrequire 'artemis/rspec'\n```\n\n## Development\n\nAfter checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.\n\nTo install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at https://github.com/yuki24/artemis. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).\n\n## Code of Conduct\n\nEveryone interacting in the Artemis project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/artemis/blob/master/CODE_OF_CONDUCT.md).\n\n[curb]: https://rubygems.org/gems/curb\n[curl]: https://curl.haxx.se/docs/http2.html\n[nghttp]: https://nghttp2.org/\n[nhp]: https://rubygems.org/gems/net-http-persistent\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyuki24%2Fartemis","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyuki24%2Fartemis","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyuki24%2Fartemis/lists"}