lws 10.0.0 → 11.0.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: 853db9b24d98b75c7b419c19b8942411b30f74c1e03fae81279a1a4b77228342
4
- data.tar.gz: 94afe71cf0b4a1e1c346b4980daf3fcd91059a5ade23db17c5a63a8444603af3
3
+ metadata.gz: f9060d0e061184ea7c8048291d6966629e271070ad3a96a6623e54861cc5f817
4
+ data.tar.gz: ca0e91888477bc818ec43ab7b8b9b2b44af1444b02abcc4f0b0a08e576663517
5
5
  SHA512:
6
- metadata.gz: d57fd5aa31bef7f4329b62d2d598efa09ca2b6c83bbce691e3952bf1e641129144f527fca41c1e35241feefef51734d56a3230e6110b5e2cddb3101d570a00e7
7
- data.tar.gz: 33082b8ba056f64543e91883309752b3978c992b88e2cda39969312c5938d997fb91b18bcc8fcfe7c43ce12dc66bdbf0b9f8e517c57d59d2bababb941451899a
6
+ metadata.gz: 364a82c69867855dda2f27187112233b844b0ec2d5533dc5023f6c68aac704f1ed93ce8bc17d01d5ca5e55500bacec3f93008ac54c871f203a474f8e8d09dd92
7
+ data.tar.gz: dcb07b606e2a2464b0be0acc7afc63f690de9c7e8d953bfa1602f290a1d93901e7a1096024c7fde6ccdfad37bb392e7fa408c8702e702473751335fd47f49971
data/CHANGELOG.md CHANGED
@@ -8,6 +8,60 @@ of LWS in the major/minor part of te version.
8
8
 
9
9
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
10
10
 
11
+ ## [11.0.0] - 2025-09-30
12
+
13
+ The biggest change in this release is the complete rework of the API of the
14
+ Resource app. Instead of using subclasses of collection and collection items,
15
+ there is now only a collection and collection item model and each has a
16
+ metadata object attached that is specific to its kind.
17
+
18
+ ### Added
19
+
20
+ - Add and enable support for retrying a request 3 times
21
+ - Add `LWS::Errors::ServerError` class to indicate LWS server errors
22
+ - Add generic `Metadata` resource class (which is not a REST model)
23
+ - Add `Collection::Metadata`, `Collection::VimeoMetadata`,
24
+ `Collection::WeatherLocationMetadata` and `YouTubeMetadata` resource
25
+ subclasses
26
+ - Add `Collection::Item::Metadata`, `Collection::Item::Forecast`,
27
+ `Collection::Item::ImageMetadata`, `Collection::Item::PDFMetadata`,
28
+ `Collection::Item::PowerPointMetadata`, `Collection::Item::VideoMetadata`,
29
+ `Collection::Item::VimeoMetadata` and `Collection::Item::YouTubeMetadata`
30
+ resource subclasses
31
+ - Add metadata classes for collection and collection item resource models
32
+
33
+ ### Changed
34
+
35
+ - All error classes are now subclasses of `LWS::Errors::Error`
36
+ - Raise `LWS::Errors::ServerError` when (after retrying) LWS server (still)
37
+ responds with a HTTP server error (HTTP error codes 500–599)
38
+ - Raise `LWS::Errors::ServerError` when previously a `Spyke::ConnectionError`
39
+ would have been raised
40
+ - Switch to Rubycop 1.69; update Rubocop todo-items
41
+
42
+ ### Removed
43
+
44
+ - Remove the `log_object` attribute from the player log model
45
+ - Remove the `Collection::Config`, `Collection::Feed`,
46
+ `Collection::Feed::Post`, `Collection::Image`, `Collection::Post`,
47
+ `Collection::Video`, `Collection::Vimeo`, `Collection::WeatherLocation`,
48
+ `Collection::WeatherLocation::Forefcast` and
49
+ `Collection::YouTube` resource models
50
+ - Drop support for the config, feed and unknown collection kind
51
+
52
+ ### Fixed
53
+
54
+ - Set correct version for dependency on `faraday-follow_redirects` gem
55
+ - Decreased minimum test coverage to 90% to work around simplecov issue
56
+ - Documentation fixes
57
+
58
+ ## [10.0.1] - 2024-10-10
59
+
60
+ ### Fixed
61
+
62
+ - Bring back the dependency on the `net-http-persistent` gem (in case Faraday
63
+ 1.x is used)
64
+
11
65
  ## [10.0.0] - 2024-10-10
12
66
 
13
67
  ### Added
@@ -571,3 +625,5 @@ Initial release
571
625
  [9.0.1]: https://gitlab.leftclick.network/platform/ruby-lws/compare/v9.0.0...v9.0.1
572
626
  [9.0.2]: https://gitlab.leftclick.network/platform/ruby-lws/compare/v9.0.1...v9.0.2
573
627
  [10.0.0]: https://gitlab.leftclick.network/platform/ruby-lws/compare/v9.0.2...v10.0.0
628
+ [10.0.1]: https://gitlab.leftclick.network/platform/ruby-lws/compare/v10.0.0...v10.0.1
629
+ [11.0.0]: https://gitlab.leftclick.network/platform/ruby-lws/compare/v10.0.1...v11.0.0
@@ -1302,10 +1302,6 @@ module LWS::DigitalSignage
1302
1302
  use_api LWS::DigitalSignage.api
1303
1303
  uri "players/:player_id/logs(/:id)"
1304
1304
 
1305
- # @!attribute log_object
1306
- # @return [String] the URL of the player log object
1307
- attribute :log_object
1308
-
1309
1305
  # @!attribute player
1310
1306
  # @return [Player] the player the log is produced by
1311
1307
  belongs_to :player, class_name: "LWS::DigitalSignage::Player"
@@ -61,6 +61,21 @@ module LWS::Generic
61
61
  raise LWS::Errors::ResourceNotFound, msg
62
62
  end
63
63
 
64
+ # @private
65
+ # @!visibility private
66
+ #
67
+ # Adds handling exceptions thrown by the raise error Faraday middleware.
68
+ #
69
+ # @param [String] method the HTTP method to use for the request
70
+ # @param [String] path the endpoint path to use for the request
71
+ # @param [Hash] params the query parameters to use for the request
72
+ def self.request(method, path, params = {})
73
+ super
74
+ rescue Spyke::ConnectionError => exception
75
+ msg = "connection failed/timed out for #{method.upcase} request on URI #{path}"
76
+ raise LWS::Errors::ServerError, msg
77
+ end
78
+
64
79
  # @private
65
80
  # @!visibility private
66
81
  #
@@ -42,10 +42,9 @@ module LWS::Resource
42
42
 
43
43
  # = The collection class
44
44
  #
45
- # There are two ways to view collections. Either it is viewed as a set
46
- # of items (see {#items}), or it is viewed as something that is associated
47
- # with one or more meta collections that each have specific item objects (see
48
- # for example {#feed}, {#image}, {#images}, etc.).
45
+ # A collection has a specific kind and contains a single or set of items.
46
+ # For some collection kinds, there is specific metadata (see {#metadata})
47
+ # available.
49
48
  class Collection < LWS::Generic::Model
50
49
  use_api LWS::Resource.api
51
50
 
@@ -94,16 +93,17 @@ module LWS::Resource
94
93
  attribute :item_ids
95
94
 
96
95
  # @!attribute items
97
- # The returned cllection item (sub)class that is determined by the kind
98
- # of this collection.
99
- #
100
96
  # @return [Array<Collection::Item>] the items that are part of the
101
97
  # collection
102
98
  has_many :items, class_name: "LWS::Resource::Collection::Item"
103
99
 
104
100
  # @!attribute kind
105
- # @return ["feed", "feeds", "image", "images", "video", "videos", "weather_location"]
106
- # the name of the class/kind of the collection
101
+ # @note
102
+ # This library only supports a subset of the available collection/item
103
+ # kinds.
104
+ # @return ["image", "other", "pdf", "powerpoint", "video", "vimeo",
105
+ # "weather_location", "youtube"] the name of the class/kind of the
106
+ # collection
107
107
  attribute :kind
108
108
 
109
109
  # @!attribute name
@@ -122,314 +122,449 @@ module LWS::Resource
122
122
  # @!attribute uuid
123
123
  # @return [String] the UUID used for unique file name generation
124
124
  attribute :uuid
125
- end
126
-
127
- # = The collection item class
128
- class Collection::Item < LWS::Generic::Model
129
- use_api LWS::Resource.api
130
- uri "collections/:collection_id/items(/:id)"
131
125
 
132
- # @!attribute collection
133
- # @return [Collection] the collection that the collection item is a
134
- # part of
135
- belongs_to :collection
136
-
137
- # @!attribute collection_id
138
- # @return [Integer] the ID of the collection that the collection item is a
139
- # part of
140
- attribute :collection_id
141
-
142
- # @!attribute metadata
143
- # @return [Hash] the metadata of the collection item
144
- attribute :metadata
145
-
146
- # @!attribute name
147
- # @return [String] the name of the collection item
148
- attribute :name
126
+ # Returns the metadata of the collection specific to its kind.
127
+ #
128
+ # @return [Collection::Metadata] the kind-specific metadata of the collection
129
+ def metadata
130
+ case kind
131
+ # when "feed"
132
+ # attrs =
133
+ # attributes["metadata"]
134
+ # .slice("feed_url", "refresh_interval")
135
+ # .symbolize_keys
136
+ # FeedMetadata.new(attrs)
137
+ when "vimeo"
138
+ attrs = attributes["metadata"]
139
+ .slice("video_url")
140
+ .symbolize_keys
141
+ VimeoMetadata.new(attrs)
142
+ when "weather_location"
143
+ attrs =
144
+ attributes["metadata"]
145
+ .slice("city", "country", "description", "feed_url",
146
+ "forecast_interval", "kind", "lat", "link", "long", "name",
147
+ "refresh_interval", "regio", "title", "token")
148
+ .symbolize_keys
149
+ WeatherLocationMetadata.new(attrs)
150
+ when "youtube"
151
+ attrs = attributes["metadata"]
152
+ .slice("video_url")
153
+ .symbolize_keys
154
+ YouTubeMetadata.new(attrs)
155
+ else
156
+ Metadata.new
157
+ end
158
+ end
159
+ end
149
160
 
150
- # @!attribute position
151
- # @return [Integer] the position of the item within the collection
152
- attribute :position
161
+ # = The metadata class
162
+ #
163
+ # This represents some kind of metadata of a collection/item that is specific to its kind.
164
+ class Metadata < Hashie::Dash
153
165
  end
154
166
 
155
- # = The collection config class
156
- class Collection::Config < Collection::Item
157
- use_api LWS::Resource.api
158
- uri "collections/:collection_id/configs(/:id)"
167
+ # = The collection metadata class.
168
+ #
169
+ # This represents some kind of metadata of a collection that is specific to its kind.
170
+ class Collection::Metadata < Metadata
159
171
  end
160
172
 
161
- # = The collection post class
162
- class Collection::Post < Collection::Item
163
- use_api LWS::Resource.api
173
+ # = The feed collection metadata class
174
+ #
175
+ # This represents the metadata of a feed collection.
176
+ # class Collection::FeedMetadata < Collection::Metadata
177
+ # # @!attribute feed_url
178
+ # # @return [String, nil] the URL of the feed
179
+ # property :feed_url
180
+ #
181
+ # # @!attribute refresh_interval
182
+ # # @return [Integer] the interval used to refresh feed (in seconds)
183
+ # property :refresh_interval
184
+ # end
164
185
 
165
- # @!attribute author
166
- # @return [String] the author of the post
167
- attribute :author
168
186
 
169
- # @!attribute avatar
170
- # @return [Hash] the URL information of the avatar image of the post
171
- attribute :avatar
187
+ # = The Vimeo collection metadata class
188
+ #
189
+ # This represents the metadata of a Vimeo collection.
190
+ class Collection::VimeoMetadata < Collection::Metadata
191
+ # @!attribute video_url
192
+ # @return [String, nil] the actual URL of the Vimeo video
193
+ property :video_url
194
+ end
172
195
 
173
- # @!attribute category
174
- # @return [String] the category of the post
175
- attribute :category
196
+ # = The weather location collection metadata class
197
+ #
198
+ # This represents the metadata of a weather location collection.
199
+ class Collection::WeatherLocationMetadata < Collection::Metadata
200
+ # @!attribute city
201
+ # @return [String, nil] the city of the weather location
202
+ property :city
176
203
 
177
- # @!attribute comments
178
- # @return [String] the comments of the post
179
- attribute :comments
204
+ # @!attribute country
205
+ # @return [String, nil] the country of the weather location
206
+ property :country
180
207
 
181
208
  # @!attribute description
182
- # @return [String] the description of the post
183
- attribute :description
209
+ # @return [String, nil] the description of the weather location
210
+ property :description
184
211
 
185
- # @!attribute description
186
- # @return [String] the description of the post
187
- attribute :enclosures
212
+ # @!attribute feed_url
213
+ # @return [String, nil] the URL of the feed of the weather location
214
+ property :feed_url
188
215
 
189
- # @!attribute guid
190
- # @return [String] the GUID of the post
191
- attribute :guid
216
+ # @!attribute forecast_interval
217
+ # @return ["daily", "hourly"] whether the forecast is for a specific day
218
+ # or hour
219
+ property :forecast_interval
192
220
 
193
- # @!attribute handle
194
- # @return [String] the handle of the post
195
- attribute :handle
221
+ # @!attribute kind
222
+ # @return ["open_weather_map", "unknown"] the kind of the weather location
223
+ property :kind
196
224
 
197
- # @!attribute link
198
- # @return [String] the link of the post
199
- attribute :link
225
+ # @!attribute lat
226
+ # @return [Float, nil] the latitude of the weather location
227
+ property :lat
200
228
 
201
229
  # @!attribute link
202
- # @return [String] the timestamp of the modification date of the post
203
- attribute :modification_date
230
+ # @return [String] the link of the weather location
231
+ property :link
204
232
 
205
- # @!attribute order_priority
206
- # @return [Integer] the order priority of the of the post (ascending;
207
- # 0 is lowers)
208
- attribute :order_priority
233
+ # @!attribute long
234
+ # @return [Float, nil] the longitude of the weather location
235
+ property :long
209
236
 
210
- # @!attribute link
211
- # @return [String] the timestamp of the publication date of the post
212
- attribute :publication_date
237
+ # @!attribute name
238
+ # @return [String] the name of the forecast location
239
+ property :name
213
240
 
214
- # @!attribute source_url
215
- # @return [String] the source URL of the post
216
- attribute :source_url
241
+ # @!attribute refresh_interval
242
+ # @return [Integer] the interval used to refresh the weather location
243
+ # (in seconds)
244
+ property :refresh_interval
217
245
 
218
- # @!attribute summary
219
- # @return [String] the summary of the post
220
- attribute :summary
246
+ # @!attribute region
247
+ # @return [String, nil] the region of the weather location
248
+ property :region
221
249
 
222
250
  # @!attribute title
223
- # @return [String] the title of the post
224
- attribute :title
225
- end
226
-
227
- # = The collection feed class
228
- class Collection::Feed < Collection::Item
229
- use_api LWS::Resource.api
230
- uri "collections/:collection_id/feeds(/:id)"
231
-
232
- # @!attribute feed_url
233
- # @return [String] the URL of the feed
234
- attribute :feed_url
235
-
236
- # @!attribute post_ids
237
- # @return [Collection::Post] the IDs of the posts included in the feed
238
- attribute :post_ids
239
-
240
- # @!attribute posts
241
- # @return [Collection::Post] the posts included in the feed
242
- has_many :posts,
243
- class_name: "LWS::Resource::Collection::Feed::Post",
244
- uri: "collections/:collection_id/feeds/:feed_id/posts(/:id)"
251
+ # @return [String] the title of the weather location
252
+ property :title
245
253
 
246
- # @!attribute refresh_interval
247
- # @return [Integer] the interval used to refresh the feed (in seconds)
248
- attribute :refresh_interval
254
+ # @attribute token
255
+ # @return [String, nil] the token used to refresh the forecasts
256
+ property :token
249
257
  end
250
258
 
251
- # = The collection feed post class
252
- class Collection::Feed::Post < Collection::Post
253
- uri "collections/:collection_id/feeds/:feed_id/posts(/:id)"
254
-
255
- # @!attribute feed
256
- # @return [Collection::Feed] the collection feed that the collection feed
257
- # post is a part of
258
- belongs_to :feed,
259
- class_name: "LWS::Resource::Collection::Feed",
260
- uri: "collections/:collection_id/feeds(/:id)"
261
-
262
- # @!attribute feed_id
263
- # @return [Integer] the ID of the collection feed that the collection
264
- # feed is a post is part of
265
- attribute :feed_id
259
+ # = The YouTube collection metadata class
260
+ #
261
+ # This represents the metadata of a YouTube collection.
262
+ class Collection::YouTubeMetadata < Collection::Metadata
263
+ # @!attribute video_url
264
+ # @return [String, nil] the actual URL of the YouTube video
265
+ property :video_url
266
266
  end
267
267
 
268
- # = The collection image class
269
- class Collection::Image < Collection::Item
268
+ # = The collection item class
269
+ #
270
+ # An item has associated metadata (see {#metadata}) that is specific to the
271
+ # collection item kind.
272
+ class Collection::Item < LWS::Generic::Model
270
273
  use_api LWS::Resource.api
271
- uri "collections/:collection_id/images(/:id)"
272
274
 
273
- # @!attribute data_url
274
- # @return [String] the URL of the image
275
- attribute :data_url
276
-
277
- # @!attribute thumbnail_url
278
- # @return [String] the URL of the thumbnail of the image
279
- attribute :thumbnail_url
280
- end
275
+ # @!attribute collection
276
+ # @return [Collection] the collection that the collection item is a
277
+ # part of
278
+ belongs_to :collection
281
279
 
282
- # = The collection video class
283
- class Collection::Video < Collection::Item
284
- use_api LWS::Resource.api
285
- uri "collections/:collection_id/videos(/:id)"
280
+ # @!attribute collection_id
281
+ # @return [Integer] the ID of the collection that the collection item is a
282
+ # part of
283
+ attribute :collection_id
286
284
 
287
285
  # @!attribute data_url
288
- # @return [String] the URL of the video
286
+ # @return [String, nil] the URL of the item (if it has associated data)
289
287
  attribute :data_url
290
288
 
291
- # @!attribute thumbnail_url
292
- # @return [String] the URL of the thumbnail of the video
293
- attribute :thumbnail_url
294
- end
289
+ # @!attribute kind
290
+ # @note
291
+ # This library only supports a subset of the available collection/item
292
+ # kinds.
293
+ # @return ["forecast", "image", "pdf", "powerpoint", "video", "vimeo",
294
+ # "youtube"] the name of the class/kind of the collection item
295
+ attribute :kind
295
296
 
296
- # = The collection Vimeo class
297
- class Collection::Vimeo < Collection::Item
298
- use_api LWS::Resource.api
299
- uri "collections/:collection_id/vimeos(/:id)"
297
+ # @!attribute name
298
+ # @return [String] the name of the collection item
299
+ attribute :name
300
300
 
301
- # @!attribute data_url
302
- # @return [String] the URL of the vimeo
303
- attribute :data_url
301
+ # @!attribute position
302
+ # @return [Integer] the position of the item within the collection
303
+ attribute :position
304
304
 
305
305
  # @!attribute thumbnail_url
306
- # @return [String] the URL of the thumbnail of the vimeo
306
+ # @return [String, nil] the URL of the thumbnail of the item (if it has
307
+ # associated data)
307
308
  attribute :thumbnail_url
308
- end
309
-
310
- # = The collection YouTube class
311
- class Collection::YouTube < Collection::Item
312
- use_api LWS::Resource.api
313
- uri "collections/:collection_id/youtubes(/:id)"
314
-
315
- # @!attribute data_url
316
- # @return [String] the URL of the youtube
317
- attribute :data_url
318
309
 
319
- # @!attribute thumbnail_url
320
- # @return [String] the URL of the thumbnail of the youtube
321
- attribute :thumbnail_url
310
+ # Returns the metadata of the collection item specific to its kind.
311
+ #
312
+ # @return [Collection::Item::Metadata] the kind-specific metadata of the
313
+ # collection item
314
+ def metadata
315
+ attrs = attributes["metadata"]&.symbolize_keys || {}
316
+ case kind
317
+ # when "config"
318
+ # ConfigMetadata.new(json: attributes["json"])
319
+ when "forecast"
320
+ attrs =
321
+ attributes
322
+ .slice("cloudiness", "code", "date", "observation",
323
+ "precipitation", "temperature", "uv_index", "wind")
324
+ .symbolize_keys
325
+ ForecastMetadata.new(attrs)
326
+ when "image"
327
+ ImageMetadata.new(attrs)
328
+ when "pdf"
329
+ PDFMetadata.new(attrs)
330
+ # when "post"
331
+ # attrs =
332
+ # attributes.slice("author", "category", "comments", "description",
333
+ # "guid", "handle", "link", "modification_data", "order_priority",
334
+ # "publication_date", "source_url", "summary", "title")
335
+ # PostMetadata.new(attrs)
336
+ when "powerpoint"
337
+ PowerPointMetadata.new(attrs)
338
+ when "video"
339
+ VideoMetadata.new(attrs)
340
+ when "vimeo"
341
+ VimeoMetadata.new(attrs)
342
+ when "youtube"
343
+ YouTubeMetadata.new(attrs)
344
+ else
345
+ Metadata.new
346
+ end
347
+ end
322
348
  end
323
349
 
324
- # = The collection weather location class
325
- class Collection::WeatherLocation < Collection::Item
326
- use_api LWS::Resource.api
327
- uri "collections/:collection_id/weather_locations(/:id)"
328
-
329
- # @!attribute city
330
- # @return [String] the city of the weather location
331
- attribute :city
332
-
333
- # @!attribute country
334
- # @return [String] the country of the weather location
335
- attribute :country
336
-
337
- # @!attribute description
338
- # @return [String] the description of the weather location
339
- attribute :description
340
-
341
- # @!attribute feed_url
342
- # @return [String] the URL of the feed of the weather location
343
- attribute :feed_url
344
-
345
- # @!attribute forecast_ids
346
- # @return [Forecast] the IDs of the forecasts for the weather location
347
- attribute :forecast_ids
348
-
349
- # @!attribute forecasts
350
- # @return [Forecast] the forecasts for the weather location
351
- has_many :forecasts,
352
- class_name: "LWS::Resource::Collection::WeatherLocation::Forecast",
353
- uri: "collections/:collection_id/weather_locations/:weather_location_id/forecasts(/:id)"
354
-
355
- # @!attribute kind
356
- # @return ["unknown", "yahoo"] the kind of the weather location
357
- attribute :kind
358
-
359
- # @!attribute lat
360
- # @return [Float, nil] the latitude of the weather location
361
- attribute :lat
362
-
363
- # @!attribute link
364
- # @return [String] the link of the weather location
365
- attribute :link
366
-
367
- # @!attribute long
368
- # @return [Float, nil] the longitude of the weather location
369
- attribute :long
370
-
371
- # @!attribute refresh_interval
372
- # @return [Integer] the interval used to refresh the weather location
373
- # (in seconds)
374
- attribute :refresh_interval
350
+ # = The collection item metadata class.
351
+ #
352
+ # This represents some kind of metadata of a collection item that is specific
353
+ # to its collection kind.
354
+ class Collection::Item::Metadata < Metadata
355
+ end
375
356
 
376
- # @!attribute region
377
- # @return [String] the region of the weather location
378
- attribute :region
357
+ # = The config collection item metadata class.
358
+ #
359
+ # This represents the metadata of a config item, part of a config collection.
360
+ # class Collection::Item::ConfigMetadata < Metadata
361
+ # # @!attribute json
362
+ # # @return [String] the JSON data of the config
363
+ # property :json
364
+ # end
379
365
 
380
- # @!attribute title
381
- # @return [String] the title of the weather location
382
- attribute :title
383
- end
384
366
 
385
- # = The collection weather location forecast class
386
- class Collection::WeatherLocation::Forecast < Collection::Item
387
- use_api LWS::Resource.api
388
- uri "collections/:collection_id/weather_locations/:weather_location_id/forecasts(/:id)"
367
+ # = The forecast collection item metadata class
368
+ #
369
+ # This represents the metadata of a forecast item, part of a weather location
370
+ # collection.
371
+ class Collection::Item::ForecastMetadata < Collection::Item::Metadata
372
+ # @!attribute cloudiness
373
+ # @return [Integer] the percentage of cloud cover for the weather
374
+ # location forecast
375
+ property :cloudiness
389
376
 
390
377
  # @!attribute code
391
378
  # @return [Integer] the code for the weather location forecast
392
- attribute :code
379
+ property :code
393
380
 
394
381
  # @!attribute date
395
382
  # @return [Integer] the timestamp of the date of the weather location forecast
396
- attribute :date
383
+ property :date
397
384
 
398
385
  # @!attribute description
399
- # @return [Integer] the description of the weather location forecast
400
- attribute :description
386
+ # @return [String] the (English) description of the weather location forecast
387
+ property :description
401
388
 
402
389
  # @!attribute observation
403
390
  # @return [Boolean] whether the weather location forecast is a
404
391
  # current observation
405
- attribute :observation
392
+ property :observation
393
+
394
+ # @!attribute precipitation
395
+ # The precipitation hash contains the propability on precipitation (key
396
+ # "probability") between 0 and 1, and the forecasted amount of rain
397
+ # (key "rain") and/or snow (key "snow") in millimeter.
398
+ # @return [Hash{String=>Float, nil}] the precipitation information of
399
+ # the weather location forecast
400
+ property :precipitation
406
401
 
407
402
  # @!attribute temperature
408
403
  # The temperature hash contains either the current temperature (key
409
404
  # "now") if the forecast is an observation or the temperature range
410
405
  # (keys "low" and "high") if it is not.
411
- # @return [Hash{String=>Float}] the temperature information of the
406
+ #
407
+ # For hourly forecasts, the value of either key "min" or "max" can have
408
+ # the value +true+ based on whether the forecasted temperature for this
409
+ # hour is the expected mininum or maximum temperature for the day.
410
+ # @return [Hash{String=>Float, Boolean, nil}] the temperature information of the
412
411
  # weather location forecast
413
- attribute :temperature
414
-
415
- # @!attribute weather_location
416
- # @return [Collection::WeatherLocation] the collection weather location
417
- # that the collection weather location post is a part of
418
- belongs_to :weather_location,
419
- class_name: "LWS::Resource::Collection::WeatherLocation",
420
- uri: "collections/:collection_id/weather_location(/:id)"
412
+ property :temperature
421
413
 
422
- # @!attribute weather_location_id
423
- # @return [Integer] the ID of the collection weather location that the
424
- # collection weather location is a post is part of
425
- attribute :weather_location_id
414
+ # @!attribute uv_index
415
+ # @return [Float] the maximum UV index of the weather location forecast
416
+ property :uv_index
426
417
 
427
418
  # @!attribute wind
428
419
  # The wind hash contains the wind chill temperature (key "chill"),
429
420
  # direction in degrees (key "direction"), and wind speed (key "speed").
430
- # @return [Hash{String=>Float}] the temperature information of the
421
+ # @return [Hash{String=>Float, nil}] the temperature information of the
431
422
  # weather location forecast
432
- attribute :wind
423
+ property :wind
424
+ end
425
+
426
+ # = The image collection item metadata class
427
+ #
428
+ # This represents the metadata of an image item, part of an image collection.
429
+ class Collection::Item::ImageMetadata < Collection::Item::Metadata
430
+ # @!attribute byte_size
431
+ # @return [Integer] the size of the image (in bytes)
432
+ property :byte_size
433
+
434
+ # @!attribute content_type
435
+ # @return [String] the MIME content type of the image
436
+ property :content_type
437
+
438
+ # @!attribute filename
439
+ # @return [String] the filename of the image
440
+ property :filename
441
+
442
+ # @!attribute height
443
+ # @return [Integer] the height of the image (in pixels)
444
+ property :height
445
+
446
+ # @!attribute width
447
+ # @return [Integer] the width of the image (in pixels)
448
+ property :width
449
+ end
450
+
451
+ # = The PDF collection item metadata class
452
+ #
453
+ # This represents the metadata of a PDF item, part of a PDF collection.
454
+ class Collection::Item::PDFMetadata < Collection::Item::ImageMetadata
455
+ end
456
+
457
+ # = The post collection item metadata class
458
+ #
459
+ # This represents the metadata of a post item, part of a feed collection.
460
+ # class Collection::Item::PostMetadata < Collection::Item::Metadata
461
+ # # @!attribute author
462
+ # # @return [String] the author of the post
463
+ # property :author
464
+ #
465
+ # # @!attribute category
466
+ # # @return [String] the category of the post
467
+ # property :category
468
+ #
469
+ # # @!attribute comments
470
+ # # @return [String] the comments of the post
471
+ # property :comments
472
+ #
473
+ # # @!attribute description
474
+ # # @return [String] the description of the post
475
+ # property :description
476
+ #
477
+ # # @!attribute description
478
+ # # @return [Array<ImageMetadata>] the description of the post
479
+ # property :enclosures
480
+ #
481
+ # # @!attribute guid
482
+ # # @return [String] the GUID of the post
483
+ # property :guid
484
+ #
485
+ # # @!attribute handle
486
+ # # @return [String] the handle of the post
487
+ # property :handle
488
+ #
489
+ # # @!attribute link
490
+ # # @return [String] the link of the post
491
+ # property :link
492
+ #
493
+ # # @!attribute link
494
+ # # @return [String] the timestamp of the modification date of the post
495
+ # property :modification_date
496
+ #
497
+ # # @!attribute order_priority
498
+ # # @return [Integer] the order priority of the of the post (ascending;
499
+ # # 0 is lowers)
500
+ # property :order_priority
501
+ #
502
+ # # @!attribute link
503
+ # # @return [String] the timestamp of the publication date of the post
504
+ # property :publication_date
505
+ #
506
+ # # @!attribute source_url
507
+ # # @return [String] the source URL of the post
508
+ # property :source_url
509
+ #
510
+ # # @!attribute summary
511
+ # # @return [String] the summary of the post
512
+ # property :summary
513
+ #
514
+ # # @!attribute title
515
+ # # @return [String] the title of the post
516
+ # property :title
517
+ # end
518
+
519
+
520
+ class Collection::Item::VideoMetadata < Collection::Item::Metadata
521
+ # @!attribute byte_size
522
+ # @return [Integer] the size of the video (in bytes)
523
+ property :byte_size
524
+
525
+ # @!attribute content_type
526
+ # @return [String] the MIME content type of the video
527
+ property :content_type
528
+
529
+ # @!attribute display_aspect_ratio
530
+ # @return [(Integer, Integer)] the aspect ratio of the video
531
+ property :display_aspect_ratio
532
+
533
+ # @!attribute duration
534
+ # @return [Integer] the duration of the video
535
+ property :duration
536
+
537
+ # @!attribute filename
538
+ # @return [String] the filename of the video
539
+ property :filename
540
+
541
+ # @!attribute height
542
+ # @return [Float] the height of the video (in pixels)
543
+ property :height
544
+
545
+ # @!attribute width
546
+ # @return [Float] the width of the video (in pixels)
547
+ property :width
548
+ end
549
+
550
+ # = The PowerPoint collection item metadata class
551
+ #
552
+ # This represents the metadata of a PowerPoint item, part of a PowerPoint
553
+ # collection.
554
+ class Collection::Item::PowerPointMetadata < Collection::Item::VideoMetadata
555
+ end
556
+
557
+ # = The Vimeo collection item metadata class
558
+ #
559
+ # This represents the metadata of a Vimeo item, part of a Vimeo collection.
560
+ class Collection::Item::VimeoMetadata < Collection::Item::VideoMetadata
561
+ end
562
+
563
+ # = The YouTube collection item metadata class
564
+ #
565
+ # This represents the metadata of a YouTube item, part of a YouTube
566
+ # collection.
567
+ class Collection::Item::YouTubeMetadata < Collection::Item::VideoMetadata
433
568
  end
434
569
 
435
570
  # = The folder class
data/lib/lws/errors.rb CHANGED
@@ -16,17 +16,23 @@ module LWS
16
16
  #
17
17
  # This module contains the exceptions that can be thrown.
18
18
  module Errors
19
+ # Parent class of all LWS errors.
20
+ class Error < StandardError; end
21
+
19
22
  # Exception thrown if there are issues with the LWS configuration.
20
- class ConfigError < StandardError; end
23
+ class ConfigError < Error; end
21
24
 
22
25
  # Exception thrown if an invalid response is returned by LWS.
23
- class InvalidResponse < StandardError; end
26
+ class InvalidResponse < Error; end
24
27
 
25
28
  # Exception thrown if the resource could not be found in LWS.
26
- class ResourceNotFound < StandardError; end
29
+ class ResourceNotFound < Error; end
30
+
31
+ # Exception thrown if the LWS server fails.
32
+ class ServerError < Error; end
27
33
 
28
34
  # Exception thrown if there is an issue with the stubbing setup.
29
- class StubError < StandardError; end
35
+ class StubError < Error; end
30
36
  end
31
37
 
32
38
  end
@@ -53,7 +53,7 @@ module LWS
53
53
  def on_complete(env)
54
54
  env[:body] = case env[:status]
55
55
  when 204, 304
56
- parse('{}')
56
+ { data: {}, metadata: nil, errors: nil }
57
57
  else
58
58
  parse(env[:body])
59
59
  end
@@ -0,0 +1,37 @@
1
+ #
2
+ # Copyright © 2016–2021 LeftClick Web Services B.V.
3
+ #
4
+ # This software is property of LeftClick Web Services B.V. and cannot be
5
+ # redistributed and/or modified without permission. The software or any
6
+ # of its parts cannot be used for any other purposes than the LeftClick
7
+ # services and only during a valid license subscription. For more
8
+ # information, please contact LeftClick Web Services B.V. at:
9
+ # Schootense Dreef 20A, 5708 HZ Helmond, The Netherlands,
10
+ # info@leftclick.eu, +3185-4444-004.
11
+
12
+
13
+ module LWS
14
+
15
+ module Middleware
16
+
17
+ # @private
18
+ # @!visibility private
19
+ class RaiseServerError <
20
+ # Use `Faraday::Response::Middleware` if it exists (Faraday < 2.0)
21
+ defined?(Faraday::Response::Middleware) ? Faraday::Response::Middleware : Faraday::Middleware
22
+
23
+ def on_complete(env)
24
+ case env[:status]
25
+ when 500...600
26
+ raise LWS::Errors::ServerError, env[:body]
27
+ when nil
28
+ raise LWS::Errors::ServerError, "response status missing"
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -23,6 +23,7 @@ require "lws/middleware/caching"
23
23
  require "lws/middleware/http_logger"
24
24
  require "lws/middleware/json_logger"
25
25
  require "lws/middleware/json_parser"
26
+ require "lws/middleware/raise_server_error"
26
27
  require "lws/middleware/request_headers"
27
28
 
28
29
  # Set up Faraday 1.0/2.0 portability using middleware class aliases.
@@ -50,5 +51,12 @@ module LWS
50
51
  # available for Faraday ≥ 2.0
51
52
  Caching
52
53
  end
54
+
55
+ Retry =
56
+ if defined? Faraday::Request::Retry
57
+ Faraday::Request::Retry
58
+ else
59
+ Faraday::Retry::Middleware
60
+ end
53
61
  end
54
62
  end
data/lib/lws/version.rb CHANGED
@@ -14,6 +14,6 @@ module LWS
14
14
 
15
15
  # The LWS library version.
16
16
  # @note The major and minor version parts match the LWS API version!
17
- VERSION = "10.0.0".freeze
17
+ VERSION = "11.0.0".freeze
18
18
 
19
19
  end
data/lib/lws.rb CHANGED
@@ -18,6 +18,7 @@ else
18
18
  # For Faraday ≥ 2.0 load these middleware gems separately.
19
19
  require "faraday/follow_redirects"
20
20
  require "faraday/net_http_persistent"
21
+ require "faraday/retry"
21
22
  end
22
23
  require "hashie"
23
24
  require "multi_json"
@@ -138,6 +139,11 @@ module LWS
138
139
  # Response
139
140
  c.use Middleware::JSONLogger, config.logger if config.json_debug
140
141
  c.use Middleware::JSONParser
142
+ c.use Middleware::RaiseServerError
143
+ c.use Middleware::Retry, exceptions: Middleware::Retry::DEFAULT_EXCEPTIONS +
144
+ [Errno::EALREADY, Faraday::ConnectionFailed],
145
+ interval: 0.2,
146
+ retry_statuses: [502, 503, 504]
141
147
  c.use Middleware::FollowRedirects, limit: 3
142
148
  if config.http_debug
143
149
  c.use Middleware::HTTPLogger, config.logger, config.http_debug_headers
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lws
3
3
  version: !ruby/object:Gem::Version
4
- version: 10.0.0
4
+ version: 11.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - LeftClick B.V.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-10-10 00:00:00.000000000 Z
11
+ date: 2025-09-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -64,6 +64,26 @@ dependencies:
64
64
  - - "<"
65
65
  - !ruby/object:Gem::Version
66
66
  version: '2.0'
67
+ - !ruby/object:Gem::Dependency
68
+ name: net-http-persistent
69
+ requirement: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: '2.9'
74
+ - - "<"
75
+ - !ruby/object:Gem::Version
76
+ version: '5.0'
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '2.9'
84
+ - - "<"
85
+ - !ruby/object:Gem::Version
86
+ version: '5.0'
67
87
  - !ruby/object:Gem::Dependency
68
88
  name: hashie
69
89
  requirement: !ruby/object:Gem::Requirement
@@ -182,6 +202,7 @@ files:
182
202
  - lib/lws/middleware/http_logger.rb
183
203
  - lib/lws/middleware/json_logger.rb
184
204
  - lib/lws/middleware/json_parser.rb
205
+ - lib/lws/middleware/raise_server_error.rb
185
206
  - lib/lws/middleware/request_headers.rb
186
207
  - lib/lws/stubbing.rb
187
208
  - lib/lws/version.rb