Unofficial Discourse GraphQL API Plugin

discourse-graphql - https://github.com/tgxworld/discourse-graphql

Hi all, I’ll like to share the discourse-graphql plugin which I’ve been working on recently as a personal project. The plugin is still a work in progress as there are only 3 query fields being exposed. Since I personally don’t use the Discourse API for integration, I’ll like to hear from potential users what queries or mutations you’ll like to see added to the plugin. Simply provide me with your use case and what fields you’re looking for in this topic so that I can add it to the plugin.

20 Likes

Hi @tgxworld, very interesting stuff.
As you already working in this direction - what do you think about
https://github.com/dosco/super-graph

Vikram Rangnekar - Super Graph an instant GraphQL API service in Go - YouTube

Or is it a crazy idea to use it with Discourse?
AFAIK it works with Rails in nice way, including Rails authentication supported (Redis, Memcache, Cookie). And it can be integrated in existing Rails apps, but I’m not sure if it is realistic to use it within a plugin.

What do you think?

Hi @4ong :wave:

Super Graph looks interesting but I’m not sure if it’ll fit our needs here. The main problem I see is that the SQL queries that we need to generate is not straight forward and can involve many conditional paths. Those conditions are probably not easy to express with just a GraphQL query.

3 Likes

Dear Alex,

Thank you for sharing this plugin. I learned a lot from reading your plugin code and how you approached this.

Bookmarked!

Thanks again.

Thank you, I think this plugin will be a great help for some custom GraphQL endpoints I need in my Discourse instance.

However, Discourse responds with 502 Bad Gateway after rebuilding.

Here are the logs.

Logs
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/zeitwerk-2.4.2/lib/zeitwerk/loader/callbacks.rb:18:in `on_file_autoloaded': expected file /var/www/discourse/plugins/discourse-graphql/app/graphql/loaders/record_loader.rb to define constant Loaders::RecordLoader, but didn't (Zeitwerk::NameError)
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/zeitwerk-2.4.2/lib/zeitwerk/kernel.rb:27:in `block in require'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/zeitwerk-2.4.2/lib/zeitwerk/kernel.rb:26:in `tap'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/zeitwerk-2.4.2/lib/zeitwerk/kernel.rb:26:in `require'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/bootsnap-1.5.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:53:in `require_relative'
	from /var/www/discourse/plugins/discourse-graphql/app/graphql/discourse_schema.rb:3:in `<main>'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/bootsnap-1.5.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/bootsnap-1.5.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/bootsnap-1.5.1/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/bootsnap-1.5.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/bootsnap-1.5.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in `require'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/zeitwerk-2.4.2/lib/zeitwerk/kernel.rb:26:in `require'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/zeitwerk-2.4.2/lib/zeitwerk/loader.rb:409:in `const_get'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/zeitwerk-2.4.2/lib/zeitwerk/loader.rb:409:in `block (2 levels) in eager_load'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/zeitwerk-2.4.2/lib/zeitwerk/loader.rb:733:in `block in ls'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/zeitwerk-2.4.2/lib/zeitwerk/loader.rb:725:in `foreach'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/zeitwerk-2.4.2/lib/zeitwerk/loader.rb:725:in `ls'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/zeitwerk-2.4.2/lib/zeitwerk/loader.rb:404:in `block in eager_load'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/zeitwerk-2.4.2/lib/zeitwerk/loader.rb:393:in `synchronize'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/zeitwerk-2.4.2/lib/zeitwerk/loader.rb:393:in `eager_load'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/zeitwerk-2.4.2/lib/zeitwerk/loader.rb:508:in `each'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/zeitwerk-2.4.2/lib/zeitwerk/loader.rb:508:in `eager_load_all'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/railties-6.0.3.3/lib/rails/application/finisher.rb:122:in `block in <module:Finisher>'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/railties-6.0.3.3/lib/rails/initializable.rb:32:in `instance_exec'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/railties-6.0.3.3/lib/rails/initializable.rb:32:in `run'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/railties-6.0.3.3/lib/rails/initializable.rb:61:in `block in run_initializers'
	from /usr/local/lib/ruby/2.7.0/tsort.rb:228:in `block in tsort_each'
	from /usr/local/lib/ruby/2.7.0/tsort.rb:350:in `block (2 levels) in each_strongly_connected_component'
	from /usr/local/lib/ruby/2.7.0/tsort.rb:431:in `each_strongly_connected_component_from'
	from /usr/local/lib/ruby/2.7.0/tsort.rb:349:in `block in each_strongly_connected_component'
	from /usr/local/lib/ruby/2.7.0/tsort.rb:347:in `each'
	from /usr/local/lib/ruby/2.7.0/tsort.rb:347:in `call'
	from /usr/local/lib/ruby/2.7.0/tsort.rb:347:in `each_strongly_connected_component'
	from /usr/local/lib/ruby/2.7.0/tsort.rb:226:in `tsort_each'
	from /usr/local/lib/ruby/2.7.0/tsort.rb:205:in `tsort_each'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/railties-6.0.3.3/lib/rails/initializable.rb:60:in `run_initializers'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/railties-6.0.3.3/lib/rails/application.rb:363:in `initialize!'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/railties-6.0.3.3/lib/rails/railtie.rb:190:in `public_send'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/railties-6.0.3.3/lib/rails/railtie.rb:190:in `method_missing'
	from /var/www/discourse/config/environment.rb:7:in `<top (required)>'
	from config.ru:7:in `require'
	from config.ru:7:in `block in <main>'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/rack-2.2.3/lib/rack/builder.rb:125:in `instance_eval'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/rack-2.2.3/lib/rack/builder.rb:125:in `initialize'
	from config.ru:1:in `new'
	from config.ru:1:in `<main>'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/unicorn-5.7.0/lib/unicorn.rb:54:in `eval'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/unicorn-5.7.0/lib/unicorn.rb:54:in `block in builder'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/unicorn-5.7.0/lib/unicorn/http_server.rb:822:in `build_app!'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/unicorn-5.7.0/lib/unicorn/http_server.rb:141:in `start'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/unicorn-5.7.0/bin/unicorn:128:in `<top (required)>'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/bin/unicorn:23:in `load'
	from /var/www/discourse/vendor/bundle/ruby/2.7.0/bin/unicorn:23:in `<main>'

I don’t know what that means, there’s a SO answer with a similar error message but I’m not certain it fits here.

Do you have any idea?

EDIT: I’ve sent a PR fixing this issue.

Thanks.

Sorry going to close this topic off. I’ve not had time to get the plugin to a good state and we don’t really have any real need for this at Discourse.

2 Likes