graphqlmd 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 75e4efde27cb6b626368452682c61b319ab9ef2ee21f25bf1a6a9e2684e6fc3a
4
+ data.tar.gz: f5370b610c3628879e2c01d95bd4ac3465ec5dc24fe8a8b536fa0a7fb38bf36c
5
+ SHA512:
6
+ metadata.gz: f51ece8322bb19a14015e111e2e64c8601eb5ed20ae4e7ef314c837ea927fce31e166b6b1acb6369540b8714e88e09e23c2ed4160c6d2e0e1dda3901b8a6b1d6
7
+ data.tar.gz: 3715e96440f72ee5c7661ae48f63b514c6e1121c9ed130e11a76846f5293ecc0c093d95d34a5b5dc58289d0d3173eb823c11f7e5bc8d3818c2d5d4e3757bb8d4
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'graphqlmd'
4
+ require 'optparse'
5
+
6
+ options = {
7
+ url: 'http://localhost:3000/graphql',
8
+ is_hide_client_mutation_id: true,
9
+ is_hide_scalar: true,
10
+ is_hide_deprecated: false,
11
+ is_allow_links: true,
12
+ is_vuepress: false
13
+ }
14
+
15
+
16
+ OptionParser.new do |opts|
17
+ opts.banner = 'Usage: graphqlmd [options]'
18
+
19
+ opts.on_tail '-v', '--version', 'Show version' do
20
+ puts "graphqlmd v#{Graphqlmd::VERSION}"
21
+ exit
22
+ end
23
+
24
+ opts.on(
25
+ '-u', '--url [URL]', "GraphQL schema url (default: #{options[:url]})"
26
+ ) do |url|
27
+ options[:url] = url
28
+ end
29
+
30
+ opts.on '--no-deprecated', 'Do not add deprecated objects, fields, args and etc.' do
31
+ options[:is_hide_deprecated] = true
32
+ end
33
+
34
+ opts.on '--no-links', 'Do not add links with anchors to docs' do
35
+ options[:is_allow_links] = false
36
+ end
37
+
38
+ opts.on '--client-mutation-id', 'Add clientMutationId to docs' do
39
+ options[:is_hide_client_mutation_id] = false
40
+ end
41
+
42
+ opts.on '--scalar', 'Add scalar objects to docs' do
43
+ options[:is_hide_scalar] = false
44
+ end
45
+
46
+ opts.on '--vuepress', 'Use vuepress additional styles' do
47
+ options[:is_vuepress] = true
48
+ end
49
+
50
+ opts.on_tail '-h', '--help', 'Show this message' do
51
+ puts opts
52
+ exit
53
+ end
54
+ end.parse!
55
+
56
+ ::Graphqlmd::Graphqlmd.new(options).call
@@ -0,0 +1,167 @@
1
+ require 'graphqlmd/consts'
2
+ require 'graphqlmd/version'
3
+ require 'json'
4
+ require 'net/http'
5
+ require 'uri'
6
+
7
+ class Graphqlmd::Graphqlmd
8
+ include ::Graphqlmd
9
+
10
+ def initialize options
11
+ @url = options[:url]
12
+ @is_hide_client_mutation_id = options[:is_hide_client_mutation_id]
13
+ @is_hide_deprecated = options[:is_hide_deprecated]
14
+ @is_hide_scalar = options[:is_hide_scalar]
15
+ @is_allow_links = options[:is_allow_links]
16
+ @is_vuepress = options[:is_vuepress]
17
+ end
18
+
19
+ def call
20
+ response = fetch_schema
21
+ data = JSON.parse(response.body).dig 'data', 'schema'
22
+ puts_queries data['queries']
23
+ puts_mutations data['mutations']
24
+ puts_objects data['types']
25
+ end
26
+
27
+ private
28
+
29
+ def puts_queries data
30
+ print_header 'Queries'
31
+ queries = data['fields'].sort_by { |v| v['name'] }
32
+
33
+ queries.each do |v|
34
+ puts "\n### #{v['name']}\n"
35
+ print_deprecation v
36
+ puts "Return Type | Description\n"
37
+ puts "-|-\n"
38
+ puts "#{type_as_string v['type']} | #{print_description(v['description'])}\n"
39
+ print_args v['args']
40
+ end
41
+ end
42
+
43
+ def puts_mutations data
44
+ print_header 'Mutations'
45
+ mutations = data['fields'].sort_by { |v| v['name'] }
46
+ mutations = mutations.reject { |v| v['isDeprecated'] } if @is_hide_deprecated
47
+
48
+ mutations.each do |v|
49
+ puts "\n### #{v['name']}\n"
50
+ print_deprecation v
51
+ puts "Return Type | Description\n"
52
+ puts "-|-\n"
53
+ puts "#{type_as_string v['type']} | #{print_description(v['description'])}\n"
54
+ print_args v['args']
55
+ end
56
+ end
57
+
58
+ def puts_objects data
59
+ print_header 'Objects'
60
+ objects = data
61
+ .reject { |v| IGNORED_OBJECT_NAMES.include? v['name'] }
62
+ .sort_by { |v| v['name'] }
63
+ objects = objects.reject { |v| v['kind'] == SCALAR } if @is_hide_scalar
64
+
65
+ objects.each do |v|
66
+ puts "\n### #{v['name']}\n"
67
+ puts "#{print_description v['description']}\n" unless v['description'].nil?
68
+ print_fields v['fields'] || v['inputFields']
69
+ end
70
+
71
+ nil
72
+ end
73
+
74
+ def print_header value
75
+ puts "## #{value}\n"
76
+ end
77
+
78
+ def print_fields fields
79
+ return if fields.nil?
80
+ return if fields.empty?
81
+
82
+ puts "\n**Fields**\n"
83
+ puts "Name | Type | Description\n"
84
+ puts "-|-|-\n"
85
+ fields.each do |v|
86
+ next if v['name'] == CLIENT_MUTATION_ID && @is_hide_client_mutation_id
87
+
88
+ puts "#{v['name']} | #{type_as_string(v['type'])} | #{print_description(v['description'])}\n"
89
+ end
90
+ end
91
+
92
+ def print_args args
93
+ return if args.nil?
94
+ return if args.empty?
95
+
96
+ puts "#### Arguments\n"
97
+ puts "Name | Type | Description\n"
98
+ puts "-|-|-|-\n"
99
+ args.each do |v|
100
+ puts "#{v['name']} | #{type_as_string(v['type'])} | #{print_description(v['description'])}\n"
101
+ end
102
+ end
103
+
104
+ def print_description value
105
+ return if value.nil? || value.empty?
106
+
107
+ "_#{value}_"
108
+ end
109
+
110
+ def print_deprecation data
111
+ return unless data['isDeprecated']
112
+
113
+ if @is_vuepress
114
+ puts "::: warning DEPRECATED\n"
115
+ puts "#{data['deprecationReason']}\n"
116
+ puts ":::\n\n"
117
+ else
118
+ puts "> **DEPRECATED**\n"
119
+ puts ">\n"
120
+ puts "> #{data['deprecationReason']}\n\n"
121
+ end
122
+ end
123
+
124
+ def type_as_string type
125
+ is_required = type['kind'] == NON_NULL
126
+ is_list = type['kind'] == LIST
127
+
128
+ if type['name']
129
+ "#{name_as_link(type)}#{required_postfix(is_required)}"
130
+ elsif is_list
131
+ "[#{type_as_string(type['ofType'])}#{required_postfix(is_required)}]"
132
+ else
133
+ "#{type_as_string(type['ofType'])}#{required_postfix(is_required)}"
134
+ end
135
+ end
136
+
137
+ def required_postfix is_required
138
+ is_required ? '!' : ''
139
+ end
140
+
141
+ def name_as_link type
142
+ return type['name'] unless @is_allow_links
143
+ return type['name'] if type['kind'] == SCALAR
144
+
145
+ "[#{type['name']}](##{type['name'].downcase})"
146
+ end
147
+
148
+ def fetch_schema
149
+ uri = URI.parse @url
150
+
151
+ Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
152
+ request = Net::HTTP::Post.new uri.request_uri, headers
153
+ request.body = body
154
+ http.request request
155
+ end
156
+ end
157
+
158
+ def headers
159
+ {
160
+ 'Content-Type' => 'application/json'
161
+ }
162
+ end
163
+
164
+ def body
165
+ { query: SCHEMA_QUERY, variables: nil }.to_json
166
+ end
167
+ end
@@ -0,0 +1,106 @@
1
+ module Graphqlmd
2
+ SCHEMA_QUERY = <<~QUERY
3
+ fragment FullType on __Type {
4
+ kind
5
+ name
6
+ description
7
+ fields(includeDeprecated: true) {
8
+ name
9
+ description
10
+ args {
11
+ ...InputValue
12
+ }
13
+ type {
14
+ ...TypeRef
15
+ }
16
+ isDeprecated
17
+ deprecationReason
18
+ }
19
+ inputFields {
20
+ ...InputValue
21
+ }
22
+ interfaces {
23
+ ...TypeRef
24
+ }
25
+ enumValues(includeDeprecated: true) {
26
+ name
27
+ isDeprecated
28
+ deprecationReason
29
+ }
30
+ possibleTypes {
31
+ ...TypeRef
32
+ }
33
+ }
34
+ fragment InputValue on __InputValue {
35
+ name
36
+ type {
37
+ ...TypeRef
38
+ }
39
+ defaultValue
40
+ }
41
+ fragment TypeRef on __Type {
42
+ kind
43
+ name
44
+ ofType {
45
+ kind
46
+ name
47
+ ofType {
48
+ kind
49
+ name
50
+ ofType {
51
+ kind
52
+ name
53
+ ofType {
54
+ kind
55
+ name
56
+ ofType {
57
+ kind
58
+ name
59
+ ofType {
60
+ kind
61
+ name
62
+ ofType {
63
+ kind
64
+ name
65
+ }
66
+ }
67
+ }
68
+ }
69
+ }
70
+ }
71
+ }
72
+ }
73
+
74
+ {
75
+ schema:__schema {
76
+ queries:queryType {
77
+ ...FullType
78
+ }
79
+ mutations:mutationType {
80
+ ...FullType
81
+ }
82
+ types {
83
+ ...FullType
84
+ }
85
+ }
86
+ }
87
+ QUERY
88
+
89
+ LIST = 'LIST'
90
+ SCALAR = 'SCALAR'
91
+ NON_NULL = 'NON_NULL'
92
+ CLIENT_MUTATION_ID = 'clientMutationId'
93
+ IGNORED_OBJECT_NAMES = %w[
94
+ Query
95
+ Mutation
96
+ SCALAR
97
+ __DirectiveLocation
98
+ __TypeKind
99
+ __InputValue
100
+ __EnumValue
101
+ __Directive
102
+ __Field
103
+ __Type
104
+ __Schema
105
+ ]
106
+ end
@@ -0,0 +1,3 @@
1
+ module Graphqlmd
2
+ VERSION = '1.0.0'
3
+ end
metadata ADDED
@@ -0,0 +1,47 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: graphqlmd
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Alexander Kalinichev
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-08-26 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: This gem will generate markdown by your GraphQL schema
14
+ email: alex@agileseason.com
15
+ executables:
16
+ - graphqlmd
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - bin/graphqlmd
21
+ - lib/graphqlmd.rb
22
+ - lib/graphqlmd/consts.rb
23
+ - lib/graphqlmd/version.rb
24
+ homepage: https://github.com/blackchestnut/graphqlmd
25
+ licenses:
26
+ - MIT
27
+ metadata: {}
28
+ post_install_message:
29
+ rdoc_options: []
30
+ require_paths:
31
+ - lib
32
+ required_ruby_version: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: '0'
37
+ required_rubygems_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ requirements: []
43
+ rubygems_version: 3.0.3
44
+ signing_key:
45
+ specification_version: 4
46
+ summary: graphqlmd
47
+ test_files: []