Class: Gitlab::Graphql::Queries::Definition

Inherits:
Object
  • Object
show all
Defined in:
lib/gitlab/graphql/queries.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path, fragments) ⇒ Definition

Returns a new instance of Definition.


127
128
129
130
131
132
133
# File 'lib/gitlab/graphql/queries.rb', line 127

def initialize(path, fragments)
  @file = path
  @fragments = fragments
  @imports = []
  @errors = []
  @ee_else_ce = []
end

Instance Attribute Details

#fileObject (readonly)

Returns the value of attribute file.


125
126
127
# File 'lib/gitlab/graphql/queries.rb', line 125

def file
  @file
end

#importsObject (readonly)

Returns the value of attribute imports.


125
126
127
# File 'lib/gitlab/graphql/queries.rb', line 125

def imports
  @imports
end

Instance Method Details

#all_errorsObject


191
192
193
194
195
196
197
# File 'lib/gitlab/graphql/queries.rb', line 191

def all_errors
  return @errors.to_set if query.nil?

  paths = imports + @ee_else_ce.flat_map { |p| [@fragments.home + p, @fragments.home_ee + p] }

  paths.map { |p| fragment(p).all_errors }.reduce(@errors.to_set) { |a, b| a | b }
end

#all_imports(mode: :ce) ⇒ Object


182
183
184
185
186
187
188
189
# File 'lib/gitlab/graphql/queries.rb', line 182

def all_imports(mode: :ce)
  return [] if query.nil?

  home = mode == :ee ? @fragments.home_ee : @fragments.home
  eithers = @ee_else_ce.map { |p| home + p }

  (imports + eithers).flat_map { |p| [p] + @fragments.get(p).all_imports(mode: mode) }
end

#complexity(schema) ⇒ Object


148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/gitlab/graphql/queries.rb', line 148

def complexity(schema)
  # See BaseResolver::resolver_complexity
  # we want to see the max possible complexity.
  fake_args = Struct
    .new(:if, :keyword_arguments)
    .new(nil, { sort: true, search: true })

  query = GraphQL::Query.new(schema, text)
  # We have no arguments, so fake them.
  query.define_singleton_method(:arguments_for) { |_x, _y| fake_args }

  GraphQL::Analysis::AST.analyze_query(query, [GraphQL::Analysis::AST::QueryComplexity]).first
end

#queryObject


162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/gitlab/graphql/queries.rb', line 162

def query
  return @query if defined?(@query)

  # CONN_DIRECTIVEs are purely client-side constructs
  @query = File.read(file).gsub(CONN_DIRECTIVE, '').gsub(IMPORT_RE) do
    path = $~[:path]

    if EE_ELSE_CE.match?(path)
      @ee_else_ce << path.gsub(EE_ELSE_CE, '')
    else
      @imports << fragment_path(path)
    end

    ''
  end
rescue Errno::ENOENT
  @errors << FileNotFound.new(file)
  @query = nil
end

#text(mode: :ce) ⇒ Object


135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/gitlab/graphql/queries.rb', line 135

def text(mode: :ce)
  qs = [query] + all_imports(mode: mode).uniq.sort.map { |p| fragment(p).query }
  t = qs.join("\n\n").gsub(/\n\n+/, "\n\n")

  return t unless /@client/.match?(t)

  doc = ::GraphQL.parse(t)
  printer = ClientFieldRedactor.new
  redacted = doc.dup.to_query_string(printer: printer)

  return redacted if printer.fields_printed > 0
end

#validate(schema) ⇒ Object


199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/gitlab/graphql/queries.rb', line 199

def validate(schema)
  return [:client_query, []] if query.present? && text.nil?

  errs = all_errors.presence || schema.validate(text)
  if @ee_else_ce.present?
    errs += schema.validate(text(mode: :ee))
  end

  [:validated, errs]
rescue ::GraphQL::ParseError => e
  [:validated, [WrappedError.new(e)]]
end