seam 2.140.0 → 2.141.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +86 -0
- data/lib/seam/action_attempt_resolver.rb +54 -0
- data/lib/seam/null.rb +23 -0
- data/lib/seam/request.rb +49 -1
- data/lib/seam/routes/access_codes.rb +1 -1
- data/lib/seam/routes/access_codes_unmanaged.rb +1 -1
- data/lib/seam/routes/access_grants.rb +6 -6
- data/lib/seam/routes/access_grants_unmanaged.rb +1 -1
- data/lib/seam/routes/access_methods.rb +5 -5
- data/lib/seam/routes/acs_credentials.rb +1 -1
- data/lib/seam/routes/acs_encoders.rb +5 -5
- data/lib/seam/routes/acs_entrances.rb +4 -4
- data/lib/seam/routes/acs_users.rb +2 -2
- data/lib/seam/routes/action_attempts.rb +3 -3
- data/lib/seam/routes/connect_webviews.rb +1 -1
- data/lib/seam/routes/connected_accounts.rb +1 -1
- data/lib/seam/routes/devices.rb +3 -3
- data/lib/seam/routes/devices_unmanaged.rb +1 -1
- data/lib/seam/routes/locks.rb +4 -4
- data/lib/seam/routes/locks_simulate.rb +3 -3
- data/lib/seam/routes/spaces.rb +1 -1
- data/lib/seam/routes/thermostats.rb +22 -22
- data/lib/seam/routes/thermostats_daily_programs.rb +2 -2
- data/lib/seam/routes/thermostats_schedules.rb +2 -2
- data/lib/seam/routes/user_identities.rb +9 -9
- data/lib/seam/routes/user_identities_unmanaged.rb +1 -1
- data/lib/seam/routes/workspaces.rb +3 -3
- data/lib/seam/strict_url_search_params_serializer.rb +17 -0
- data/lib/seam/url_search_params.rb +102 -0
- data/lib/seam/url_search_params_serializer.rb +217 -0
- data/lib/seam/version.rb +1 -1
- data/lib/seam.rb +3 -0
- metadata +6 -2
- data/lib/seam/helpers/action_attempt.rb +0 -56
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "seam/
|
|
3
|
+
require "seam/action_attempt_resolver"
|
|
4
4
|
|
|
5
5
|
module Seam
|
|
6
6
|
module Clients
|
|
@@ -19,7 +19,7 @@ module Seam
|
|
|
19
19
|
|
|
20
20
|
wait_for_action_attempt = wait_for_action_attempt.nil? ? @defaults.wait_for_action_attempt : wait_for_action_attempt
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
Seam::ActionAttemptResolver.resolve(Seam::Resources::ActionAttempt.load_from_response(res.body["action_attempt"]), @client, wait_for_action_attempt)
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
# Simulates a manual lock action using a keypad. You can only perform this action for [August](https://docs.seam.co/device-and-system-integration-guides/august-locks) devices within [sandbox workspaces](https://docs.seam.co/core-concepts/workspaces#sandbox-workspaces).
|
|
@@ -30,7 +30,7 @@ module Seam
|
|
|
30
30
|
|
|
31
31
|
wait_for_action_attempt = wait_for_action_attempt.nil? ? @defaults.wait_for_action_attempt : wait_for_action_attempt
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
Seam::ActionAttemptResolver.resolve(Seam::Resources::ActionAttempt.load_from_response(res.body["action_attempt"]), @client, wait_for_action_attempt)
|
|
34
34
|
end
|
|
35
35
|
end
|
|
36
36
|
end
|
data/lib/seam/routes/spaces.rb
CHANGED
|
@@ -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
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "seam/
|
|
3
|
+
require "seam/action_attempt_resolver"
|
|
4
4
|
|
|
5
5
|
module Seam
|
|
6
6
|
module Clients
|
|
@@ -31,7 +31,7 @@ module Seam
|
|
|
31
31
|
|
|
32
32
|
wait_for_action_attempt = wait_for_action_attempt.nil? ? @defaults.wait_for_action_attempt : wait_for_action_attempt
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
Seam::ActionAttemptResolver.resolve(Seam::Resources::ActionAttempt.load_from_response(res.body["action_attempt"]), @client, wait_for_action_attempt)
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
# Sets a specified [thermostat](https://docs.seam.co/capability-guides/thermostats) to [cool mode](https://docs.seam.co/capability-guides/thermostats/configure-current-climate-settings).
|
|
@@ -44,7 +44,7 @@ module Seam
|
|
|
44
44
|
|
|
45
45
|
wait_for_action_attempt = wait_for_action_attempt.nil? ? @defaults.wait_for_action_attempt : wait_for_action_attempt
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
Seam::ActionAttemptResolver.resolve(Seam::Resources::ActionAttempt.load_from_response(res.body["action_attempt"]), @client, wait_for_action_attempt)
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
# Creates a [climate preset](https://docs.seam.co/capability-guides/thermostats/creating-and-managing-climate-presets) for a specified [thermostat](https://docs.seam.co/capability-guides/thermostats).
|
|
@@ -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)
|
|
@@ -88,7 +88,7 @@ module Seam
|
|
|
88
88
|
|
|
89
89
|
wait_for_action_attempt = wait_for_action_attempt.nil? ? @defaults.wait_for_action_attempt : wait_for_action_attempt
|
|
90
90
|
|
|
91
|
-
|
|
91
|
+
Seam::ActionAttemptResolver.resolve(Seam::Resources::ActionAttempt.load_from_response(res.body["action_attempt"]), @client, wait_for_action_attempt)
|
|
92
92
|
end
|
|
93
93
|
|
|
94
94
|
# Sets a specified [thermostat](https://docs.seam.co/capability-guides/thermostats) to [heat-cool ("auto") mode](https://docs.seam.co/capability-guides/thermostats/configure-current-climate-settings).
|
|
@@ -103,7 +103,7 @@ module Seam
|
|
|
103
103
|
|
|
104
104
|
wait_for_action_attempt = wait_for_action_attempt.nil? ? @defaults.wait_for_action_attempt : wait_for_action_attempt
|
|
105
105
|
|
|
106
|
-
|
|
106
|
+
Seam::ActionAttemptResolver.resolve(Seam::Resources::ActionAttempt.load_from_response(res.body["action_attempt"]), @client, wait_for_action_attempt)
|
|
107
107
|
end
|
|
108
108
|
|
|
109
109
|
# Returns a list of all [thermostats](https://docs.seam.co/capability-guides/thermostats).
|
|
@@ -128,7 +128,7 @@ module Seam
|
|
|
128
128
|
|
|
129
129
|
wait_for_action_attempt = wait_for_action_attempt.nil? ? @defaults.wait_for_action_attempt : wait_for_action_attempt
|
|
130
130
|
|
|
131
|
-
|
|
131
|
+
Seam::ActionAttemptResolver.resolve(Seam::Resources::ActionAttempt.load_from_response(res.body["action_attempt"]), @client, wait_for_action_attempt)
|
|
132
132
|
end
|
|
133
133
|
|
|
134
134
|
# Sets a specified [climate preset](https://docs.seam.co/capability-guides/thermostats/creating-and-managing-climate-presets) as the ["fallback"](https://docs.seam.co/capability-guides/thermostats/creating-and-managing-climate-presets/setting-the-fallback-climate-preset) preset for a specified [thermostat](https://docs.seam.co/capability-guides/thermostats).
|
|
@@ -152,7 +152,7 @@ module Seam
|
|
|
152
152
|
|
|
153
153
|
wait_for_action_attempt = wait_for_action_attempt.nil? ? @defaults.wait_for_action_attempt : wait_for_action_attempt
|
|
154
154
|
|
|
155
|
-
|
|
155
|
+
Seam::ActionAttemptResolver.resolve(Seam::Resources::ActionAttempt.load_from_response(res.body["action_attempt"]), @client, wait_for_action_attempt)
|
|
156
156
|
end
|
|
157
157
|
|
|
158
158
|
# Sets the [HVAC mode](https://docs.seam.co/capability-guides/thermostats/configure-current-climate-settings) for a specified [thermostat](https://docs.seam.co/capability-guides/thermostats).
|
|
@@ -168,15 +168,15 @@ module Seam
|
|
|
168
168
|
|
|
169
169
|
wait_for_action_attempt = wait_for_action_attempt.nil? ? @defaults.wait_for_action_attempt : wait_for_action_attempt
|
|
170
170
|
|
|
171
|
-
|
|
171
|
+
Seam::ActionAttemptResolver.resolve(Seam::Resources::ActionAttempt.load_from_response(res.body["action_attempt"]), @client, wait_for_action_attempt)
|
|
172
172
|
end
|
|
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,20 +207,20 @@ 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)
|
|
220
220
|
|
|
221
221
|
wait_for_action_attempt = wait_for_action_attempt.nil? ? @defaults.wait_for_action_attempt : wait_for_action_attempt
|
|
222
222
|
|
|
223
|
-
|
|
223
|
+
Seam::ActionAttemptResolver.resolve(Seam::Resources::ActionAttempt.load_from_response(res.body["action_attempt"]), @client, wait_for_action_attempt)
|
|
224
224
|
end
|
|
225
225
|
end
|
|
226
226
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "seam/
|
|
3
|
+
require "seam/action_attempt_resolver"
|
|
4
4
|
|
|
5
5
|
module Seam
|
|
6
6
|
module Clients
|
|
@@ -40,7 +40,7 @@ module Seam
|
|
|
40
40
|
|
|
41
41
|
wait_for_action_attempt = wait_for_action_attempt.nil? ? @defaults.wait_for_action_attempt : wait_for_action_attempt
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
Seam::ActionAttemptResolver.resolve(Seam::Resources::ActionAttempt.load_from_response(res.body["action_attempt"]), @client, wait_for_action_attempt)
|
|
44
44
|
end
|
|
45
45
|
end
|
|
46
46
|
end
|
|
@@ -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)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "seam/
|
|
3
|
+
require "seam/action_attempt_resolver"
|
|
4
4
|
|
|
5
5
|
module Seam
|
|
6
6
|
module Clients
|
|
@@ -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).
|
|
@@ -56,7 +56,7 @@ module Seam
|
|
|
56
56
|
|
|
57
57
|
wait_for_action_attempt = wait_for_action_attempt.nil? ? @defaults.wait_for_action_attempt : wait_for_action_attempt
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
Seam::ActionAttemptResolver.resolve(Seam::Resources::ActionAttempt.load_from_response(res.body["action_attempt"]), @client, wait_for_action_attempt)
|
|
60
60
|
end
|
|
61
61
|
|
|
62
62
|
# Updates the [workspace](https://docs.seam.co/core-concepts/workspaces) associated with the authentication value.
|
|
@@ -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
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"
|