superthread 0.7.4 → 0.8.1
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.
- checksums.yaml +4 -4
- data/lib/superthread/cli/base.rb +1 -1
- data/lib/superthread/cli/cards.rb +71 -3
- data/lib/superthread/cli/checklists.rb +29 -27
- data/lib/superthread/cli/search.rb +17 -2
- data/lib/superthread/connection.rb +1 -1
- data/lib/superthread/mention_formatter.rb +33 -0
- data/lib/superthread/models/checklist.rb +7 -0
- data/lib/superthread/models/checklist_item.rb +4 -0
- data/lib/superthread/resources/search.rb +35 -17
- data/lib/superthread/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 05edf5da03e7cda08cca6e16f9813bb8f464b7847f3717a669eeb69802a67208
|
|
4
|
+
data.tar.gz: bdb2593ece548e526dfd602ca061e40541d09a062b633919133bf5ab6cc672c7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7800b583a4a5b07062e460c1b053e593b3c344037d0a6dbf84e576097be4dfdb67594d61f021eaf46aa1bf9ec6b16b93ce5c9c31633331dfa5ef13b1742e82f6
|
|
7
|
+
data.tar.gz: 0d547f6b5c884715da432f8fdfa68593435f85c20cd06786c0f6594f33381ee661f30058c86912595124d3b113fd91978861146e578c3bf8513213d5cd33e269
|
data/lib/superthread/cli/base.rb
CHANGED
|
@@ -137,7 +137,7 @@ module Superthread
|
|
|
137
137
|
def output_list(items, columns: nil, headers: {})
|
|
138
138
|
all_items = items.respond_to?(:items) ? items.items : Array(items)
|
|
139
139
|
limit = effective_limit
|
|
140
|
-
truncated = all_items.length > limit
|
|
140
|
+
truncated = limit && all_items.length > limit
|
|
141
141
|
visible = truncated ? all_items.first(limit) : all_items
|
|
142
142
|
|
|
143
143
|
if json_output?
|
|
@@ -52,6 +52,52 @@ module Superthread
|
|
|
52
52
|
end
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
+
desc "search TERM", "Search for cards across boards and spaces"
|
|
56
|
+
option :space, type: :string, aliases: "-s", desc: "Space to filter by (ID or name)"
|
|
57
|
+
option :status, type: :string, desc: "Status filter (comma-separated)"
|
|
58
|
+
option :field, type: :string, enum: %w[title content], desc: "Search in title or content"
|
|
59
|
+
option :include_archived, type: :boolean, desc: "Include archived cards"
|
|
60
|
+
# Search for cards by keyword with rich output.
|
|
61
|
+
#
|
|
62
|
+
# @param term [String] the search term
|
|
63
|
+
# @return [void]
|
|
64
|
+
def search(term)
|
|
65
|
+
handle_error do
|
|
66
|
+
statuses = options[:status]&.split(",")&.map(&:strip)
|
|
67
|
+
results = client.search.query(
|
|
68
|
+
workspace_id,
|
|
69
|
+
query: term,
|
|
70
|
+
types: ["card"],
|
|
71
|
+
statuses: statuses,
|
|
72
|
+
field: options[:field],
|
|
73
|
+
space_id: (space_id if options[:space]),
|
|
74
|
+
archived: options[:include_archived],
|
|
75
|
+
limit: effective_limit
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
card_ids = results.map { |r| r[:id] }.compact
|
|
79
|
+
if card_ids.empty?
|
|
80
|
+
say "No cards found matching '#{term}'.", :yellow unless options[:quiet]
|
|
81
|
+
return
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
cards = card_ids.filter_map do |id|
|
|
85
|
+
client.cards.find(workspace_id, id)
|
|
86
|
+
rescue Superthread::NotFoundError, Superthread::ForbiddenError
|
|
87
|
+
nil
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
if cards.empty?
|
|
91
|
+
say "No cards found matching '#{term}'.", :yellow unless options[:quiet]
|
|
92
|
+
return
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
enrich_members(cards)
|
|
96
|
+
output_list cards, columns: %i[id title priority list_title board_title members],
|
|
97
|
+
headers: {id: "CARD_ID", list_title: "LIST", board_title: "BOARD"}
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
55
101
|
desc "get CARD", "Get card details"
|
|
56
102
|
option :raw, type: :boolean, desc: "Show raw content without markdown rendering"
|
|
57
103
|
option :no_content, type: :boolean, desc: "Hide content, show only metadata"
|
|
@@ -127,7 +173,7 @@ module Superthread
|
|
|
127
173
|
option :board, type: :string, aliases: "-b", desc: "Board (ID or name, required unless --sprint)"
|
|
128
174
|
option :space, type: :string, aliases: "-s", desc: "Space (required for --sprint, helps resolve board name)"
|
|
129
175
|
option :sprint, type: :string, desc: "Sprint (ID or name, required unless --board)"
|
|
130
|
-
option :content, type: :string, desc: "Card content (HTML)"
|
|
176
|
+
option :content, type: :string, desc: "Card content (HTML). Use {{@Name}} to mention users"
|
|
131
177
|
option :project, type: :string, desc: "Project ID"
|
|
132
178
|
option :start_date, type: :numeric, desc: "Start date (Unix timestamp)"
|
|
133
179
|
option :due_date, type: :numeric, desc: "Due date (Unix timestamp)"
|
|
@@ -393,6 +439,16 @@ module Superthread
|
|
|
393
439
|
|
|
394
440
|
private
|
|
395
441
|
|
|
442
|
+
# Override Base#effective_limit for search-specific defaults.
|
|
443
|
+
# Returns nil for --limit 0 (unlimited), 30 for search default.
|
|
444
|
+
#
|
|
445
|
+
# @return [Integer, nil] the limit (nil = unlimited when --limit 0)
|
|
446
|
+
def effective_limit
|
|
447
|
+
limit = options[:limit]
|
|
448
|
+
return nil if limit == 0
|
|
449
|
+
(limit.is_a?(Integer) && limit > 0) ? limit : 30
|
|
450
|
+
end
|
|
451
|
+
|
|
396
452
|
# Enrich card members with display names from workspace users.
|
|
397
453
|
#
|
|
398
454
|
# The API returns members with only user_id. This fetches the workspace
|
|
@@ -441,11 +497,23 @@ module Superthread
|
|
|
441
497
|
sprint_obj = client.sprints.find(workspace_id, existing.sprint_id,
|
|
442
498
|
space_id: existing.project_id)
|
|
443
499
|
list = sprint_obj.lists&.find { |l| l.title&.downcase == list_ref.downcase }
|
|
500
|
+
unless list || looks_like_id?(list_ref)
|
|
501
|
+
available = sprint_obj.lists&.map(&:title)&.join(", ") || "none"
|
|
502
|
+
raise Thor::Error, "List '#{list_ref}' not found in sprint. Available: #{available}"
|
|
503
|
+
end
|
|
444
504
|
result[:list_id] = list ? list.id : list_ref
|
|
445
505
|
result[:sprint_id] = existing.sprint_id
|
|
446
506
|
result[:project_id] = existing.project_id
|
|
507
|
+
elsif looks_like_id?(list_ref)
|
|
508
|
+
result[:list_id] = list_ref
|
|
447
509
|
else
|
|
448
|
-
|
|
510
|
+
board = client.boards.find(workspace_id, existing.board_id)
|
|
511
|
+
list = board.lists&.find { |l| l.title&.downcase == list_ref.downcase }
|
|
512
|
+
unless list
|
|
513
|
+
available = board.lists&.map(&:title)&.join(", ") || "none"
|
|
514
|
+
raise Thor::Error, "List '#{list_ref}' not found on board. Available: #{available}"
|
|
515
|
+
end
|
|
516
|
+
result[:list_id] = list.id
|
|
449
517
|
end
|
|
450
518
|
end
|
|
451
519
|
|
|
@@ -518,7 +586,7 @@ module Superthread
|
|
|
518
586
|
card.checklists.each do |checklist|
|
|
519
587
|
progress = "(#{checklist.completed_count}/#{checklist.total_count})"
|
|
520
588
|
Ui.kv(checklist.title, progress)
|
|
521
|
-
checklist.
|
|
589
|
+
checklist.sorted_items.each do |item|
|
|
522
590
|
marker = item.checked? ? "✓" : "○"
|
|
523
591
|
title = item.title.gsub(/<[^>]*>/, "").strip
|
|
524
592
|
puts " #{marker} #{title}"
|
|
@@ -57,7 +57,7 @@ module Superthread
|
|
|
57
57
|
if checklist.items&.any?
|
|
58
58
|
puts ""
|
|
59
59
|
Ui.section "Items"
|
|
60
|
-
checklist.
|
|
60
|
+
checklist.sorted_items.each do |item|
|
|
61
61
|
marker = item.checked? ? "✓" : "○"
|
|
62
62
|
puts " #{marker} #{item.title} (#{item.id})"
|
|
63
63
|
end
|
|
@@ -116,7 +116,7 @@ module Superthread
|
|
|
116
116
|
|
|
117
117
|
desc "add-item CHECKLIST", "Add item to a checklist"
|
|
118
118
|
option :card, type: :string, required: true, aliases: "-c", desc: "Parent card ID"
|
|
119
|
-
option :title, type: :string, required: true, desc: "Item title"
|
|
119
|
+
option :title, type: :string, required: true, desc: "Item title. Use {{@Name}} to mention users"
|
|
120
120
|
option :checked, type: :boolean, default: false, desc: "Create as checked"
|
|
121
121
|
# Add a new item to an existing checklist.
|
|
122
122
|
#
|
|
@@ -139,7 +139,7 @@ module Superthread
|
|
|
139
139
|
desc "update-item ITEM_ID", "Update a checklist item"
|
|
140
140
|
option :card, type: :string, required: true, aliases: "-c", desc: "Parent card ID"
|
|
141
141
|
option :checklist, type: :string, required: true, desc: "Parent checklist ID"
|
|
142
|
-
option :title, type: :string, desc: "New item title"
|
|
142
|
+
option :title, type: :string, desc: "New item title. Use {{@Name}} to mention users"
|
|
143
143
|
option :checked, type: :boolean, desc: "Mark as checked/unchecked"
|
|
144
144
|
# Update the title or checked state of a checklist item.
|
|
145
145
|
#
|
|
@@ -179,43 +179,45 @@ module Superthread
|
|
|
179
179
|
end
|
|
180
180
|
end
|
|
181
181
|
|
|
182
|
-
desc "check ITEM_ID", "Mark
|
|
182
|
+
desc "check ITEM_ID [ITEM_ID...]", "Mark checklist item(s) as checked"
|
|
183
183
|
option :card, type: :string, required: true, aliases: "-c", desc: "Parent card ID"
|
|
184
184
|
option :checklist, type: :string, required: true, desc: "Parent checklist ID"
|
|
185
|
-
# Mark
|
|
185
|
+
# Mark one or more checklist items as completed.
|
|
186
186
|
#
|
|
187
|
-
# @param
|
|
187
|
+
# @param item_ids [Array<String>] the unique identifiers of the items
|
|
188
188
|
# @return [void]
|
|
189
|
-
def check(
|
|
189
|
+
def check(*item_ids)
|
|
190
190
|
handle_error do
|
|
191
|
-
item
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
191
|
+
raise Thor::Error, "No item IDs provided" if item_ids.empty?
|
|
192
|
+
|
|
193
|
+
item_ids.each do |item_id|
|
|
194
|
+
client.cards.update_checklist_item(
|
|
195
|
+
workspace_id, options[:card], options[:checklist], item_id,
|
|
196
|
+
checked: true
|
|
197
|
+
)
|
|
198
|
+
end
|
|
199
|
+
output_success "Checked #{item_ids.size} item(s)"
|
|
199
200
|
end
|
|
200
201
|
end
|
|
201
202
|
|
|
202
|
-
desc "uncheck ITEM_ID", "Mark
|
|
203
|
+
desc "uncheck ITEM_ID [ITEM_ID...]", "Mark checklist item(s) as unchecked"
|
|
203
204
|
option :card, type: :string, required: true, aliases: "-c", desc: "Parent card ID"
|
|
204
205
|
option :checklist, type: :string, required: true, desc: "Parent checklist ID"
|
|
205
|
-
# Mark
|
|
206
|
+
# Mark one or more checklist items as not completed.
|
|
206
207
|
#
|
|
207
|
-
# @param
|
|
208
|
+
# @param item_ids [Array<String>] the unique identifiers of the items
|
|
208
209
|
# @return [void]
|
|
209
|
-
def uncheck(
|
|
210
|
+
def uncheck(*item_ids)
|
|
210
211
|
handle_error do
|
|
211
|
-
item
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
212
|
+
raise Thor::Error, "No item IDs provided" if item_ids.empty?
|
|
213
|
+
|
|
214
|
+
item_ids.each do |item_id|
|
|
215
|
+
client.cards.update_checklist_item(
|
|
216
|
+
workspace_id, options[:card], options[:checklist], item_id,
|
|
217
|
+
checked: false
|
|
218
|
+
)
|
|
219
|
+
end
|
|
220
|
+
output_success "Unchecked #{item_ids.size} item(s)"
|
|
219
221
|
end
|
|
220
222
|
end
|
|
221
223
|
end
|
|
@@ -7,6 +7,7 @@ module Superthread
|
|
|
7
7
|
desc "query SEARCH_TERM", "Search across workspace"
|
|
8
8
|
option :field, type: :string, enum: %w[title content], desc: "Field to search in"
|
|
9
9
|
option :types, type: :string, desc: "Entity types to search (comma-separated: board,card,page,project,epic,note)"
|
|
10
|
+
option :status, type: :string, desc: "Status filter (comma-separated, e.g., open,started)"
|
|
10
11
|
option :space, type: :string, aliases: "-s", desc: "Space to filter by (ID or name)"
|
|
11
12
|
option :include_archived, type: :boolean, desc: "Include archived items"
|
|
12
13
|
option :grouped, type: :boolean, desc: "Group results by type"
|
|
@@ -17,18 +18,32 @@ module Superthread
|
|
|
17
18
|
def query(search_term)
|
|
18
19
|
handle_error do
|
|
19
20
|
types = options[:types]&.split(",")&.map(&:strip)
|
|
21
|
+
statuses = options[:status]&.split(",")&.map(&:strip)
|
|
20
22
|
results = client.search.query(
|
|
21
23
|
workspace_id,
|
|
22
24
|
query: search_term,
|
|
23
25
|
field: options[:field],
|
|
24
26
|
types: types,
|
|
25
|
-
|
|
27
|
+
statuses: statuses,
|
|
28
|
+
space_id: (space_id if options[:space]),
|
|
26
29
|
archived: options[:include_archived],
|
|
27
|
-
grouped: options[:grouped]
|
|
30
|
+
grouped: options[:grouped],
|
|
31
|
+
limit: effective_limit
|
|
28
32
|
)
|
|
29
33
|
output_list results, columns: %i[result_type id title], headers: {id: "ID"}
|
|
30
34
|
end
|
|
31
35
|
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
# Override Base#effective_limit for search-specific defaults.
|
|
40
|
+
#
|
|
41
|
+
# @return [Integer, nil] the limit (nil = unlimited when --limit 0)
|
|
42
|
+
def effective_limit
|
|
43
|
+
limit = options[:limit]
|
|
44
|
+
return nil if limit == 0
|
|
45
|
+
(limit.is_a?(Integer) && limit > 0) ? limit : 30
|
|
46
|
+
end
|
|
32
47
|
end
|
|
33
48
|
end
|
|
34
49
|
end
|
|
@@ -32,6 +32,8 @@ module Superthread
|
|
|
32
32
|
PLACEHOLDER_PATTERN = /___ESCAPED_MENTION_(.+?)___END___/
|
|
33
33
|
# @return [Regexp] pattern matching raw HTML mention tags that should use {{@Name}} syntax
|
|
34
34
|
HTML_MENTION_PATTERN = /<(?:user-mention|mention-user)\b/i
|
|
35
|
+
# @return [Regexp] pattern matching plain @Word that is not inside {{@...}} delimiters
|
|
36
|
+
PLAIN_MENTION_PATTERN = /(?<!\{\{)@(\w+)/
|
|
35
37
|
|
|
36
38
|
# @param client [Superthread::Client] the API client for fetching members
|
|
37
39
|
# @param workspace_id [String] the workspace to look up members in
|
|
@@ -46,6 +48,7 @@ module Superthread
|
|
|
46
48
|
# @return [String, nil] content with mentions converted to HTML tags
|
|
47
49
|
def format(content)
|
|
48
50
|
warn_html_mentions(content) if content
|
|
51
|
+
warn_plain_mentions(content) if content
|
|
49
52
|
return content if content.nil? || !content.include?("{{@")
|
|
50
53
|
|
|
51
54
|
member_map = build_member_map
|
|
@@ -99,6 +102,36 @@ module Superthread
|
|
|
99
102
|
"(e.g., '{{@Steve Clarke}} check this')."
|
|
100
103
|
end
|
|
101
104
|
|
|
105
|
+
# Warns when content contains plain @Name mentions that match workspace members.
|
|
106
|
+
# This catches the common mistake of using @Name instead of {{@Name}}.
|
|
107
|
+
#
|
|
108
|
+
# @param content [String] text to check for plain @mentions
|
|
109
|
+
# @return [void]
|
|
110
|
+
def warn_plain_mentions(content)
|
|
111
|
+
return if content.include?("{{@")
|
|
112
|
+
|
|
113
|
+
names = content.scan(PLAIN_MENTION_PATTERN).flatten
|
|
114
|
+
return if names.empty?
|
|
115
|
+
|
|
116
|
+
member_map = build_member_map
|
|
117
|
+
return if member_map.nil?
|
|
118
|
+
|
|
119
|
+
# Also index by first name for multi-word display names
|
|
120
|
+
first_name_map = {}
|
|
121
|
+
member_map.each_value do |info|
|
|
122
|
+
first = info[:name].split.first&.downcase
|
|
123
|
+
first_name_map[first] = info[:name] if first
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
names.each do |name|
|
|
127
|
+
match = member_map[name.downcase]&.fetch(:name) || first_name_map[name.downcase]
|
|
128
|
+
if match
|
|
129
|
+
warn "Warning: Found @#{name} — did you mean {{@#{match}}}? " \
|
|
130
|
+
"Use {{@Name}} syntax to mention users and trigger notifications."
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
102
135
|
# Fetches workspace members and builds a case-insensitive lookup map.
|
|
103
136
|
#
|
|
104
137
|
# @return [Hash{String => Hash}, nil] map of lowercase names to {id:, name:}, or nil on failure
|
|
@@ -57,6 +57,13 @@ module Superthread
|
|
|
57
57
|
|
|
58
58
|
timestamps :time_created, :time_updated
|
|
59
59
|
|
|
60
|
+
# Items sorted by position.
|
|
61
|
+
#
|
|
62
|
+
# @return [Array<ChecklistItem>] items in position order
|
|
63
|
+
def sorted_items
|
|
64
|
+
(items || []).sort_by { |i| i.position || 0 }
|
|
65
|
+
end
|
|
66
|
+
|
|
60
67
|
# Count of completed items.
|
|
61
68
|
#
|
|
62
69
|
# @return [Integer] Number of checked items
|
|
@@ -41,6 +41,10 @@ module Superthread
|
|
|
41
41
|
# @return [Boolean] whether this item is checked/completed
|
|
42
42
|
attribute :checked, Shale::Type::Boolean
|
|
43
43
|
|
|
44
|
+
# @!attribute [rw] position
|
|
45
|
+
# @return [Integer] position within the checklist for ordering
|
|
46
|
+
attribute :position, Shale::Type::Integer
|
|
47
|
+
|
|
44
48
|
# @!attribute [rw] time_created
|
|
45
49
|
# @return [Integer] Unix timestamp when the item was created
|
|
46
50
|
attribute :time_created, Shale::Type::Integer
|
|
@@ -7,10 +7,17 @@ module Superthread
|
|
|
7
7
|
# Provides methods for searching across workspace entities
|
|
8
8
|
# (cards, pages, boards, etc.) via the Superthread API.
|
|
9
9
|
class Search < Base
|
|
10
|
+
# Safety cap on pagination requests to prevent runaway loops.
|
|
11
|
+
MAX_PAGES = 100
|
|
12
|
+
|
|
10
13
|
# Searches across workspace entities.
|
|
11
14
|
#
|
|
15
|
+
# Follows pagination cursors automatically. When limit is provided,
|
|
16
|
+
# stops after accumulating that many results.
|
|
17
|
+
#
|
|
12
18
|
# @param workspace_id [String] the workspace identifier
|
|
13
19
|
# @param query [String] the search query string
|
|
20
|
+
# @param limit [Integer, nil] max results to return (nil = no limit)
|
|
14
21
|
# @param params [Hash{Symbol => Object}] optional search parameters
|
|
15
22
|
# @option params [String] :field the field to search (title, content)
|
|
16
23
|
# @option params [Array<String>] :types entity types to include (board, card, page, etc.)
|
|
@@ -18,28 +25,39 @@ module Superthread
|
|
|
18
25
|
# @option params [String] :space_id the space identifier to filter by
|
|
19
26
|
# @option params [Boolean] :archived when true, includes archived entities
|
|
20
27
|
# @option params [Boolean] :grouped when true, groups results by type (default: false)
|
|
21
|
-
# @option params [String] :cursor the pagination cursor for next page
|
|
22
28
|
# @return [Superthread::Objects::Collection] the search results
|
|
23
|
-
def query(workspace_id, query:, **params)
|
|
29
|
+
def query(workspace_id, query:, limit: nil, **params)
|
|
24
30
|
ws = safe_id("workspace_id", workspace_id)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
grouped = params.fetch(:grouped, false)
|
|
32
|
+
all_results = []
|
|
33
|
+
cursor = nil
|
|
34
|
+
pages = 0
|
|
35
|
+
|
|
36
|
+
loop do
|
|
37
|
+
search_params = compact_params(
|
|
38
|
+
query: query,
|
|
39
|
+
project_id: params[:space_id],
|
|
40
|
+
grouped: grouped,
|
|
41
|
+
cursor: cursor,
|
|
42
|
+
**params.except(:space_id, :grouped)
|
|
43
|
+
)
|
|
44
|
+
response = http_get("/#{ws}/search", params: search_params)
|
|
45
|
+
|
|
46
|
+
results = (response[:results] || []).map do |item|
|
|
47
|
+
result_type, data = item.first
|
|
48
|
+
data.merge(result_type: result_type.to_s)
|
|
49
|
+
end
|
|
50
|
+
all_results.concat(results)
|
|
35
51
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
52
|
+
cursor = response[:cursor]
|
|
53
|
+
pages += 1
|
|
54
|
+
break if cursor.nil? || cursor.empty?
|
|
55
|
+
break if limit && all_results.size >= limit
|
|
56
|
+
break if pages >= MAX_PAGES
|
|
40
57
|
end
|
|
41
58
|
|
|
42
|
-
|
|
59
|
+
all_results = all_results.first(limit) if limit
|
|
60
|
+
Objects::Collection.from_response(all_results)
|
|
43
61
|
end
|
|
44
62
|
end
|
|
45
63
|
end
|
data/lib/superthread/version.rb
CHANGED