seam 2.140.0 → 2.141.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: 564fdfd341da5fc43c859ba3a1bb7d013b40845ffbab7e0e05f917493b974821
4
- data.tar.gz: a9ce5bded784a3153d98b85d6fcaaa1625837f84e9078c94a6c372e9a4a2eb24
3
+ metadata.gz: 67761c76f072fe523b56a8ee78b3112bcccd5c2da40cdd6a38c623e251a66861
4
+ data.tar.gz: 17eb707e5799d5b97c05d18abb5ce0224411a9cb5f06d00166a791de0e342c66
5
5
  SHA512:
6
- metadata.gz: 1cbe2df337d9004d747493a81330ccceda4caa1476e38d0907670b9f47d16bd4e5036a2745c958ca203ff0154e773ef91339769881da525a30ef2839f4d93761
7
- data.tar.gz: 0d69f48f2499b5f2275e44ddce95be1ffa50a417e8430374197f6a976fef7691facf1fdf80f247a8dfe0f166f2a32a966b79e74c7c851252e3df5fb502e46332
6
+ metadata.gz: dda63b3fe99166377d432246a928f10da2f337cd8633da0df34055efb453afcffbdda6392b3ad94d4951ed12badf293dfb0bb94f5e2dd16dd8f36ef0ffe58f78
7
+ data.tar.gz: 03233cc7ee5e3136c92e3274410539c0642e69352538797198e2a2dfaebfd9d3187a6fa1e15cfbd744b36c3c8ab12e490631f6513020fd8298e295d5b3fbce34
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- seam (2.140.0)
4
+ seam (2.141.0)
5
5
  faraday (~> 2.7)
6
6
  faraday-retry (~> 2.2)
7
7
  svix (~> 1.30)
data/README.md CHANGED
@@ -27,6 +27,7 @@ accurate and fully typed.
27
27
  - [API Key](#api-key)
28
28
  - [Personal Access Token](#personal-access-token)
29
29
  - [Action Attempts](#action-attempts)
30
+ - [Setting a value to null](#setting-a-value-to-null)
30
31
  - [Pagination](#pagination)
31
32
  - [Manually fetch pages with the next_page_cursor](#manually-fetch-pages-with-the-next_page_cursor)
32
33
  - [Resume pagination](#resume-pagination)
@@ -43,6 +44,7 @@ accurate and fully typed.
43
44
  - [Configuring the Faraday Client](#configuring-the-faraday-client)
44
45
  - [Using the Faraday Client](#using-the-faraday-client)
45
46
  - [Overriding the Client](#overriding-the-client)
47
+ - [Serializing URL search params](#serializing-url-search-params)
46
48
  - [Development and Testing](#development-and-testing)
47
49
  - [Quickstart](#quickstart)
48
50
  - [Source code](#source-code)
@@ -226,6 +228,35 @@ rescue Seam::ActionAttemptTimeoutError
226
228
  end
227
229
  ```
228
230
 
231
+ ### Setting a value to null
232
+
233
+ The Seam API distinguishes three states for an updatable parameter:
234
+ omitted (leave the stored value unchanged), null (unset the stored value),
235
+ and a value (set it).
236
+
237
+ Ruby's `nil` means omitted.
238
+ The SDK removes `nil` parameters from the request entirely,
239
+ so passing `nil` never unsets a value.
240
+ To unset a value, pass the `Seam::NULL` sentinel,
241
+ which the SDK sends as JSON `null` in request bodies
242
+ and as an empty value in query strings:
243
+
244
+ ```ruby
245
+ require "seam"
246
+
247
+ seam = Seam.new
248
+
249
+ # Leaves ends_at unchanged.
250
+ seam.access_grants.update(access_grant_id: access_grant_id, ends_at: nil)
251
+
252
+ # Unsets ends_at so the grant no longer expires.
253
+ seam.access_grants.update(access_grant_id: access_grant_id, ends_at: Seam::NULL)
254
+ ```
255
+
256
+ Only pass `Seam::NULL` for parameters the API documents as nullable.
257
+ Generated methods document nullable parameters
258
+ with `Seam::Null` in their `@param` types, e.g. `[String, Seam::Null, nil]`.
259
+
229
260
  ### Pagination
230
261
 
231
262
  Some Seam API endpoints that return lists of resources support pagination.
@@ -489,6 +520,61 @@ devices = seam.client.get("/devices/list").body["devices"]
489
520
  A Faraday compatible client may be provided to create a `Seam` instance.
490
521
  This API is used internally and is not directly supported.
491
522
 
523
+ #### Serializing URL search params
524
+
525
+ The Seam API parses URL search params as complex types.
526
+ If you call it with your own HTTP client,
527
+ `Seam.serialize_url_search_params` is exported for that purpose.
528
+ The `_strict=true` parameter is added to any non-empty query
529
+ so the Seam API uses strict, schema-aware parsing.
530
+ A query with no serializable params remains empty.
531
+
532
+ ```ruby
533
+ require "net/http"
534
+ require "seam"
535
+
536
+ uri = URI("https://connect.getseam.com/devices/list")
537
+ uri.query = Seam.serialize_url_search_params({device_ids: ["device1", "device2"]})
538
+
539
+ Net::HTTP.get(uri, {"Authorization" => "Bearer your-api-key"})
540
+ ```
541
+
542
+ The serialization defines the name and value of each search param,
543
+ where every value is a string.
544
+ `Seam::UrlSearchParams` holds those pairs and renders the query string,
545
+ as [URLSearchParams] does for the [reference implementation]:
546
+
547
+ ```ruby
548
+ require "seam"
549
+
550
+ search_params = Seam::UrlSearchParams.new
551
+
552
+ Seam.update_url_search_params(search_params, {device_ids: ["device1", "device2"]})
553
+
554
+ search_params.to_a
555
+ # => [["device_ids", "device1"], ["device_ids", "device2"], ["_strict", "true"]]
556
+
557
+ search_params.to_s
558
+ # => "device_ids=device1&device_ids=device2&_strict=true"
559
+ ```
560
+
561
+ Pass either the query string or the pairs to your HTTP client.
562
+ A client may percent-encode a few characters differently
563
+ than `URLSearchParams` does,
564
+ which the Seam API reads as the same params either way.
565
+
566
+ A param set to `nil` is omitted,
567
+ while a param set to `Seam::NULL` is serialized to an empty value,
568
+ which the Seam API reads as null,
569
+ as described in [Setting a value to null](#setting-a-value-to-null).
570
+ A param that cannot be represented raises a `Seam::UnserializableParamError`.
571
+
572
+ The Seam API parses these params with the corresponding [parser].
573
+
574
+ [URLSearchParams]: https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams
575
+ [reference implementation]: https://github.com/seamapi/url-search-params-serializer
576
+ [parser]: https://github.com/seamapi/url-search-params-parser
577
+
492
578
  ## Development and Testing
493
579
 
494
580
  ### Quickstart
data/lib/seam/null.rb ADDED
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "singleton"
4
+
5
+ module Seam
6
+ # The type of the {Seam::NULL} sentinel.
7
+ class Null
8
+ include Singleton
9
+
10
+ def to_s
11
+ "NULL"
12
+ end
13
+
14
+ def inspect
15
+ "NULL"
16
+ end
17
+ end
18
+
19
+ # Sentinel for an explicit JSON null: +nil+ omits a parameter, +Seam::NULL+
20
+ # unsets its stored value. Only for parameters the API documents as
21
+ # nullable.
22
+ NULL = Null.instance
23
+ end
data/lib/seam/request.rb CHANGED
@@ -5,6 +5,7 @@ require "faraday/retry"
5
5
  require_relative "defaults"
6
6
  require_relative "version"
7
7
  require_relative "paginator"
8
+ require_relative "strict_url_search_params_serializer"
8
9
 
9
10
  module Seam
10
11
  module Http
@@ -16,7 +17,11 @@ module Seam
16
17
  default_options = {
17
18
  url: endpoint,
18
19
  headers: auth_headers.merge(default_headers),
19
- request: {timeout: timeout, open_timeout: timeout}
20
+ request: {
21
+ timeout: timeout,
22
+ open_timeout: timeout,
23
+ params_encoder: UrlSearchParamsEncoder
24
+ }
20
25
  }
21
26
 
22
27
  options = deep_merge(default_options, faraday_options)
@@ -33,6 +38,7 @@ module Seam
33
38
  faraday_retry_options = default_faraday_retry_options.merge(faraday_retry_options)
34
39
 
35
40
  Faraday.new(options) do |builder|
41
+ builder.use ReplaceNullMiddleware
36
42
  builder.request :json
37
43
  builder.use Seam::PaginationMiddleware
38
44
  builder.response :json
@@ -97,6 +103,14 @@ module Seam
97
103
  end
98
104
  end
99
105
 
106
+ class ReplaceNullMiddleware < Faraday::Middleware
107
+ def on_request(env)
108
+ return unless env.body.is_a?(Hash) || env.body.is_a?(Array)
109
+
110
+ env.body = Seam.replace_null(env.body)
111
+ end
112
+ end
113
+
100
114
  def self.deep_merge(hash1, hash2)
101
115
  result = hash1.dup
102
116
  hash2.each do |key, value|
@@ -111,5 +125,39 @@ module Seam
111
125
 
112
126
  private_class_method :deep_merge
113
127
  end
128
+
129
+ module UrlSearchParamsEncoder
130
+ # Pairs decoded from a query string already present in the request
131
+ # path, passed through {encode} verbatim rather than re-serialized.
132
+ Decoded = Struct.new(:values)
133
+
134
+ def self.encode(params)
135
+ search_params = Seam::UrlSearchParams.new
136
+ map_params = {}
137
+
138
+ params.each do |name, value|
139
+ if value.is_a?(Decoded)
140
+ value.values.each { |element| search_params.append(name, element) }
141
+ else
142
+ map_params[name] = value
143
+ end
144
+ end
145
+
146
+ return search_params.to_s if map_params.empty?
147
+
148
+ Seam.update_url_search_params(search_params, map_params)
149
+ search_params.to_s
150
+ end
151
+
152
+ # Called by Faraday when a request path carries its own query string.
153
+ def self.decode(query)
154
+ return {} if query.nil? || query.empty?
155
+
156
+ pairs = URI.decode_www_form(query.encode(Encoding::UTF_8))
157
+ pairs.each_with_object({}) do |(name, value), decoded|
158
+ (decoded[name] ||= Decoded.new([])).values << value
159
+ end
160
+ end
161
+ end
114
162
  end
115
163
  end
@@ -129,7 +129,7 @@ module Seam
129
129
  # @param customer_key [String, nil] Customer key for which you want to list access codes.
130
130
  # @param device_id [String, nil] ID of the device for which you want to list access codes. Specify `device_id`, `access_code_ids`, `access_method_id`, `access_grant_id`, or `access_grant_key`.
131
131
  # @param limit [Float, nil] Numerical limit on the number of access codes to return.
132
- # @param page_cursor [String, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
132
+ # @param page_cursor [String, Seam::Null, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
133
133
  # @param search [String, nil] String for which to search. Filters returned access codes to include all records that satisfy a partial match using `name`, `code` or `access_code_id`.
134
134
  # @param user_identifier_key [String, nil] Your user ID for the user by which to filter access codes.
135
135
  # @return [Seam::Resources::AccessCode] OK
@@ -53,7 +53,7 @@ module Seam
53
53
  # Returns a list of all [unmanaged access codes](https://docs.seam.co/low-level-apis/smart-locks/access-codes/migrating-existing-access-codes).
54
54
  # @param device_id [String] ID of the device for which you want to list unmanaged access codes.
55
55
  # @param limit [Float, nil] Numerical limit on the number of unmanaged access codes to return.
56
- # @param page_cursor [String, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
56
+ # @param page_cursor [String, Seam::Null, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
57
57
  # @param search [String, nil] String for which to search. Filters returned access codes to include all records that satisfy a partial match using `name`, `code` or `access_code_id`.
58
58
  # @param user_identifier_key [String, nil] Your user ID for the user by which to filter unmanaged access codes.
59
59
  # @return [Seam::Resources::UnmanagedAccessCode] OK
@@ -20,12 +20,12 @@ module Seam
20
20
  # @param acs_entrance_ids [Array<String>, nil] Set of IDs of the [entrances](https://docs.seam.co/api/acs/systems/list) to which access is being granted.
21
21
  # @param customization_profile_id [String, nil] ID of the customization profile to apply to the Access Grant and its access methods.
22
22
  # @param device_ids [Array<String>, nil] Set of IDs of the [devices](https://docs.seam.co/api/devices/list) to which access is being granted.
23
- # @param ends_at [String, nil] Date and time at which the validity of the new grant ends, in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. Must be a time in the future and after `starts_at`.
23
+ # @param ends_at [String, Seam::Null, nil] Date and time at which the validity of the new grant ends, in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. Must be a time in the future and after `starts_at`.
24
24
  # @param location [Hash, nil]
25
25
  # @deprecated location: Create a space first, then reference it using `space_ids`.
26
26
  # @param location_ids [Array<String>, nil]
27
27
  # @deprecated location_ids: Use `space_ids`.
28
- # @param name [String, nil] Name for the access grant.
28
+ # @param name [String, Seam::Null, nil] Name for the access grant.
29
29
  # @param reservation_key [String, nil] Reservation key for the access grant.
30
30
  # @param space_ids [Array<String>, nil] Set of IDs of existing spaces to which access is being granted.
31
31
  # @param space_keys [Array<String>, nil] Set of keys of existing spaces to which access is being granted.
@@ -79,7 +79,7 @@ module Seam
79
79
  # Gets an Access Grant.
80
80
  # @param access_code_id [String, nil] ID of the access code by which you want to filter the list of Access Grants.
81
81
  # @param access_grant_ids [Array<String>, nil] IDs of the access grants to retrieve.
82
- # @param access_grant_key [String, nil] Filter Access Grants by access_grant_key. Use null to filter for Access Grants without an access_grant_key.
82
+ # @param access_grant_key [String, Seam::Null, nil] Filter Access Grants by access_grant_key. Use null to filter for Access Grants without an access_grant_key.
83
83
  # @param acs_entrance_id [String, nil] ID of the entrance by which you want to filter the list of Access Grants.
84
84
  # @param acs_system_id [String, nil] ID of the access system by which you want to filter the list of Access Grants.
85
85
  # @param customer_key [String, nil] Customer key for which you want to list access grants.
@@ -87,7 +87,7 @@ module Seam
87
87
  # @param limit [Float, nil] Numerical limit on the number of access grants to return.
88
88
  # @param location_id [String, nil]
89
89
  # @deprecated location_id: Use `space_id`.
90
- # @param page_cursor [String, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
90
+ # @param page_cursor [String, Seam::Null, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
91
91
  # @param reservation_key [String, nil] Filter Access Grants by reservation_key.
92
92
  # @param space_id [String, nil] ID of the space by which you want to filter the list of Access Grants.
93
93
  # @param user_identity_id [String, nil] ID of user identity by which you want to filter the list of Access Grants.
@@ -111,8 +111,8 @@ module Seam
111
111
  # Updates an existing Access Grant's time window.
112
112
  # @param access_grant_id [String, nil] ID of the Access Grant to update. Provide either `access_grant_id` or `access_grant_key`.
113
113
  # @param access_grant_key [String, nil] Key of the Access Grant to update. Provide either `access_grant_id` or `access_grant_key`.
114
- # @param ends_at [Time, nil] Date and time at which the validity of the grant ends, in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. Must be a time in the future and after `starts_at`.
115
- # @param name [String, nil] Display name for the access grant.
114
+ # @param ends_at [Time, Seam::Null, nil] Date and time at which the validity of the grant ends, in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. Must be a time in the future and after `starts_at`.
115
+ # @param name [String, Seam::Null, nil] Display name for the access grant.
116
116
  # @param starts_at [Time, nil] Date and time at which the validity of the grant starts, in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format.
117
117
  # @return [nil] OK
118
118
  def update(access_grant_id: nil, access_grant_key: nil, ends_at: nil, name: nil, starts_at: nil)
@@ -21,7 +21,7 @@ module Seam
21
21
  # @param acs_entrance_id [String, nil] ID of the entrance by which you want to filter the list of unmanaged Access Grants.
22
22
  # @param acs_system_id [String, nil] ID of the access system by which you want to filter the list of unmanaged Access Grants.
23
23
  # @param limit [Float, nil] Numerical limit on the number of unmanaged access grants to return.
24
- # @param page_cursor [String, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
24
+ # @param page_cursor [String, Seam::Null, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
25
25
  # @param reservation_key [String, nil] Filter unmanaged Access Grants by reservation_key.
26
26
  # @param user_identity_id [String, nil] ID of user identity by which you want to filter the list of unmanaged Access Grants.
27
27
  # @return [Seam::Resources::UnmanagedAccessGrant] OK
@@ -80,7 +80,7 @@ module Seam
80
80
  # @param acs_entrance_id [String, nil] ID of the entrance for which you want to retrieve all access methods that grant access to it.
81
81
  # @param device_id [String, nil] ID of the device by which to filter the returned access methods. Must be combined with `access_grant_id`, `access_grant_key`, or `acs_entrance_id`.
82
82
  # @param limit [Integer, nil] Maximum number of records to return per page.
83
- # @param page_cursor [String, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
83
+ # @param page_cursor [String, Seam::Null, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
84
84
  # @param space_id [String, nil] ID of the space by which to filter the returned access methods. Must be combined with `access_grant_id`, `access_grant_key`, or `acs_entrance_id`.
85
85
  # @return [Seam::Resources::AccessMethod] OK
86
86
  def list(access_code_id: nil, access_grant_id: nil, access_grant_key: nil, acs_entrance_id: nil, device_id: nil, limit: nil, page_cursor: nil, space_id: nil)
@@ -65,7 +65,7 @@ module Seam
65
65
  # @param created_before [Time, nil] Date and time, in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format, before which events to return were created.
66
66
  # @param is_multi_phone_sync_credential [Boolean, nil] Indicates whether you want to retrieve only multi-phone sync credentials or non-multi-phone sync credentials.
67
67
  # @param limit [Float, nil] Number of credentials to return.
68
- # @param page_cursor [String, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
68
+ # @param page_cursor [String, Seam::Null, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
69
69
  # @param search [String, nil] String for which to search. Filters returned credentials to include all records that satisfy a partial match using `display_name`, `code`, `card_number`, `acs_user_id` or `acs_credential_id`.
70
70
  # @return [Seam::Resources::AcsCredential] OK
71
71
  def list(acs_user_id: nil, acs_system_id: nil, user_identity_id: nil, created_before: nil, is_multi_phone_sync_credential: nil, limit: nil, page_cursor: nil, search: nil)
@@ -41,7 +41,7 @@ module Seam
41
41
  # @param acs_system_ids [Array<String>, nil] IDs of the access systems for which you want to retrieve all encoders.
42
42
  # @param acs_encoder_ids [Array<String>, nil] IDs of the encoders that you want to retrieve.
43
43
  # @param limit [Float, nil] Number of encoders to return.
44
- # @param page_cursor [String, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
44
+ # @param page_cursor [String, Seam::Null, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
45
45
  # @return [Seam::Resources::AcsEncoder] OK
46
46
  def list(acs_system_id: nil, acs_system_ids: nil, acs_encoder_ids: nil, limit: nil, page_cursor: nil)
47
47
  res = @client.post("/acs/encoders/list", {acs_system_id: acs_system_id, acs_system_ids: acs_system_ids, acs_encoder_ids: acs_encoder_ids, limit: limit, page_cursor: page_cursor}.compact)
@@ -38,9 +38,9 @@ module Seam
38
38
  # @param connected_account_id [String, nil] ID of the connected account for which you want to retrieve all entrances.
39
39
  # @param customer_key [String, nil] Customer key for which you want to list entrances.
40
40
  # @param limit [Integer, nil] Maximum number of records to return per page.
41
- # @param location_id [String, nil]
41
+ # @param location_id [String, Seam::Null, nil]
42
42
  # @deprecated location_id: Use `space_id`.
43
- # @param page_cursor [String, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
43
+ # @param page_cursor [String, Seam::Null, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
44
44
  # @param search [String, nil] String for which to search. Filters returned entrances to include all records that satisfy a partial match using `display_name`.
45
45
  # @param space_id [String, nil] ID of the space for which you want to list entrances.
46
46
  # @return [Seam::Resources::AcsEntrance] OK
@@ -69,7 +69,7 @@ module Seam
69
69
  # @param acs_system_id [String, nil] ID of the `acs_system` for which you want to retrieve all access system users.
70
70
  # @param created_before [Time, nil] Timestamp by which to limit returned access system users. Returns users created before this timestamp.
71
71
  # @param limit [Integer, nil] Maximum number of records to return per page.
72
- # @param page_cursor [String, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
72
+ # @param page_cursor [String, Seam::Null, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
73
73
  # @param search [String, nil] String for which to search. Filters returned access system users to include all records that satisfy a partial match using `full_name`, `phone_number`, `email_address`, `acs_user_id`, `user_identity_id`, `user_identity_full_name` or `user_identity_phone_number`.
74
74
  # @param user_identity_email_address [String, nil] Email address of the user identity for which you want to retrieve all access system users.
75
75
  # @param user_identity_id [String, nil] ID of the user identity for which you want to retrieve all access system users.
@@ -153,7 +153,7 @@ module Seam
153
153
  end
154
154
 
155
155
  # Updates the properties of a specified [access system user](https://docs.seam.co/low-level-apis/access-systems/user-management).
156
- # @param access_schedule [Hash, nil] `starts_at` and `ends_at` timestamps for the access system user's access. If you specify an `access_schedule`, you may include both `starts_at` and `ends_at`. If you omit `starts_at`, it defaults to the current time. `ends_at` is optional and must be a time in the future and after `starts_at`.
156
+ # @param access_schedule [Hash, Seam::Null, nil] `starts_at` and `ends_at` timestamps for the access system user's access. If you specify an `access_schedule`, you may include both `starts_at` and `ends_at`. If you omit `starts_at`, it defaults to the current time. `ends_at` is optional and must be a time in the future and after `starts_at`.
157
157
  # @param acs_system_id [String, nil] ID of the access system that you want to update. You can only provide acs_system_id with user_identity_id.
158
158
  # @param acs_user_id [String, nil] ID of the access system user that you want to update. You can only provide acs_user_id or user_identity_id.
159
159
  # @param email [String, nil]
@@ -25,7 +25,7 @@ module Seam
25
25
  # @param action_attempt_ids [Array<String>, nil] IDs of the action attempts that you want to retrieve.
26
26
  # @param device_id [String, nil] ID of the device to filter action attempts by.
27
27
  # @param limit [Integer, nil] Maximum number of records to return per page.
28
- # @param page_cursor [String, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
28
+ # @param page_cursor [String, Seam::Null, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
29
29
  # @return [Seam::Resources::ActionAttempt] OK
30
30
  def list(action_attempt_ids: nil, device_id: nil, limit: nil, page_cursor: nil)
31
31
  res = @client.post("/action_attempts/list", {action_attempt_ids: action_attempt_ids, device_id: device_id, limit: limit, page_cursor: page_cursor}.compact)
@@ -58,7 +58,7 @@ module Seam
58
58
  # @param custom_metadata_has [Hash, nil] Custom metadata pairs by which you want to [filter Connect Webviews](https://docs.seam.co/core-concepts/connect-webviews/filtering-connect-webviews-by-custom-metadata). Returns Connect Webviews with `custom_metadata` that contains all of the provided key:value pairs.
59
59
  # @param customer_key [String, nil] Customer key for which you want to list connect webviews.
60
60
  # @param limit [Float, nil] Maximum number of records to return per page.
61
- # @param page_cursor [String, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
61
+ # @param page_cursor [String, Seam::Null, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
62
62
  # @param search [String, nil] String for which to search. Filters returned Connect Webviews to include all records that satisfy a partial match using `connect_webview_id`, `accepted_providers`, `custom_metadata`, or `customer_key`.
63
63
  # @param user_identifier_key [String, nil] Your user ID for the user by which you want to filter Connect Webviews.
64
64
  # @return [Seam::Resources::ConnectWebview] OK
@@ -43,7 +43,7 @@ module Seam
43
43
  # @param custom_metadata_has [Hash, nil] Custom metadata pairs by which you want to filter connected accounts. Returns connected accounts with `custom_metadata` that contains all of the provided key:value pairs.
44
44
  # @param customer_key [String, nil] Customer key by which you want to filter connected accounts.
45
45
  # @param limit [Integer, nil] Maximum number of records to return per page.
46
- # @param page_cursor [String, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
46
+ # @param page_cursor [String, Seam::Null, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
47
47
  # @param search [String, nil] String for which to search. Filters returned connected accounts to include all records that satisfy a partial match using `connected_account_id`, `account_type`, `customer_key`, `custom_metadata`, `user_identifier.username`, `user_identifier.email` or `user_identifier.phone`.
48
48
  # @param space_id [String, nil] ID of the space by which you want to filter connected accounts.
49
49
  # @param user_identifier_key [String, nil] Your user ID for the user by which you want to filter connected accounts.
@@ -44,10 +44,10 @@ module Seam
44
44
  # @param device_types [Array<String>, nil] Array of device types for which you want to list devices.
45
45
  # @param limit [Float, nil] Numerical limit on the number of devices to return.
46
46
  # @param manufacturer [String, nil] Manufacturer for which you want to list devices.
47
- # @param page_cursor [String, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
47
+ # @param page_cursor [String, Seam::Null, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
48
48
  # @param search [String, nil] String for which to search. Filters returned devices to include all records that satisfy a partial match using `device_id` (full or partial UUID prefix, minimum 4 characters), `connected_account_id`, `display_name`, `custom_metadata` or `location.location_name`.
49
49
  # @param space_id [String, nil] ID of the space for which you want to list devices.
50
- # @param unstable_location_id [String, nil]
50
+ # @param unstable_location_id [String, Seam::Null, nil]
51
51
  # @deprecated unstable_location_id: Use `space_id`.
52
52
  # @param user_identifier_key [String, nil] Your own internal user ID for the user for which you want to list devices.
53
53
  # @return [Seam::Resources::Device] OK
@@ -86,7 +86,7 @@ module Seam
86
86
  # @param backup_access_code_pool_enabled [Boolean, nil] Indicates whether the device's [backup access code pool](https://docs.seam.co/low-level-apis/smart-locks/access-codes/backup-access-codes) is enabled. Set to `false` to disable the pool: Seam stops refilling it and removes any backup codes that have not yet been pulled into active use.
87
87
  # @param custom_metadata [Hash, nil] Custom metadata that you want to associate with the device. Supports up to 50 JSON key:value pairs. [Adding custom metadata to a device](https://docs.seam.co/core-concepts/devices/adding-custom-metadata-to-a-device) enables you to store custom information, like customer details or internal IDs from your application. Then, you can [filter devices by the desired metadata](https://docs.seam.co/core-concepts/devices/filtering-devices-by-custom-metadata).
88
88
  # @param is_managed [Boolean, nil] Indicates whether the device is managed. To unmanage a device, set `is_managed` to `false`.
89
- # @param name [String, nil] Name for the device.
89
+ # @param name [String, Seam::Null, nil] Name for the device.
90
90
  # @param properties [Hash, nil]
91
91
  # @return [nil] OK
92
92
  def update(device_id:, backup_access_code_pool_enabled: nil, custom_metadata: nil, is_managed: nil, name: nil, properties: nil)
@@ -39,7 +39,7 @@ module Seam
39
39
  # @param device_types [Array<String>, nil] Array of device types for which you want to list devices.
40
40
  # @param limit [Float, nil] Numerical limit on the number of devices to return.
41
41
  # @param manufacturer [String, nil] Manufacturer for which you want to list devices.
42
- # @param page_cursor [String, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
42
+ # @param page_cursor [String, Seam::Null, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
43
43
  # @param search [String, nil] String for which to search. Filters returned devices to include all records that satisfy a partial match using `device_id` (full or partial UUID prefix, minimum 4 characters), `connected_account_id`, `display_name`, `custom_metadata` or `location.location_name`.
44
44
  # @return [Seam::Resources::UnmanagedDevice] OK
45
45
  def list(connect_webview_id: nil, connected_account_id: nil, connected_account_ids: nil, created_before: nil, customer_key: nil, device_ids: nil, device_type: nil, device_types: nil, limit: nil, manufacturer: nil, page_cursor: nil, search: nil)
@@ -95,7 +95,7 @@ module Seam
95
95
  # Returns a list of all spaces.
96
96
  # @param customer_key [String, nil] Customer key for which you want to list spaces.
97
97
  # @param limit [Float, nil] Maximum number of records to return per page.
98
- # @param page_cursor [String, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
98
+ # @param page_cursor [String, Seam::Null, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
99
99
  # @param search [String, nil] String for which to search. Filters returned spaces to include all records that satisfy a partial match using `name`, `space_key`, or `customer_key`.
100
100
  # @param space_key [String, nil] Filter spaces by space_key.
101
101
  # @return [Seam::Resources::Space] OK
@@ -60,7 +60,7 @@ module Seam
60
60
  # @param hvac_mode_setting [String, nil] Desired [HVAC mode](https://docs.seam.co/capability-guides/thermostats/understanding-thermostat-concepts/hvac-mode) setting, such as `heat`, `cool`, `heat_cool`, or `off`.
61
61
  # @param manual_override_allowed [Boolean, nil] Indicates whether a person at the thermostat or using the API can change the thermostat's settings.
62
62
  # @deprecated manual_override_allowed: Use 'thermostat_schedule.is_override_allowed'
63
- # @param name [String, nil] User-friendly name to identify the [climate preset](https://docs.seam.co/capability-guides/thermostats/creating-and-managing-climate-presets).
63
+ # @param name [String, Seam::Null, nil] User-friendly name to identify the [climate preset](https://docs.seam.co/capability-guides/thermostats/creating-and-managing-climate-presets).
64
64
  # @return [nil] OK
65
65
  def create_climate_preset(climate_preset_key:, device_id:, climate_preset_mode: nil, cooling_set_point_celsius: nil, cooling_set_point_fahrenheit: nil, ecobee_metadata: nil, fan_mode_setting: nil, heating_set_point_celsius: nil, heating_set_point_fahrenheit: nil, hvac_mode_setting: nil, manual_override_allowed: nil, name: nil)
66
66
  @client.post("/thermostats/create_climate_preset", {climate_preset_key: climate_preset_key, device_id: device_id, climate_preset_mode: climate_preset_mode, cooling_set_point_celsius: cooling_set_point_celsius, cooling_set_point_fahrenheit: cooling_set_point_fahrenheit, ecobee_metadata: ecobee_metadata, fan_mode_setting: fan_mode_setting, heating_set_point_celsius: heating_set_point_celsius, heating_set_point_fahrenheit: heating_set_point_fahrenheit, hvac_mode_setting: hvac_mode_setting, manual_override_allowed: manual_override_allowed, name: name}.compact)
@@ -173,10 +173,10 @@ module Seam
173
173
 
174
174
  # Sets a [temperature threshold](https://docs.seam.co/capability-guides/thermostats/setting-and-monitoring-temperature-thresholds) for a specified thermostat. Seam emits a `thermostat.temperature_threshold_exceeded` event and adds a warning on a thermostat if it reports a temperature outside the threshold range.
175
175
  # @param device_id [String] ID of the thermostat device for which you want to set a temperature threshold.
176
- # @param lower_limit_celsius [Float, nil] Lower temperature limit in in °C. Seam alerts you if the reported temperature is lower than this value. You can specify either `lower_limit` but not both.
177
- # @param lower_limit_fahrenheit [Float, nil] Lower temperature limit in in °F. Seam alerts you if the reported temperature is lower than this value. You can specify either `lower_limit` but not both.
178
- # @param upper_limit_celsius [Float, nil] Upper temperature limit in in °C. Seam alerts you if the reported temperature is higher than this value. You can specify either `upper_limit` but not both.
179
- # @param upper_limit_fahrenheit [Float, nil] Upper temperature limit in in °C. Seam alerts you if the reported temperature is higher than this value. You can specify either `upper_limit` but not both.
176
+ # @param lower_limit_celsius [Float, Seam::Null, nil] Lower temperature limit in in °C. Seam alerts you if the reported temperature is lower than this value. You can specify either `lower_limit` but not both.
177
+ # @param lower_limit_fahrenheit [Float, Seam::Null, nil] Lower temperature limit in in °F. Seam alerts you if the reported temperature is lower than this value. You can specify either `lower_limit` but not both.
178
+ # @param upper_limit_celsius [Float, Seam::Null, nil] Upper temperature limit in in °C. Seam alerts you if the reported temperature is higher than this value. You can specify either `upper_limit` but not both.
179
+ # @param upper_limit_fahrenheit [Float, Seam::Null, nil] Upper temperature limit in in °C. Seam alerts you if the reported temperature is higher than this value. You can specify either `upper_limit` but not both.
180
180
  # @return [nil] OK
181
181
  def set_temperature_threshold(device_id:, lower_limit_celsius: nil, lower_limit_fahrenheit: nil, upper_limit_celsius: nil, upper_limit_fahrenheit: nil)
182
182
  @client.patch("/thermostats/set_temperature_threshold", {device_id: device_id, lower_limit_celsius: lower_limit_celsius, lower_limit_fahrenheit: lower_limit_fahrenheit, upper_limit_celsius: upper_limit_celsius, upper_limit_fahrenheit: upper_limit_fahrenheit}.compact)
@@ -197,7 +197,7 @@ module Seam
197
197
  # @param hvac_mode_setting [String, nil] Desired [HVAC mode](https://docs.seam.co/capability-guides/thermostats/understanding-thermostat-concepts/hvac-mode) setting, such as `heat`, `cool`, `heat_cool`, or `off`.
198
198
  # @param manual_override_allowed [Boolean, nil] Indicates whether a person at the thermostat can change the thermostat's settings. See [Specifying Manual Override Permissions](https://docs.seam.co/capability-guides/thermostats/creating-and-managing-thermostat-schedules#specifying-manual-override-permissions).
199
199
  # @deprecated manual_override_allowed: Use 'thermostat_schedule.is_override_allowed'
200
- # @param name [String, nil] User-friendly name to identify the [climate preset](https://docs.seam.co/capability-guides/thermostats/creating-and-managing-climate-presets).
200
+ # @param name [String, Seam::Null, nil] User-friendly name to identify the [climate preset](https://docs.seam.co/capability-guides/thermostats/creating-and-managing-climate-presets).
201
201
  # @return [nil] OK
202
202
  def update_climate_preset(climate_preset_key:, device_id:, climate_preset_mode: nil, cooling_set_point_celsius: nil, cooling_set_point_fahrenheit: nil, ecobee_metadata: nil, fan_mode_setting: nil, heating_set_point_celsius: nil, heating_set_point_fahrenheit: nil, hvac_mode_setting: nil, manual_override_allowed: nil, name: nil)
203
203
  @client.patch("/thermostats/update_climate_preset", {climate_preset_key: climate_preset_key, device_id: device_id, climate_preset_mode: climate_preset_mode, cooling_set_point_celsius: cooling_set_point_celsius, cooling_set_point_fahrenheit: cooling_set_point_fahrenheit, ecobee_metadata: ecobee_metadata, fan_mode_setting: fan_mode_setting, heating_set_point_celsius: heating_set_point_celsius, heating_set_point_fahrenheit: heating_set_point_fahrenheit, hvac_mode_setting: hvac_mode_setting, manual_override_allowed: manual_override_allowed, name: name}.compact)
@@ -207,13 +207,13 @@ module Seam
207
207
 
208
208
  # Updates the thermostat weekly program for a thermostat device. To configure a weekly program, specify the ID of the daily program that you want to use for each day of the week. When you update a weekly program, the set of programs that you specify overwrites any previous weekly program for the thermostat.
209
209
  # @param device_id [String] ID of the thermostat device for which you want to update the weekly program.
210
- # @param friday_program_id [String, nil] ID of the thermostat daily program to run on Fridays.
211
- # @param monday_program_id [String, nil] ID of the thermostat daily program to run on Mondays.
212
- # @param saturday_program_id [String, nil] ID of the thermostat daily program to run on Saturdays.
213
- # @param sunday_program_id [String, nil] ID of the thermostat daily program to run on Sundays.
214
- # @param thursday_program_id [String, nil] ID of the thermostat daily program to run on Thursdays.
215
- # @param tuesday_program_id [String, nil] ID of the thermostat daily program to run on Tuesdays.
216
- # @param wednesday_program_id [String, nil] ID of the thermostat daily program to run on Wednesdays.
210
+ # @param friday_program_id [String, Seam::Null, nil] ID of the thermostat daily program to run on Fridays.
211
+ # @param monday_program_id [String, Seam::Null, nil] ID of the thermostat daily program to run on Mondays.
212
+ # @param saturday_program_id [String, Seam::Null, nil] ID of the thermostat daily program to run on Saturdays.
213
+ # @param sunday_program_id [String, Seam::Null, nil] ID of the thermostat daily program to run on Sundays.
214
+ # @param thursday_program_id [String, Seam::Null, nil] ID of the thermostat daily program to run on Thursdays.
215
+ # @param tuesday_program_id [String, Seam::Null, nil] ID of the thermostat daily program to run on Tuesdays.
216
+ # @param wednesday_program_id [String, Seam::Null, nil] ID of the thermostat daily program to run on Wednesdays.
217
217
  # @return [Seam::Resources::ActionAttempt] OK
218
218
  def update_weekly_program(device_id:, friday_program_id: nil, monday_program_id: nil, saturday_program_id: nil, sunday_program_id: nil, thursday_program_id: nil, tuesday_program_id: nil, wednesday_program_id: nil, wait_for_action_attempt: nil)
219
219
  res = @client.post("/thermostats/update_weekly_program", {device_id: device_id, friday_program_id: friday_program_id, monday_program_id: monday_program_id, saturday_program_id: saturday_program_id, sunday_program_id: sunday_program_id, thursday_program_id: thursday_program_id, tuesday_program_id: tuesday_program_id, wednesday_program_id: wednesday_program_id}.compact)
@@ -14,7 +14,7 @@ module Seam
14
14
  # @param ends_at [String] Date and time at which the new thermostat schedule ends, in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format.
15
15
  # @param starts_at [String] Date and time at which the new thermostat schedule starts, in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format.
16
16
  # @param is_override_allowed [Boolean, nil] Indicates whether a person at the thermostat or using the API can change the thermostat's settings while the new schedule is active. See also [Specifying Manual Override Permissions](https://docs.seam.co/capability-guides/thermostats/creating-and-managing-thermostat-schedules#specifying-manual-override-permissions).
17
- # @param max_override_period_minutes [Integer, nil] Number of minutes for which a person at the thermostat or using the API can change the thermostat's settings after the activation of the scheduled climate preset. See also [Specifying Manual Override Permissions](https://docs.seam.co/capability-guides/thermostats/creating-and-managing-thermostat-schedules#specifying-manual-override-permissions).
17
+ # @param max_override_period_minutes [Integer, Seam::Null, nil] Number of minutes for which a person at the thermostat or using the API can change the thermostat's settings after the activation of the scheduled climate preset. See also [Specifying Manual Override Permissions](https://docs.seam.co/capability-guides/thermostats/creating-and-managing-thermostat-schedules#specifying-manual-override-permissions).
18
18
  # @param name [String, nil] Name of the thermostat schedule.
19
19
  # @return [Seam::Resources::ThermostatSchedule] OK
20
20
  def create(climate_preset_key:, device_id:, ends_at:, starts_at:, is_override_allowed: nil, max_override_period_minutes: nil, name: nil)
@@ -56,7 +56,7 @@ module Seam
56
56
  # @param climate_preset_key [String, nil] Key of the [climate preset](https://docs.seam.co/capability-guides/thermostats/creating-and-managing-climate-presets) to use for the thermostat schedule.
57
57
  # @param ends_at [String, nil] Date and time at which the thermostat schedule ends, in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format.
58
58
  # @param is_override_allowed [Boolean, nil] Indicates whether a person at the thermostat or using the API can change the thermostat's settings while the schedule is active. See also [Specifying Manual Override Permissions](https://docs.seam.co/capability-guides/thermostats/creating-and-managing-thermostat-schedules#specifying-manual-override-permissions).
59
- # @param max_override_period_minutes [Integer, nil] Number of minutes for which a person at the thermostat or using the API can change the thermostat's settings after the activation of the scheduled climate preset. See also [Specifying Manual Override Permissions](https://docs.seam.co/capability-guides/thermostats/creating-and-managing-thermostat-schedules#specifying-manual-override-permissions).
59
+ # @param max_override_period_minutes [Integer, Seam::Null, nil] Number of minutes for which a person at the thermostat or using the API can change the thermostat's settings after the activation of the scheduled climate preset. See also [Specifying Manual Override Permissions](https://docs.seam.co/capability-guides/thermostats/creating-and-managing-thermostat-schedules#specifying-manual-override-permissions).
60
60
  # @param name [String, nil] Name of the thermostat schedule.
61
61
  # @param starts_at [String, nil] Date and time at which the thermostat schedule starts, in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format.
62
62
  # @return [nil] OK
@@ -29,10 +29,10 @@ module Seam
29
29
 
30
30
  # Creates a new [user identity](https://docs.seam.co/capability-guides/mobile-access/managing-mobile-app-user-accounts-with-user-identities#what-is-a-user-identity).
31
31
  # @param acs_system_ids [Array<String>, nil] List of access system IDs to associate with the new user identity through access system users. If there's no user with the same email address or phone number in the specified access systems, a new access system user is created. If there is an existing user with the same email or phone number in the specified access systems, the user is linked to the user identity.
32
- # @param email_address [String, nil] Unique email address for the new user identity.
33
- # @param full_name [String, nil] Full name of the user associated with the new user identity.
34
- # @param phone_number [String, nil] Unique phone number for the new user identity in E.164 format (for example, +15555550100).
35
- # @param user_identity_key [String, nil] Unique key for the new user identity.
32
+ # @param email_address [String, Seam::Null, nil] Unique email address for the new user identity.
33
+ # @param full_name [String, Seam::Null, nil] Full name of the user associated with the new user identity.
34
+ # @param phone_number [String, Seam::Null, nil] Unique phone number for the new user identity in E.164 format (for example, +15555550100).
35
+ # @param user_identity_key [String, Seam::Null, nil] Unique key for the new user identity.
36
36
  # @return [Seam::Resources::UserIdentity] OK
37
37
  def create(acs_system_ids: nil, email_address: nil, full_name: nil, phone_number: nil, user_identity_key: nil)
38
38
  res = @client.post("/user_identities/create", {acs_system_ids: acs_system_ids, email_address: email_address, full_name: full_name, phone_number: phone_number, user_identity_key: user_identity_key}.compact)
@@ -88,7 +88,7 @@ module Seam
88
88
  # @param created_before [Time, nil] Timestamp by which to limit returned user identities. Returns user identities created before this timestamp.
89
89
  # @param credential_manager_acs_system_id [String, nil] `acs_system_id` of the credential manager by which you want to filter the list of user identities.
90
90
  # @param limit [Integer, nil] Maximum number of records to return per page.
91
- # @param page_cursor [String, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
91
+ # @param page_cursor [String, Seam::Null, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
92
92
  # @param search [String, nil] String for which to search. Filters returned user identities to include all records that satisfy a partial match using `full_name`, `phone_number`, `email_address` or `user_identity_id`.
93
93
  # @param user_identity_ids [Array<String>, nil] Array of user identity IDs by which to filter the list of user identities.
94
94
  # @return [Seam::Resources::UserIdentity] OK
@@ -156,10 +156,10 @@ module Seam
156
156
 
157
157
  # Updates a specified [user identity](https://docs.seam.co/capability-guides/mobile-access/managing-mobile-app-user-accounts-with-user-identities#what-is-a-user-identity).
158
158
  # @param user_identity_id [String] ID of the user identity that you want to update.
159
- # @param email_address [String, nil] Unique email address for the user identity.
160
- # @param full_name [String, nil] Full name of the user associated with the user identity.
161
- # @param phone_number [String, nil] Unique phone number for the user identity.
162
- # @param user_identity_key [String, nil] Unique key for the user identity.
159
+ # @param email_address [String, Seam::Null, nil] Unique email address for the user identity.
160
+ # @param full_name [String, Seam::Null, nil] Full name of the user associated with the user identity.
161
+ # @param phone_number [String, Seam::Null, nil] Unique phone number for the user identity.
162
+ # @param user_identity_key [String, Seam::Null, nil] Unique key for the user identity.
163
163
  # @return [nil] OK
164
164
  def update(user_identity_id:, email_address: nil, full_name: nil, phone_number: nil, user_identity_key: nil)
165
165
  @client.patch("/user_identities/update", {user_identity_id: user_identity_id, email_address: email_address, full_name: full_name, phone_number: phone_number, user_identity_key: user_identity_key}.compact)
@@ -20,7 +20,7 @@ module Seam
20
20
  # Returns a list of all unmanaged [user identities](https://docs.seam.co/capability-guides/mobile-access/managing-mobile-app-user-accounts-with-user-identities#what-is-a-user-identity) (where is_managed = false).
21
21
  # @param created_before [Time, nil] Timestamp by which to limit returned unmanaged user identities. Returns user identities created before this timestamp.
22
22
  # @param limit [Integer, nil] Maximum number of records to return per page.
23
- # @param page_cursor [String, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
23
+ # @param page_cursor [String, Seam::Null, nil] Identifies the specific page of results to return, obtained from the previous page's `next_page_cursor`.
24
24
  # @param search [String, nil] String for which to search. Filters returned unmanaged user identities to include all records that satisfy a partial match using `full_name`, `phone_number`, `email_address`, `user_identity_id` or `acs_system_id`.
25
25
  # @return [Seam::Resources::UnmanagedUserIdentity] OK
26
26
  def list(created_before: nil, limit: nil, page_cursor: nil, search: nil)
@@ -13,7 +13,7 @@ module Seam
13
13
  # Creates a new [workspace](https://docs.seam.co/core-concepts/workspaces).
14
14
  # @param name [String] Name of the new workspace.
15
15
  # @param company_name [String, nil] Company name for the new workspace.
16
- # @param connect_partner_name [String, nil] Connect partner name for the new workspace.
16
+ # @param connect_partner_name [String, Seam::Null, nil] Connect partner name for the new workspace.
17
17
  # @deprecated connect_partner_name: Use `company_name` instead.
18
18
  # @param connect_webview_customization [Hash, nil] [Connect Webview](https://docs.seam.co/core-concepts/connect-webviews) customizations for the new workspace. See also [Customize the Look and Feel of Your Connect Webviews](https://docs.seam.co/core-concepts/connect-webviews/customizing-connect-webviews#customize-the-look-and-feel-of-your-connect-webviews).
19
19
  # @param is_sandbox [Boolean, nil] Indicates whether the new workspace is a [sandbox workspace](https://docs.seam.co/core-concepts/workspaces#sandbox-workspaces).
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "url_search_params_serializer"
4
+
5
+ # Strict serialization, used by the SDK itself: _strict=true is added to any
6
+ # non-empty query so the Seam API uses strict, schema-aware parsing.
7
+ module Seam
8
+ # (see UrlSearchParamsSerializer.serialize_url_search_params)
9
+ def self.serialize_url_search_params(params)
10
+ UrlSearchParamsSerializer.serialize_url_search_params(params, strict: true)
11
+ end
12
+
13
+ # (see UrlSearchParamsSerializer.update_url_search_params)
14
+ def self.update_url_search_params(search_params, params)
15
+ UrlSearchParamsSerializer.update_url_search_params(search_params, params, strict: true)
16
+ end
17
+ end
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "uri"
4
+
5
+ module Seam
6
+ # A mutable, ordered list of name/value string pairs modeling the parts of
7
+ # the WHATWG URLSearchParams interface that the Seam URL search params
8
+ # serializer needs.
9
+ class UrlSearchParams
10
+ include Enumerable
11
+
12
+ # @param init [String, Hash, Enumerable, nil]
13
+ def initialize(init = nil)
14
+ @pairs = []
15
+ return if init.nil?
16
+
17
+ case init
18
+ when String
19
+ query = init.delete_prefix("?")
20
+ URI.decode_www_form(query).each { |name, value| append(name, value) } unless query.empty?
21
+ when Hash
22
+ init.each { |name, value| append(name, value) }
23
+ else
24
+ init.each { |name, value| append(name, value) }
25
+ end
26
+ end
27
+
28
+ def append(name, value)
29
+ @pairs << [name.to_s, value.to_s]
30
+ nil
31
+ end
32
+
33
+ def set(name, value)
34
+ name = name.to_s
35
+ replaced = false
36
+ @pairs = @pairs.filter_map do |pair|
37
+ next pair unless pair.first == name
38
+ next nil if replaced
39
+
40
+ replaced = true
41
+ [name, value.to_s]
42
+ end
43
+ append(name, value) unless replaced
44
+ nil
45
+ end
46
+
47
+ def get(name)
48
+ name = name.to_s
49
+ @pairs.each { |pair_name, value| return value if pair_name == name }
50
+ nil
51
+ end
52
+
53
+ def get_all(name)
54
+ name = name.to_s
55
+ @pairs.filter_map { |pair_name, value| value if pair_name == name }
56
+ end
57
+
58
+ def has?(name)
59
+ name = name.to_s
60
+ @pairs.any? { |pair_name, _| pair_name == name }
61
+ end
62
+
63
+ def delete(name)
64
+ name = name.to_s
65
+ @pairs.reject! { |pair_name, _| pair_name == name }
66
+ nil
67
+ end
68
+
69
+ def sort!
70
+ @pairs = @pairs.each_with_index.sort_by do |(name, _), index|
71
+ [name.encode(Encoding::UTF_16BE).b, index]
72
+ end.map(&:first)
73
+ nil
74
+ end
75
+
76
+ def each(&block)
77
+ return @pairs.each unless block
78
+
79
+ @pairs.each(&block)
80
+ self
81
+ end
82
+
83
+ def size
84
+ @pairs.size
85
+ end
86
+ alias_method :length, :size
87
+
88
+ def empty?
89
+ @pairs.empty?
90
+ end
91
+
92
+ def to_s
93
+ @pairs.map do |name, value|
94
+ "#{self.class.encode_component(name)}=#{self.class.encode_component(value)}"
95
+ end.join("&")
96
+ end
97
+
98
+ def self.encode_component(string)
99
+ URI.encode_www_form_component(string.encode(Encoding::UTF_8))
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,217 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "date"
4
+
5
+ require_relative "null"
6
+ require_relative "url_search_params"
7
+
8
+ module Seam
9
+ class UnserializableParamError < StandardError
10
+ attr_reader :param_name
11
+
12
+ def initialize(param_name, reason)
13
+ @param_name = param_name
14
+ super("Could not serialize parameter: '#{param_name}' #{reason}")
15
+ end
16
+ end
17
+
18
+ def self.replace_null(value)
19
+ case value
20
+ when Seam::Null then nil
21
+ when Hash then value.transform_values { |v| replace_null(v) }
22
+ when Array then value.map { |v| replace_null(v) }
23
+ else value
24
+ end
25
+ end
26
+
27
+ # Serializes parameters to a URL query string following the
28
+ # @seamapi/url-search-params-serializer standard:
29
+ # https://github.com/seamapi/url-search-params-serializer
30
+ module UrlSearchParamsSerializer
31
+ # @param params [Hash]
32
+ # @param strict [Boolean] Whether to add +_strict=true+ to a non-empty
33
+ # query string
34
+ # @return [String] The query string, without a leading +?+
35
+ # @raise [UnserializableParamError]
36
+ def self.serialize_url_search_params(params, strict: false)
37
+ search_params = UrlSearchParams.new
38
+ update_url_search_params(search_params, params, strict: strict)
39
+ search_params.to_s
40
+ end
41
+
42
+ # Serializes parameters into an existing {UrlSearchParams} collection,
43
+ # preserving pairs it does not overwrite.
44
+ #
45
+ # @param search_params [UrlSearchParams]
46
+ # @param params [Hash]
47
+ # @param strict [Boolean] Whether to add +_strict=true+ when the
48
+ # resulting collection is non-empty
49
+ # @return [nil]
50
+ # @raise [UnserializableParamError]
51
+ def self.update_url_search_params(search_params, params, strict: false)
52
+ nested_update(search_params, params, [])
53
+ search_params.sort!
54
+
55
+ if strict && !search_params.empty?
56
+ search_params.delete("_strict")
57
+ search_params.append("_strict", "true")
58
+ end
59
+
60
+ nil
61
+ end
62
+
63
+ def self.nested_update(search_params, params, path)
64
+ params.each do |key, value|
65
+ unless key.is_a?(String) || key.is_a?(Symbol)
66
+ raise UnserializableParamError.new(
67
+ key.inspect,
68
+ "has a name that is not a string which is unsupported"
69
+ )
70
+ end
71
+ key = key.to_s
72
+
73
+ if key.include?(".")
74
+ raise UnserializableParamError.new(
75
+ key,
76
+ 'contains one or more dots "." in its name which is unsupported'
77
+ )
78
+ end
79
+
80
+ current_path = [*path, key]
81
+
82
+ if value.is_a?(Hash)
83
+ nested_update(search_params, value, current_path)
84
+ next
85
+ end
86
+
87
+ name = current_path.join(".")
88
+
89
+ next if value.nil?
90
+
91
+ value = value.to_s if value.is_a?(Symbol)
92
+
93
+ next if value.is_a?(String) && value.empty?
94
+
95
+ if value.is_a?(Array)
96
+ serialize_array(search_params, name, value)
97
+ next
98
+ end
99
+
100
+ search_params.set(name, serialize_value(name, value))
101
+ end
102
+ end
103
+
104
+ def self.serialize_array(search_params, name, values)
105
+ # The parser reads a single pair with an empty value as an empty array.
106
+ if values.empty?
107
+ search_params.set(name, "")
108
+ return
109
+ end
110
+
111
+ values = values.map { |value| value.is_a?(Symbol) ? value.to_s : value }
112
+
113
+ if values.length == 1 && values.first == ""
114
+ raise UnserializableParamError.new(
115
+ name,
116
+ "is a single element array containing the empty string which is unsupported"
117
+ )
118
+ end
119
+
120
+ if values.any? { |value| value == "" }
121
+ raise UnserializableParamError.new(
122
+ name,
123
+ "is an array containing the empty string which is unsupported"
124
+ )
125
+ end
126
+
127
+ if values.any? { |value| value.nil? || value.is_a?(Seam::Null) }
128
+ raise UnserializableParamError.new(
129
+ name,
130
+ "is an array containing null or undefined values which is unsupported"
131
+ )
132
+ end
133
+
134
+ values.each { |value| search_params.append(name, serialize_value(name, value)) }
135
+ end
136
+
137
+ def self.serialize_value(name, value)
138
+ case value
139
+ when Seam::Null then ""
140
+ when String then value
141
+ when true, false then value.to_s
142
+ when Integer then value.to_s
143
+ when Float then serialize_float(name, value)
144
+ when Time then serialize_time(value)
145
+ when DateTime then serialize_time(value.to_time)
146
+ when Date then serialize_time(Time.utc(value.year, value.month, value.day))
147
+ else
148
+ raise UnserializableParamError.new(name, "is a #{value.class}")
149
+ end
150
+ end
151
+
152
+ # Formats a float exactly like ECMAScript Number::toString.
153
+ def self.serialize_float(name, value)
154
+ raise UnserializableParamError.new(name, "is NaN") if value.nan?
155
+ if value.infinite?
156
+ raise UnserializableParamError.new(name, "is #{value.positive? ? "Infinity" : "-Infinity"}")
157
+ end
158
+ return "0" if value.zero?
159
+
160
+ digits, point = shortest_decimal(value.abs)
161
+ count = digits.length
162
+
163
+ formatted = if point.between?(count, 21)
164
+ digits + "0" * (point - count)
165
+ elsif point.positive? && point <= 21
166
+ "#{digits[0, point]}.#{digits[point..]}"
167
+ elsif point > -6 && point <= 0
168
+ "0.#{"0" * -point}#{digits}"
169
+ else
170
+ mantissa = (count == 1) ? digits : "#{digits[0]}.#{digits[1..]}"
171
+ exponent = point - 1
172
+ "#{mantissa}e#{(exponent >= 0) ? "+" : "-"}#{exponent.abs}"
173
+ end
174
+
175
+ value.negative? ? "-#{formatted}" : formatted
176
+ end
177
+
178
+ # Returns the shortest round-tripping decimal digits of a positive float
179
+ # and the position of the decimal point relative to the first digit.
180
+ def self.shortest_decimal(value)
181
+ repr = value.to_s
182
+
183
+ if repr.include?("e")
184
+ mantissa, exponent = repr.split("e")
185
+ integer_part, fraction_part = mantissa.split(".")
186
+ digits = integer_part + (fraction_part || "")
187
+ point = integer_part.length + exponent.to_i
188
+ else
189
+ integer_part, fraction_part = repr.split(".")
190
+ digits = integer_part + (fraction_part || "")
191
+ point = integer_part.length
192
+ end
193
+
194
+ leading_zeros = digits[/\A0*/].length
195
+ digits = digits[leading_zeros..]
196
+ point -= leading_zeros
197
+
198
+ [digits.sub(/0+\z/, ""), point]
199
+ end
200
+
201
+ # Formats a time exactly like JavaScript's Date#toISOString.
202
+ def self.serialize_time(time)
203
+ utc = time.getutc
204
+ year = if utc.year.between?(0, 9999)
205
+ format("%04d", utc.year)
206
+ elsif utc.year > 9999
207
+ format("+%06d", utc.year)
208
+ else
209
+ format("-%06d", -utc.year)
210
+ end
211
+ format(
212
+ "%s-%02d-%02dT%02d:%02d:%02d.%03dZ",
213
+ year, utc.month, utc.day, utc.hour, utc.min, utc.sec, utc.nsec / 1_000_000
214
+ )
215
+ end
216
+ end
217
+ end
data/lib/seam/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Seam
4
- VERSION = "2.140.0"
4
+ VERSION = "2.141.0"
5
5
  end
data/lib/seam.rb CHANGED
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "seam/null"
4
+ require_relative "seam/url_search_params"
5
+ require_relative "seam/strict_url_search_params_serializer"
3
6
  require_relative "seam/http"
4
7
  require_relative "seam/http_without_workspace"
5
8
  require_relative "seam/webhook"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: seam
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.140.0
4
+ version: 2.141.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Seam Labs, Inc.
@@ -197,6 +197,7 @@ files:
197
197
  - lib/seam/http.rb
198
198
  - lib/seam/http_single_workspace.rb
199
199
  - lib/seam/http_without_workspace.rb
200
+ - lib/seam/null.rb
200
201
  - lib/seam/options.rb
201
202
  - lib/seam/paginator.rb
202
203
  - lib/seam/parse_options.rb
@@ -279,7 +280,10 @@ files:
279
280
  - lib/seam/routes/user_identities_unmanaged.rb
280
281
  - lib/seam/routes/webhooks.rb
281
282
  - lib/seam/routes/workspaces.rb
283
+ - lib/seam/strict_url_search_params_serializer.rb
282
284
  - lib/seam/token.rb
285
+ - lib/seam/url_search_params.rb
286
+ - lib/seam/url_search_params_serializer.rb
283
287
  - lib/seam/version.rb
284
288
  - lib/seam/wait_for_action_attempt.rb
285
289
  - lib/seam/webhook.rb