Class: Woods::Unblocked::Client
- Inherits:
-
Object
- Object
- Woods::Unblocked::Client
- Defined in:
- lib/woods/unblocked/client.rb
Overview
REST client for the Unblocked API v1.
Handles document and collection CRUD with rate limiting, retries, and error handling. Uses Net::HTTP for zero external dependencies.
Constant Summary collapse
- BASE_URL =
'https://getunblocked.com/api/v1'- MAX_RETRIES =
3- DEFAULT_TIMEOUT =
30- PAGE_SIZE =
Max page size the list endpoint accepts (per API docs).
200- DEFAULT_ICON_URL =
Repo-hosted Woods mark, used as the collection icon when none is given. The live API rejects collection creation without an iconUrl (despite the API docs marking it optional), so a working default matters.
'https://raw.githubusercontent.com/lost-in-the/woods/main/assets/woods-mark-black.svg'
Instance Method Summary collapse
-
#all_documents(collection_id:) ⇒ Array<Hash>
List every document in a collection, paging until exhausted.
-
#create_collection(name:, description:, icon_url: nil) ⇒ Hash
Create a new collection.
-
#delete_document(document_id:) ⇒ Hash
Delete a document by ID.
-
#initialize(api_token:, rate_limiter: RateLimiter.new) ⇒ Client
constructor
A new instance of Client.
-
#list_collections ⇒ Array<Hash>
List all collections.
-
#list_documents(limit: PAGE_SIZE, after: nil) ⇒ Array<Hash>
List a single page of documents.
-
#put_document(collection_id:, title:, body:, uri:) ⇒ Hash
Create or update a document (upsert by URI).
Constructor Details
#initialize(api_token:, rate_limiter: RateLimiter.new) ⇒ Client
Returns a new instance of Client.
56 57 58 59 60 61 |
# File 'lib/woods/unblocked/client.rb', line 56 def initialize(api_token:, rate_limiter: RateLimiter.new) raise ArgumentError, 'api_token is required' if api_token.nil? || api_token.to_s.strip.empty? @api_token = api_token @rate_limiter = rate_limiter end |
Instance Method Details
#all_documents(collection_id:) ⇒ Array<Hash>
List every document in a collection, paging until exhausted.
Filters client-side on ‘collectionId` since the API has no collection filter. ~5 calls for ~1000 documents; each goes through the rate limiter.
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/woods/unblocked/client.rb', line 146 def all_documents(collection_id:) docs = [] after = nil loop do page = list_documents(limit: PAGE_SIZE, after: after) break if page.empty? docs.concat(page) break if page.size < PAGE_SIZE after = page.last['id'] # A full page with no cursor id would refetch page 1 forever — # stop with what we have rather than loop against the budget. break if after.nil? end docs.select { |doc| doc['collectionId'] == collection_id } end |
#create_collection(name:, description:, icon_url: nil) ⇒ Hash
Create a new collection.
92 93 94 95 96 97 98 |
# File 'lib/woods/unblocked/client.rb', line 92 def create_collection(name:, description:, icon_url: nil) request(:post, 'collections', { name: name, description: description, iconUrl: icon_url || DEFAULT_ICON_URL }) end |
#delete_document(document_id:) ⇒ Hash
Delete a document by ID.
116 117 118 |
# File 'lib/woods/unblocked/client.rb', line 116 def delete_document(document_id:) request(:delete, "documents/#{document_id}") end |
#list_collections ⇒ Array<Hash>
List all collections.
103 104 105 106 107 108 109 110 |
# File 'lib/woods/unblocked/client.rb', line 103 def list_collections result = request(:get, 'collections') # The live API returns a bare JSON array; the envelope fallbacks are # defensive (calling ['items'] on an Array raises TypeError). return result if result.is_a?(Array) result['items'] || result['data'] || [result].flatten.compact end |
#list_documents(limit: PAGE_SIZE, after: nil) ⇒ Array<Hash>
List a single page of documents.
The endpoint returns a bare JSON array of document metadata (no body): ‘id, collectionId, title, uri, createdAt, updatedAt`. Pagination is cursor-based via `after`/`before` (opaque cursors); there is no server-side collection filter.
130 131 132 133 134 135 136 137 |
# File 'lib/woods/unblocked/client.rb', line 130 def list_documents(limit: PAGE_SIZE, after: nil) query = "limit=#{limit}" query += "&after=#{URI.encode_www_form_component(after)}" if after result = request(:get, "documents?#{query}") return result if result.is_a?(Array) result['items'] || result['data'] || [] end |
#put_document(collection_id:, title:, body:, uri:) ⇒ Hash
Create or update a document (upsert by URI).
Documents are unique by ‘uri` across the organization. If a document with the given URI exists, it is updated; otherwise it is created. Documents become available for queries within ~1 minute.
74 75 76 77 78 79 80 81 |
# File 'lib/woods/unblocked/client.rb', line 74 def put_document(collection_id:, title:, body:, uri:) request(:put, 'documents', { collectionId: collection_id, title: title, body: body, uri: uri }) end |