# frozen_string_literal: true require 'forwardable' module WCC::Blogs class Client Response = Struct.new(:client, :request, :raw_response) do # rubocop:disable Metrics/BlockLength extend Forwardable def_delegators :raw_response, :status, :headers alias_method :code, :status def body @body ||= raw_response.body.to_s end def raw @raw ||= JSON.parse(body) end alias_method :to_json, :raw def next_page_url raw.dig('_links', 'next') end def next_page? !!next_page_url end def next_page return unless next_page_url return @next_page if @next_page np = client.get(next_page_url, request[:query]) @next_page = np.assert_ok! end def assert_ok! return self if status >= 200 && status < 300 raise ApiError[status], self end def each_page(&block) # rubocop:disable Metrics/MethodLength raise ArgumentError, 'Not a collection response' unless page_items ret = Enumerator.new do |y| y << self if next_page? next_page.each_page.each do |page| y << page end end end if block_given? ret.map(&block) else ret.lazy end end def items each_page.flat_map(&:page_items) end def page_items raw['items'] end def count total end def first raise ArgumentError, 'Not a collection response' unless page_items page_items.first end end class ApiError < StandardError attr_reader :response def self.[](code) case code when 404 NotFoundException else ApiError end end def initialize(response, message = nil) @response = response super(message || "An unexpected error occurred: #{response.status}") end end class NotFoundError < ApiError def initialize(response) super(response, "Blog post '#{response.effective_url}' does not exist") end end end end