trmnl-api 0.7.0 → 0.9.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f9fb20c5a06061df12d534be39e9d165b7774a7854f35c6c3b89ee4021f6831c
4
- data.tar.gz: 30da4deb5099f07f3c23be8e093cc7e926718545919d2ecdd06c035006649a30
3
+ metadata.gz: cb8a2557d167924338d70a68b91207d89f48b72a44e66e252fd0760fc3ffc035
4
+ data.tar.gz: 4c3329056c42c1b57347eb00b748f0baf384720c67aeacf938ce2dcecee4a2e3
5
5
  SHA512:
6
- metadata.gz: eaa11f3d4ba80ce5eae39682e952536a1b05f1577d856e217028a8164b44b5d123ae188700c3b096205ca743dbb3b291cea7643094678f49f81a28c96bd42719
7
- data.tar.gz: fd5cb1d4372bbce29288d3d466b730223f51d4fca707ab9b432eb79cb987140a8ac6767ca49d60aa6a2e3100a8a422c3bab77be1137fc6463d1d180d0c49d73d
6
+ metadata.gz: 6b7a621e59c10820c52b5dbad143b03399544297fba3faa89078a938539ef53cbb7c823a1028f24930fa4edd56d21c2788a440bdf5b3310ccba8d8dac1fc7f06
7
+ data.tar.gz: b67362a9aa48c7a4009e5b7f59201378c69bca85de6bb560e4c1b208ab6c5bc15c64e6edceb17d3d6a163b7f1fae00fffb3052c987cb9ee4a851c131b713ead9
checksums.yaml.gz.sig CHANGED
Binary file
data/README.adoc CHANGED
@@ -3,17 +3,18 @@
3
3
  :figure-caption!:
4
4
 
5
5
  :trmnl_link: link:https://usetrmnl.com[TRMNL]
6
+ :trmnl_api_link: link:https://usetrmnl.com/api-docs/index.html[TRMNL API]
6
7
  :dry_monads_link: link:https://dry-rb.org/gems/dry-monads[Dry Monads]
7
8
 
8
9
  = TRMNL API
9
10
 
10
- A monadic {trmnl_link} API client. You can use this client in your own code to interact with our APIs for any/all devices that you own.
11
+ A monadic {trmnl_api_link} client. You can use this client in your own code to interact with our APIs for any/all devices that you own.
11
12
 
12
13
  toc::[]
13
14
 
14
15
  == Features
15
16
 
16
- * Provides {trmnl_link} API access.
17
+ * Provides {trmnl_api_link} access.
17
18
 
18
19
  == Requirements
19
20
 
@@ -48,7 +49,7 @@ require "trmnl/api"
48
49
  This client provides access to multiple endpoints. Each endpoint will answer either a `Success` or `Failure` (as provided by {dry_monads_link}) based on result of the API call. This allows you pattern match in your own code when using each endpoint. Example:
49
50
 
50
51
  ``` ruby
51
- client = TRMNL::API::Client.new
52
+ client = TRMNL::API.new
52
53
 
53
54
  case client.display token: "secret"
54
55
  in Success(payload) then puts payload
@@ -65,7 +66,7 @@ By default, you shouldn't need to change the default configuration but you can a
65
66
 
66
67
  [source,ruby]
67
68
  ----
68
- client = TRMNL::API::Client.new do |settings|
69
+ client = TRMNL::API.new do |settings|
69
70
  settings.content_type = "application/json",
70
71
  settings.uri = "https://trmnl.app/api"
71
72
  end
@@ -88,7 +89,7 @@ Allows you to obtain the list of approved plugin categories. Example:
88
89
 
89
90
  [source,ruby]
90
91
  ----
91
- client = TRMNL::API::Client.new
92
+ client = TRMNL::API.new
92
93
  client.categories
93
94
 
94
95
  # Success(
@@ -106,7 +107,7 @@ Allows you to obtain current screen being displayed for your device. You must su
106
107
 
107
108
  [source,ruby]
108
109
  ----
109
- client = TRMNL::API::Client.new
110
+ client = TRMNL::API.new
110
111
  client.current_screen token: "secret"
111
112
 
112
113
  # Success(
@@ -124,7 +125,7 @@ Allows you to obtain current screen being displayed for your device with additio
124
125
 
125
126
  [source,ruby]
126
127
  ----
127
- client = TRMNL::API::Client.new
128
+ client = TRMNL::API.new
128
129
  client.display token: "secret"
129
130
 
130
131
  # Success(
@@ -147,7 +148,7 @@ Allows you to obtain the current stable firmware version. Example:
147
148
 
148
149
  [source,ruby]
149
150
  ----
150
- client = TRMNL::API::Client.new
151
+ client = TRMNL::API.new
151
152
  client.firmware
152
153
 
153
154
  # Success(#<data TRMNL::API::Models::Firmware url="https://trmnl-fw.s3.us-east-2.amazonaws.com/FW1.4.8.bin", version="1.4.8">)
@@ -159,7 +160,7 @@ Allows you obtain a list of public IP addresses for all TRMNL core servers becau
159
160
 
160
161
  [source,ruby]
161
162
  ----
162
- client = TRMNL::API::Client.new
163
+ client = TRMNL::API.new
163
164
  client.ip_addresses
164
165
 
165
166
  # Success(
@@ -182,7 +183,7 @@ Allows you to create a log entry (which is what the device reports when it captu
182
183
 
183
184
  [source,ruby]
184
185
  ----
185
- client = TRMNL::API::Client.new
186
+ client = TRMNL::API.new
186
187
  client.log token: "secret",
187
188
  log: {
188
189
  logs_array: [
@@ -221,7 +222,7 @@ Allows you to obtain the model information for all devices and screens. Example:
221
222
 
222
223
  [source,ruby]
223
224
  ----
224
- client = TRMNL::API::Client.new
225
+ client = TRMNL::API.new
225
226
  client.models
226
227
 
227
228
  # Success(
@@ -276,7 +277,7 @@ Allows you to obtain palettes details. The IDs correlate to the `palette_ids` as
276
277
 
277
278
  [source,ruby]
278
279
  ----
279
- client = TRMNL::API::Client.new
280
+ client = TRMNL::API.new
280
281
  client.palettes
281
282
 
282
283
  Success(
@@ -299,13 +300,94 @@ Success(
299
300
  )
300
301
  ----
301
302
 
303
+ ==== Recipes
304
+
305
+ Allows you to obtain information about link:https://usetrmnl.com/recipes[Recipes]. Example:
306
+
307
+ ⚠️ This _does not_ use the {trmnl_api_link} like every other endpoint documented here. This is why you must customize the settings URI to point to the root of the TRMNL application instead of using the default API endpoint.
308
+
309
+ [source,ruby]
310
+ ----
311
+ client = TRMNL::API.new { |settings| settings.uri = "https://usetrmnl.com" }
312
+
313
+ client.recipes # Answers first page.
314
+ client.recipes page: 10 # Answers page ten.
315
+ client.recipes search: "comic" # Answers first page of comics.
316
+ client.recipes "sort-by": "popularity" # Answers first page sorted by popularity.
317
+
318
+ # Success(
319
+ # #<data TRMNL::API::Models::Recipe:0x0000b4d0
320
+ # current_page = 1,
321
+ # data = [
322
+ # #<Struct:TRMNL::API::Models::Recipes::Entry:0x0000b4f0
323
+ # author = #<Struct:TRMNL::API::Models::Recipes::Author:0x0000b500
324
+ # category = "travel",
325
+ # description = "Displays upcoming...",
326
+ # description_locales = {},
327
+ # email_address = nil,
328
+ # field_type = "author_bio",
329
+ # github_url = "https://github.com/CaptainProton42/trmnl-bustimes-org",
330
+ # keyname = "readme",
331
+ # learn_more_url = nil,
332
+ # name = "About This Plugin",
333
+ # youtube_url = nil
334
+ # >,
335
+ # custom_fields = [
336
+ # {
337
+ # "keyname" => "readme",
338
+ # "name" => "About This Plugin",
339
+ # "category" => "travel",
340
+ # "field_type" => "author_bio",
341
+ # "description" => "Displays upcoming...",
342
+ # "github_url" => "https://github.com/CaptainProton42/trmnl-bustimes-org"
343
+ # },
344
+ # {
345
+ # "keyname" => "atco",
346
+ # "field_type" => "string",
347
+ # "name" => "Bus Stop",
348
+ # "description" => "The <a href=\"https://mullinscr.github.io/naptan/atco_codes/\">ATCO</a> code for your bus stop.",
349
+ # "help_text" => "You can find this..."
350
+ # },
351
+ # {
352
+ # "keyname" => "bus",
353
+ # "field_type" => "multi_string",
354
+ # "name" => "Busses",
355
+ # "description" => "Optionally, choose specific bus services you want to display departures for.",
356
+ # "help_text" => "Use the name of the service, e.g. '10' or '3A'.",
357
+ # "optional" => true
358
+ # }
359
+ # ],
360
+ # icon_content_type = "image/png",
361
+ # icon_url = "https://trmnl-public.s3.us-east-2.amazonaws.com/59lqujqwid1cvzsd7sr3erfuexur",
362
+ # id = 222328,
363
+ # name = "UK Bus Departures (bustimes.org)",
364
+ # published_at = 2026-01-14 22:53:07.587 UTC,
365
+ # screenshot_url = "https://trmnl.s3.us-east-2.amazonaws.com...",
366
+ # statistics = #<data TRMNL::API::Models::Recipes::Statistics:0x0000b710
367
+ # forks = 0,
368
+ # installs = 1
369
+ # >
370
+ # >
371
+ # ],
372
+ # from = 1,
373
+ # next_page_url = "/recipes.json?page=2",
374
+ # per_page = 25,
375
+ # prev_page_url = nil,
376
+ # to = 25,
377
+ # total = 658
378
+ # >
379
+ # )
380
+ ----
381
+
382
+ You'll always get a `data` array with may or may not be filled. Pagination information is listed at the bottom.
383
+
302
384
  ==== Setup
303
385
 
304
386
  Allows you to obtain the setup response for when a new device is setup. You must supply your device's MAC Address as the `id`. Example:
305
387
 
306
388
  [source,ruby]
307
389
  ----
308
- client = TRMNL::API::Client.new
390
+ client = TRMNL::API.new
309
391
  client.setup id: "A1:B2:C3:D4:E5:F6"
310
392
 
311
393
  # Success(
@@ -7,53 +7,56 @@ module TRMNL
7
7
  # Provides the primary client for making API requests.
8
8
  class Client
9
9
  include Dependencies[:settings]
10
+ include Inspectable[:endpoints]
11
+
12
+ ENDPOINTS = {
13
+ categories: Endpoints::Category,
14
+ current_screen: Endpoints::CurrentScreen,
15
+ display: Endpoints::Display,
16
+ firmware: Endpoints::Firmware,
17
+ ip_addresses: Endpoints::IPAddress,
18
+ log: Endpoints::Log,
19
+ models: Endpoints::Model,
20
+ palettes: Endpoints::Palette,
21
+ recipes: Endpoints::Recipe,
22
+ setup: Endpoints::Setup
23
+ }.freeze
24
+
25
+ def initialize(requester: Requester, endpoints: ENDPOINTS, **)
26
+ super(**)
10
27
 
11
- include Endpoints::Dependencies[
12
- endpoint_categories: :categories,
13
- endpoint_current_screen: :current_screen,
14
- endpoint_display: :display,
15
- endpoint_firmware: :firmware,
16
- endpoint_ip_addresses: :ip_addresses,
17
- endpoint_log: :log,
18
- endpoint_models: :models,
19
- endpoint_palettes: :palettes,
20
- endpoint_setup: :setup
21
- ]
22
-
23
- include Inspectable[
24
- endpoint_categories: :class,
25
- endpoint_current_screen: :class,
26
- endpoint_display: :class,
27
- endpoint_firmware: :class,
28
- endpoint_ip_addresses: :class,
29
- endpoint_log: :class,
30
- endpoint_models: :class,
31
- endpoint_palettes: :class,
32
- endpoint_setup: :class
33
- ]
34
-
35
- def initialize(**)
36
- super
37
28
  yield settings if block_given?
29
+
30
+ requester = requester.new(settings:)
31
+
32
+ @endpoints = endpoints.each.with_object({}) do |(key, value), all|
33
+ all[key] = value.new requester:
34
+ end
38
35
  end
39
36
 
40
- def categories = endpoint_categories.call
37
+ def categories = endpoints.fetch(__method__).call
38
+
39
+ def current_screen(**) = endpoints.fetch(__method__).call(**)
40
+
41
+ def display(**) = endpoints.fetch(__method__).call(**)
42
+
43
+ def firmware = endpoints.fetch(__method__).call
41
44
 
42
- def current_screen(**) = endpoint_current_screen.call(**)
45
+ def ip_addresses = endpoints.fetch(__method__).call
43
46
 
44
- def display(**) = endpoint_display.call(**)
47
+ def log(**) = endpoints.fetch(__method__).call(**)
45
48
 
46
- def firmware = endpoint_firmware.call
49
+ def models(**) = endpoints.fetch(__method__).call(**)
47
50
 
48
- def ip_addresses = endpoint_ip_addresses.call
51
+ def palettes = endpoints.fetch(__method__).call
49
52
 
50
- def log(**) = endpoint_log.call(**)
53
+ def recipes(**) = endpoints.fetch(__method__).call(**)
51
54
 
52
- def models(**) = endpoint_models.call(**)
55
+ def setup(**) = endpoints.fetch(__method__).call(**)
53
56
 
54
- def palettes = endpoint_palettes.call
57
+ private
55
58
 
56
- def setup(**) = endpoint_setup.call(**)
59
+ attr_reader :endpoints
57
60
  end
58
61
  end
59
62
  end
@@ -10,7 +10,7 @@ module TRMNL
10
10
  module Container
11
11
  extend Containable
12
12
 
13
- register(:settings) { TRMNL::API::Configuration::Loader.new.call }
13
+ register(:settings, as: :fresh) { TRMNL::API::Configuration::Loader.new.call }
14
14
  register(:requester) { API::Requester.new }
15
15
  register(:logger) { Cogger.new id: "trmnl-api", formatter: :json }
16
16
 
@@ -27,6 +27,7 @@ module TRMNL
27
27
  register :ip_address, Contracts::IPAddress
28
28
  register :model, Contracts::Model
29
29
  register :palette, Contracts::Palette
30
+ register :recipe, Contracts::Recipe
30
31
  register :setup, Contracts::Setup
31
32
  end
32
33
 
@@ -37,6 +38,7 @@ module TRMNL
37
38
  register :ip_address, Models::IPAddress
38
39
  register :model, Models::Model
39
40
  register :palette, Models::Palette
41
+ register :recipe, Models::Recipe
40
42
  register :setup, Models::Setup
41
43
  end
42
44
  end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/schema"
4
+
5
+ module TRMNL
6
+ module API
7
+ module Contracts
8
+ # Validates API response.
9
+ Recipe = Dry::Schema.JSON do
10
+ required(:data).array(:hash) do
11
+ required(:id).filled :integer
12
+ required(:name).filled :string
13
+ required(:screenshot_url).filled :string
14
+ required(:published_at).filled :time
15
+ optional(:icon_url).maybe :string
16
+ optional(:icon_content_type).maybe :string
17
+ required(:author_bio).maybe Recipes::Author
18
+ required(:custom_fields).array(:hash)
19
+
20
+ required(:stats).filled :hash do
21
+ required(:installs).filled :integer
22
+ required(:forks).filled :integer
23
+ end
24
+ end
25
+
26
+ required(:total).filled :integer
27
+ required(:from).filled :integer
28
+ required(:to).filled :integer
29
+ required(:per_page).filled :integer
30
+ required(:current_page).filled :integer
31
+ required(:prev_page_url).maybe :string
32
+ required(:next_page_url).maybe :string
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/schema"
4
+
5
+ module TRMNL
6
+ module API
7
+ module Contracts
8
+ module Recipes
9
+ # Validates API response.
10
+ Author = Dry::Schema.JSON do
11
+ required(:keyname).filled :string
12
+ required(:name).filled :string
13
+ required(:field_type).filled :string
14
+ optional(:category).filled :string
15
+ optional(:description).filled :string
16
+ optional(:"description-de").filled :string
17
+ optional(:"description-nl").filled :string
18
+ optional(:"description-fr").filled :string
19
+ optional(:"description-en").filled :string
20
+ optional(:"description-en-GB").filled :string
21
+ optional(:"description-es-ES").filled :string
22
+ optional(:"description-it").filled :string
23
+ optional(:"description-no").filled :string
24
+ optional(:"description-da").filled :string
25
+ optional(:"description-ja").filled :string
26
+ optional(:"description-de-AT").filled :string
27
+ optional(:"description-ko").filled :string
28
+ optional(:"description-sv").filled :string
29
+ optional(:"description-pt-BR").filled :string
30
+ optional(:"description-zh-HK").filled :string
31
+ optional(:"description-pl").filled :string
32
+ optional(:"description-uk").filled :string
33
+ optional(:"description-zh-CN").filled :string
34
+ optional(:"description-hu").filled :string
35
+ optional(:"description-he").filled :string
36
+ optional(:"description-sk").filled :string
37
+ optional(:"description-ru").filled :string
38
+ optional(:"description-is").filled :string
39
+ optional(:"description-id").filled :string
40
+ optional(:email_address).filled :string
41
+ optional(:learn_more_url).filled :string
42
+ optional(:github_url).filled :string
43
+ optional(:youtube_url).filled :string
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -10,7 +10,7 @@ module TRMNL
10
10
  class Category
11
11
  include TRMNL::API::Dependencies[:requester, contract: "contracts.category"]
12
12
 
13
- include Inspectable[contract: :class]
13
+ include Inspectable[contract: :type]
14
14
  include Pipeable
15
15
 
16
16
  def call
@@ -17,6 +17,7 @@ module TRMNL
17
17
  register(:log) { Log.new }
18
18
  register(:models) { Model.new }
19
19
  register(:palettes) { Palette.new }
20
+ register(:recipes) { Recipe.new }
20
21
  register(:setup) { Setup.new }
21
22
  end
22
23
  end
@@ -14,7 +14,7 @@ module TRMNL
14
14
  model: "models.current_screen"
15
15
  ]
16
16
 
17
- include Inspectable[contract: :class]
17
+ include Inspectable[contract: :type]
18
18
  include Pipeable
19
19
 
20
20
  def call token:
@@ -14,7 +14,7 @@ module TRMNL
14
14
  model: "models.display"
15
15
  ]
16
16
 
17
- include Inspectable[contract: :class]
17
+ include Inspectable[contract: :type]
18
18
  include Pipeable
19
19
 
20
20
  def call token:
@@ -14,7 +14,7 @@ module TRMNL
14
14
  model: "models.firmware"
15
15
  ]
16
16
 
17
- include Inspectable[contract: :class]
17
+ include Inspectable[contract: :type]
18
18
  include Pipeable
19
19
 
20
20
  def call
@@ -14,7 +14,7 @@ module TRMNL
14
14
  model: "models.ip_address"
15
15
  ]
16
16
 
17
- include Inspectable[contract: :class]
17
+ include Inspectable[contract: :type]
18
18
  include Pipeable
19
19
 
20
20
  def call
@@ -14,7 +14,7 @@ module TRMNL
14
14
  model: "models.model"
15
15
  ]
16
16
 
17
- include Inspectable[contract: :class]
17
+ include Inspectable[contract: :type]
18
18
  include Pipeable
19
19
 
20
20
  def call
@@ -14,7 +14,7 @@ module TRMNL
14
14
  model: "models.palette"
15
15
  ]
16
16
 
17
- include Inspectable[contract: :class]
17
+ include Inspectable[contract: :type]
18
18
  include Pipeable
19
19
 
20
20
  def call
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "inspectable"
4
+ require "pipeable"
5
+
6
+ module TRMNL
7
+ module API
8
+ module Endpoints
9
+ # Handles API request/response.
10
+ class Recipe
11
+ include TRMNL::API::Dependencies[
12
+ :requester,
13
+ contract: "contracts.recipe",
14
+ model: "models.recipe"
15
+ ]
16
+
17
+ include Inspectable[contract: :type]
18
+ include Pipeable
19
+
20
+ def call(**)
21
+ pipe(
22
+ requester.get("recipes.json", **),
23
+ try(:parse, catch: JSON::ParserError),
24
+ validate(contract, as: :to_h),
25
+ to(model, :for)
26
+ )
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -14,7 +14,7 @@ module TRMNL
14
14
  model: "models.setup"
15
15
  ]
16
16
 
17
- include Inspectable[contract: :class]
17
+ include Inspectable[contract: :type]
18
18
  include Pipeable
19
19
 
20
20
  def call id:
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TRMNL
4
+ module API
5
+ LocaleReducer = lambda do |attributes, prefix: "description-"|
6
+ attributes.each.with_object({}) do |(key, value), all|
7
+ next unless key.start_with? prefix
8
+
9
+ attributes.delete key
10
+ all[key.to_s.delete_prefix(prefix)] = value
11
+ end
12
+ end
13
+ end
14
+ end
@@ -3,7 +3,7 @@
3
3
  module TRMNL
4
4
  module API
5
5
  module Models
6
- # Models API response.
6
+ # Models the data of the API response.
7
7
  CurrentScreen = Data.define :refresh_rate, :image_url, :filename do
8
8
  def self.for(attributes) = new(**attributes)
9
9
  end
@@ -3,7 +3,7 @@
3
3
  module TRMNL
4
4
  module API
5
5
  module Models
6
- # Models data for API display responses.
6
+ # Models the data of the API response.
7
7
  Display = Struct.new(
8
8
  :filename,
9
9
  :firmware_url,
@@ -3,7 +3,7 @@
3
3
  module TRMNL
4
4
  module API
5
5
  module Models
6
- # Models API response.
6
+ # Models the data of the API response.
7
7
  Firmware = Data.define :url, :version do
8
8
  def self.for(attributes) = new(**attributes)
9
9
  end
@@ -3,7 +3,7 @@
3
3
  module TRMNL
4
4
  module API
5
5
  module Models
6
- # IPs API response.
6
+ # Models the data of the API response.
7
7
  IPAddress = Data.define :version_4, :version_6 do
8
8
  def self.for attributes
9
9
  new(**attributes.transform_keys(ipv4: :version_4, ipv6: :version_6))
@@ -3,7 +3,7 @@
3
3
  module TRMNL
4
4
  module API
5
5
  module Models
6
- # Models data for API display responses.
6
+ # Models the data of the API response.
7
7
  Model = Struct.new(
8
8
  :name,
9
9
  :label,
@@ -3,8 +3,8 @@
3
3
  module TRMNL
4
4
  module API
5
5
  module Models
6
- # IPs API response.
7
- Palette = Data.define :id, :name, :grays, :colors, :framework_class do
6
+ # Models the data of the API response.
7
+ Palette = Struct.new :id, :name, :grays, :colors, :framework_class do
8
8
  def self.for(attributes) = new(**attributes)
9
9
  end
10
10
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TRMNL
4
+ module API
5
+ module Models
6
+ # Models the data of the API response.
7
+ Recipe = Data.define(
8
+ :data,
9
+ :total,
10
+ :from,
11
+ :to,
12
+ :per_page,
13
+ :current_page,
14
+ :prev_page_url,
15
+ :next_page_url
16
+ ) do
17
+ def self.for(**attributes)
18
+ data = attributes[:data].map { Recipes::Entry.for(**it) }
19
+ new(**attributes.merge!(data:))
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TRMNL
4
+ module API
5
+ module Models
6
+ module Recipes
7
+ # Models the author of the API response.
8
+ Author = Struct.new(
9
+ :keyname,
10
+ :name,
11
+ :field_type,
12
+ :category,
13
+ :description,
14
+ :description_locales,
15
+ :email_address,
16
+ :learn_more_url,
17
+ :github_url,
18
+ :youtube_url
19
+ ) do
20
+ def self.for(locale_reducer: LocaleReducer, **attributes)
21
+ description_locales = locale_reducer.call attributes
22
+ new(description_locales:, **attributes)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TRMNL
4
+ module API
5
+ module Models
6
+ module Recipes
7
+ # Models the data of the API response.
8
+ Entry = Struct.new(
9
+ :id,
10
+ :name,
11
+ :icon_url,
12
+ :icon_content_type,
13
+ :screenshot_url,
14
+ :author,
15
+ :custom_fields,
16
+ :statistics,
17
+ :published_at
18
+ ) do
19
+ def self.for(**attributes)
20
+ new(
21
+ **attributes.merge!(
22
+ author: Author.for(**attributes.delete(:author_bio)),
23
+ statistics: Statistics[**attributes.delete(:stats)]
24
+ )
25
+ )
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TRMNL
4
+ module API
5
+ module Models
6
+ module Recipes
7
+ # Models the statistics of the API response.
8
+ Statistics = Data.define :installs, :forks
9
+ end
10
+ end
11
+ end
12
+ end
@@ -3,7 +3,7 @@
3
3
  module TRMNL
4
4
  module API
5
5
  module Models
6
- # Models API response.
6
+ # Models the data of the API response.
7
7
  Setup = Data.define :api_key, :friendly_id, :image_url, :message do
8
8
  def self.for(attributes) = new(**attributes)
9
9
  end
@@ -23,18 +23,20 @@ module TRMNL
23
23
 
24
24
  private
25
25
 
26
- attr_reader :settings, :http
27
-
28
26
  def call method, path, headers, **options
29
27
  http.headers(settings.headers.merge(headers))
30
28
  .public_send(method, uri(path), options)
31
29
  .then { |response| response.status.success? ? Success(response) : Failure(response) }
30
+ rescue HTTP::RequestError => error then handle_bad_request path, error
32
31
  rescue HTTP::ConnectionError => error then handle_bad_connection path, error
33
32
  rescue HTTP::TimeoutError => error then handle_timeout path, error
34
33
  rescue OpenSSL::SSL::SSLError => error then handle_bad_ssl path, error
35
34
  end
36
35
 
37
- def uri(path) = "#{settings.uri}/#{path}"
36
+ def handle_bad_request path, error
37
+ logger.debug { error.message }
38
+ Failure "Unable to make request: #{uri(path).inspect}. Is the URI valid?"
39
+ end
38
40
 
39
41
  def handle_bad_connection path, error
40
42
  logger.debug { error.message }
@@ -51,6 +53,8 @@ module TRMNL
51
53
  Failure "Unable to secure connection: #{uri(path).inspect}. " \
52
54
  "Is your certificate or SSL valid?"
53
55
  end
56
+
57
+ def uri(path) = "#{settings.uri}/#{path}"
54
58
  end
55
59
  end
56
60
  end
data/trmnl-api.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "trmnl-api"
5
- spec.version = "0.7.0"
5
+ spec.version = "0.9.0"
6
6
  spec.authors = ["TRMNL"]
7
7
  spec.email = ["engineering@usetrmnl.com"]
8
8
  spec.homepage = "https://github.com/usetrmnl/trmnl-api"
@@ -21,18 +21,17 @@ Gem::Specification.new do |spec|
21
21
  spec.signing_key = Gem.default_key_path
22
22
  spec.cert_chain = [Gem.default_cert_path]
23
23
 
24
- spec.required_ruby_version = ">= 3.4"
24
+ spec.required_ruby_version = ">= 4.0"
25
25
 
26
- spec.add_dependency "cogger", "~> 1.4"
27
- spec.add_dependency "containable", "~> 1.2"
28
- spec.add_dependency "dry-monads", "~> 1.8"
26
+ spec.add_dependency "cogger", "~> 2.0"
27
+ spec.add_dependency "containable", "~> 2.0"
28
+ spec.add_dependency "dry-monads", "~> 1.9"
29
29
  spec.add_dependency "dry-schema", "~> 1.14"
30
30
  spec.add_dependency "dry-types", "~> 1.8"
31
31
  spec.add_dependency "http", "~> 5.3"
32
- spec.add_dependency "infusible", "~> 4.3"
33
- spec.add_dependency "inspectable", "~> 0.3"
34
- spec.add_dependency "openssl", "~> 3.3"
35
- spec.add_dependency "pipeable", "~> 1.3"
32
+ spec.add_dependency "infusible", "~> 5.0"
33
+ spec.add_dependency "inspectable", "~> 1.0"
34
+ spec.add_dependency "pipeable", "~> 2.0"
36
35
  spec.add_dependency "zeitwerk", "~> 2.7"
37
36
 
38
37
  spec.extra_rdoc_files = Dir["README*", "LICENSE*"]
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trmnl-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - TRMNL
@@ -41,42 +41,42 @@ dependencies:
41
41
  requirements:
42
42
  - - "~>"
43
43
  - !ruby/object:Gem::Version
44
- version: '1.4'
44
+ version: '2.0'
45
45
  type: :runtime
46
46
  prerelease: false
47
47
  version_requirements: !ruby/object:Gem::Requirement
48
48
  requirements:
49
49
  - - "~>"
50
50
  - !ruby/object:Gem::Version
51
- version: '1.4'
51
+ version: '2.0'
52
52
  - !ruby/object:Gem::Dependency
53
53
  name: containable
54
54
  requirement: !ruby/object:Gem::Requirement
55
55
  requirements:
56
56
  - - "~>"
57
57
  - !ruby/object:Gem::Version
58
- version: '1.2'
58
+ version: '2.0'
59
59
  type: :runtime
60
60
  prerelease: false
61
61
  version_requirements: !ruby/object:Gem::Requirement
62
62
  requirements:
63
63
  - - "~>"
64
64
  - !ruby/object:Gem::Version
65
- version: '1.2'
65
+ version: '2.0'
66
66
  - !ruby/object:Gem::Dependency
67
67
  name: dry-monads
68
68
  requirement: !ruby/object:Gem::Requirement
69
69
  requirements:
70
70
  - - "~>"
71
71
  - !ruby/object:Gem::Version
72
- version: '1.8'
72
+ version: '1.9'
73
73
  type: :runtime
74
74
  prerelease: false
75
75
  version_requirements: !ruby/object:Gem::Requirement
76
76
  requirements:
77
77
  - - "~>"
78
78
  - !ruby/object:Gem::Version
79
- version: '1.8'
79
+ version: '1.9'
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: dry-schema
82
82
  requirement: !ruby/object:Gem::Requirement
@@ -125,56 +125,42 @@ dependencies:
125
125
  requirements:
126
126
  - - "~>"
127
127
  - !ruby/object:Gem::Version
128
- version: '4.3'
128
+ version: '5.0'
129
129
  type: :runtime
130
130
  prerelease: false
131
131
  version_requirements: !ruby/object:Gem::Requirement
132
132
  requirements:
133
133
  - - "~>"
134
134
  - !ruby/object:Gem::Version
135
- version: '4.3'
135
+ version: '5.0'
136
136
  - !ruby/object:Gem::Dependency
137
137
  name: inspectable
138
138
  requirement: !ruby/object:Gem::Requirement
139
139
  requirements:
140
140
  - - "~>"
141
141
  - !ruby/object:Gem::Version
142
- version: '0.3'
143
- type: :runtime
144
- prerelease: false
145
- version_requirements: !ruby/object:Gem::Requirement
146
- requirements:
147
- - - "~>"
148
- - !ruby/object:Gem::Version
149
- version: '0.3'
150
- - !ruby/object:Gem::Dependency
151
- name: openssl
152
- requirement: !ruby/object:Gem::Requirement
153
- requirements:
154
- - - "~>"
155
- - !ruby/object:Gem::Version
156
- version: '3.3'
142
+ version: '1.0'
157
143
  type: :runtime
158
144
  prerelease: false
159
145
  version_requirements: !ruby/object:Gem::Requirement
160
146
  requirements:
161
147
  - - "~>"
162
148
  - !ruby/object:Gem::Version
163
- version: '3.3'
149
+ version: '1.0'
164
150
  - !ruby/object:Gem::Dependency
165
151
  name: pipeable
166
152
  requirement: !ruby/object:Gem::Requirement
167
153
  requirements:
168
154
  - - "~>"
169
155
  - !ruby/object:Gem::Version
170
- version: '1.3'
156
+ version: '2.0'
171
157
  type: :runtime
172
158
  prerelease: false
173
159
  version_requirements: !ruby/object:Gem::Requirement
174
160
  requirements:
175
161
  - - "~>"
176
162
  - !ruby/object:Gem::Version
177
- version: '1.3'
163
+ version: '2.0'
178
164
  - !ruby/object:Gem::Dependency
179
165
  name: zeitwerk
180
166
  requirement: !ruby/object:Gem::Requirement
@@ -211,6 +197,8 @@ files:
211
197
  - lib/trmnl/api/contracts/ip_address.rb
212
198
  - lib/trmnl/api/contracts/model.rb
213
199
  - lib/trmnl/api/contracts/palette.rb
200
+ - lib/trmnl/api/contracts/recipe.rb
201
+ - lib/trmnl/api/contracts/recipes/author.rb
214
202
  - lib/trmnl/api/contracts/setup.rb
215
203
  - lib/trmnl/api/dependencies.rb
216
204
  - lib/trmnl/api/endpoints/category.rb
@@ -223,13 +211,19 @@ files:
223
211
  - lib/trmnl/api/endpoints/log.rb
224
212
  - lib/trmnl/api/endpoints/model.rb
225
213
  - lib/trmnl/api/endpoints/palette.rb
214
+ - lib/trmnl/api/endpoints/recipe.rb
226
215
  - lib/trmnl/api/endpoints/setup.rb
216
+ - lib/trmnl/api/locale_reducer.rb
227
217
  - lib/trmnl/api/models/current_screen.rb
228
218
  - lib/trmnl/api/models/display.rb
229
219
  - lib/trmnl/api/models/firmware.rb
230
220
  - lib/trmnl/api/models/ip_address.rb
231
221
  - lib/trmnl/api/models/model.rb
232
222
  - lib/trmnl/api/models/palette.rb
223
+ - lib/trmnl/api/models/recipe.rb
224
+ - lib/trmnl/api/models/recipes/author.rb
225
+ - lib/trmnl/api/models/recipes/entry.rb
226
+ - lib/trmnl/api/models/recipes/statistics.rb
233
227
  - lib/trmnl/api/models/setup.rb
234
228
  - lib/trmnl/api/requester.rb
235
229
  - lib/trmnl/api/types.rb
@@ -251,14 +245,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
251
245
  requirements:
252
246
  - - ">="
253
247
  - !ruby/object:Gem::Version
254
- version: '3.4'
248
+ version: '4.0'
255
249
  required_rubygems_version: !ruby/object:Gem::Requirement
256
250
  requirements:
257
251
  - - ">="
258
252
  - !ruby/object:Gem::Version
259
253
  version: '0'
260
254
  requirements: []
261
- rubygems_version: 4.0.1
255
+ rubygems_version: 4.0.4
262
256
  specification_version: 4
263
257
  summary: A monadic TRMNL API client.
264
258
  test_files: []
metadata.gz.sig CHANGED
Binary file