diff --git a/CHANGELOG.md b/CHANGELOG.md index 23dc53b..552b8d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Fixed +- Pagination limit on `cb list`, `cb network list`, `cb team list` and + `cb team_member list`. ## [3.6.1] - 2024-11-05 ### Added diff --git a/src/client/client.cr b/src/client/client.cr index 3bff0da..1ee799f 100644 --- a/src/client/client.cr +++ b/src/client/client.cr @@ -3,6 +3,7 @@ require "json" require "log" require "promise" require "../ext/stdlib_ext" +require "./pagination" module CB class Client diff --git a/src/client/cluster.cr b/src/client/cluster.cr index f84f7a6..4919c55 100644 --- a/src/client/cluster.cr +++ b/src/client/cluster.cr @@ -21,9 +21,28 @@ module CB result end + struct ClusterListResponse + include JSON::Serializable + pagination_properties + property clusters : Array(CB::Model::Cluster) = [] of CB::Model::Cluster + end + def get_clusters(team_id) - resp = get "clusters?order_field=name&team_id=#{team_id}&limit=200" - Array(CB::Model::Cluster).from_json resp.body, root: "clusters" + clusters : Array(CB::Model::Cluster) = [] of CB::Model::Cluster + query_params = Hash(String, String | Array(String)).new.tap do |params| + params["team_id"] = team_id.to_s + params["order_field"] = "name" + end + + loop do + resp = get "clusters?#{HTTP::Params.encode(query_params)}" + data = ClusterListResponse.from_json resp.body + clusters.concat(data.clusters) + break unless data.has_more + query_params["cursor"] = data.next_cursor.to_s + end + + clusters end # Retrieve the cluster by id or by name. diff --git a/src/client/network.cr b/src/client/network.cr index adda08f..5b0ec51 100644 --- a/src/client/network.cr +++ b/src/client/network.cr @@ -15,17 +15,31 @@ module CB CB::Model::Network.from_json resp.body end + struct NetworkListResponse + include JSON::Serializable + pagination_properties + property networks : Array(CB::Model::Network) + end + # Get all networks for a team. # # https://crunchybridgeapi.docs.apiary.io/#reference/0/networks/list-networks def get_networks(team : Identifier?) - resp = if team - team_id = team.eid? ? team.to_s : get_team_by_name(team).id - get "networks?team_id=#{team_id}" - else - get "networks" - end - Array(CB::Model::Network).from_json resp.body, root: "networks" + networks = [] of CB::Model::Network + query_params = Hash(String, String | Array(String)).new.tap do |params| + params["order_field"] = "id" + params["team_id"] = team.eid? ? team.to_s : get_team_by_name(team).id if team + end + + loop do + resp = get "networks?#{HTTP::Params.encode(query_params)}" + data = NetworkListResponse.from_json resp.body + networks.concat(data.networks) + break unless data.has_more + query_params["cursor"] = data.next_cursor.to_s + end + + networks end def get_networks(teams : Array(CB::Model::Team)) diff --git a/src/client/pagination.cr b/src/client/pagination.cr new file mode 100644 index 0000000..916e9dc --- /dev/null +++ b/src/client/pagination.cr @@ -0,0 +1,4 @@ +macro pagination_properties + property has_more : Bool = false + property next_cursor : String? = nil +end diff --git a/src/client/team.cr b/src/client/team.cr index b5ac1b2..4f430c3 100644 --- a/src/client/team.cr +++ b/src/client/team.cr @@ -10,12 +10,30 @@ module CB CB::Model::Team.from_json resp.body end + struct TeamListResponse + include JSON::Serializable + pagination_properties + property teams : Array(CB::Model::Team) + end + # List available teams. # # https://crunchybridgeapi.docs.apiary.io/#reference/0/teams/list-teams def get_teams - resp = get "teams?order_field=name" - Array(CB::Model::Team).from_json resp.body, root: "teams" + teams = [] of CB::Model::Team + query_params = Hash(String, String | Array(String)).new.tap do |params| + params["order_field"] = "name" + end + + loop do + resp = get "teams?#{HTTP::Params.encode(query_params)}" + data = TeamListResponse.from_json resp.body + teams.concat(data.teams) + break unless data.has_more + query_params["cursor"] = data.next_cursor.to_s + end + + teams end # Update a team. diff --git a/src/client/team_member.cr b/src/client/team_member.cr index 61a724c..93ff452 100644 --- a/src/client/team_member.cr +++ b/src/client/team_member.cr @@ -13,12 +13,30 @@ module CB CB::Model::TeamMember.from_json resp.body end + struct TeamMemberListResponse + include JSON::Serializable + pagination_properties + property team_members : Array(CB::Model::TeamMember) + end + # List the memebers of a team. # # https://crunchybridgeapi.docs.apiary.io/#reference/0/teamsteamidmembers/list-team-members def list_team_members(team_id) - resp = get "teams/#{team_id}/members" - Array(CB::Model::TeamMember).from_json resp.body, root: "team_members" + team_members = [] of CB::Model::TeamMember + query_params = Hash(String, String | Array(String)).new.tap do |params| + params["order_field"] = "email" + end + + loop do + resp = get "teams/#{team_id}/members?#{HTTP::Params.encode(query_params)}" + data = TeamMemberListResponse.from_json resp.body + team_members.concat(data.team_members) + break unless data.has_more + query_params["cursor"] = data.next_cursor.to_s + end + + team_members end # Retrieve details about a team member. diff --git a/src/ui/spinner.cr b/src/ui/spinner.cr index 33e225d..f9cb780 100644 --- a/src/ui/spinner.cr +++ b/src/ui/spinner.cr @@ -4,7 +4,7 @@ module CB def initialize(@text : String = "", @io : IO = IO::Memory.new) @chars = ["|", "/", "-", "\\"].map { |c| "#{c.colorize.blue}" } - @delay = 0.2 + @delay = 200.milliseconds @running = false # Control Sequence to allow overwriting the line so that the spinner can