1# frozen_string_literal: true
2
3module Resolvers
4  class PackagePipelinesResolver < BaseResolver
5    include Gitlab::Graphql::Authorize::AuthorizeResource
6
7    type Types::Ci::PipelineType.connection_type, null: true
8    extension Gitlab::Graphql::Extensions::ExternallyPaginatedArrayExtension
9
10    authorizes_object!
11    authorize :read_pipeline
12
13    alias_method :package, :object
14
15    def resolve(first: nil, last: nil, after: nil, before: nil, lookahead:)
16      finder = ::Packages::BuildInfosFinder.new(
17        package,
18        first: first,
19        last: last,
20        after: decode_cursor(after),
21        before: decode_cursor(before),
22        max_page_size: context.schema.default_max_page_size,
23        support_next_page: lookahead.selects?(:page_info)
24      )
25
26      build_infos = finder.execute
27
28      # this .pluck_pipeline_ids can load max 101 pipelines ids
29      ::Ci::Pipeline.id_in(build_infos.pluck_pipeline_ids)
30    end
31
32    # we manage the pagination manually, so opt out of the connection field extension
33    def self.field_options
34      super.merge(
35        connection: false,
36        extras: [:lookahead]
37      )
38    end
39
40    private
41
42    def decode_cursor(encoded)
43      return unless encoded
44
45      decoded = Gitlab::Json.parse(context.schema.cursor_encoder.decode(encoded, nonce: true))
46      id_from_cursor(decoded)
47    rescue JSON::ParserError
48      raise Gitlab::Graphql::Errors::ArgumentError, "Please provide a valid cursor"
49    end
50
51    def id_from_cursor(cursor)
52      cursor&.fetch('id')
53    rescue KeyError
54      raise Gitlab::Graphql::Errors::ArgumentError, "Please provide a valid cursor"
55    end
56  end
57end
58