seam 2.0.0a2 → 2.0.0b1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +49 -53
- data/README.md +323 -3
- data/Rakefile +4 -1
- data/lib/seam/auth.rb +118 -0
- data/lib/seam/base_resource.rb +63 -0
- data/lib/seam/deep_hash_accessor.rb +37 -0
- data/lib/seam/default_endpoint.rb +5 -0
- data/lib/seam/helpers/action_attempt.rb +45 -0
- data/lib/seam/http.rb +52 -0
- data/lib/seam/http_multi_workspace.rb +62 -0
- data/lib/seam/http_single_workspace.rb +42 -0
- data/lib/seam/options.rb +64 -0
- data/lib/seam/parse_options.rb +23 -0
- data/lib/seam/request.rb +82 -51
- data/lib/seam/routes/clients/access_codes.rb +74 -0
- data/lib/seam/routes/clients/access_codes_simulate.rb +18 -0
- data/lib/seam/routes/clients/access_codes_unmanaged.rb +42 -0
- data/lib/seam/routes/clients/acs.rb +44 -0
- data/lib/seam/routes/clients/acs_access_groups.rb +48 -0
- data/lib/seam/routes/clients/acs_access_groups_unmanaged.rb +24 -0
- data/lib/seam/routes/clients/acs_credential_pools.rb +18 -0
- data/lib/seam/routes/clients/acs_credential_provisioning_automations.rb +18 -0
- data/lib/seam/routes/clients/acs_credentials.rb +60 -0
- data/lib/seam/routes/clients/acs_credentials_unmanaged.rb +24 -0
- data/lib/seam/routes/clients/acs_encoders.rb +36 -0
- data/lib/seam/routes/clients/acs_entrances.rb +36 -0
- data/lib/seam/routes/clients/acs_systems.rb +30 -0
- data/lib/seam/routes/clients/acs_users.rb +78 -0
- data/lib/seam/routes/clients/acs_users_unmanaged.rb +24 -0
- data/lib/seam/routes/clients/action_attempts.rb +28 -0
- data/lib/seam/routes/clients/client_sessions.rb +54 -0
- data/lib/seam/routes/clients/connect_webviews.rb +36 -0
- data/lib/seam/routes/clients/connected_accounts.rb +36 -0
- data/lib/seam/routes/clients/devices.rb +50 -0
- data/lib/seam/routes/clients/devices_simulate.rb +30 -0
- data/lib/seam/routes/clients/devices_unmanaged.rb +30 -0
- data/lib/seam/routes/clients/events.rb +24 -0
- data/lib/seam/routes/clients/index.rb +38 -0
- data/lib/seam/routes/clients/locks.rb +42 -0
- data/lib/seam/routes/clients/networks.rb +24 -0
- data/lib/seam/routes/clients/noise_sensors.rb +26 -0
- data/lib/seam/routes/clients/noise_sensors_noise_thresholds.rb +42 -0
- data/lib/seam/routes/clients/noise_sensors_simulate.rb +18 -0
- data/lib/seam/routes/clients/phones.rb +28 -0
- data/lib/seam/routes/clients/phones_simulate.rb +18 -0
- data/lib/seam/routes/clients/thermostats.rb +108 -0
- data/lib/seam/routes/clients/thermostats_schedules.rb +42 -0
- data/lib/seam/routes/clients/user_identities.rb +88 -0
- data/lib/seam/routes/clients/user_identities_enrollment_automations.rb +36 -0
- data/lib/seam/routes/clients/webhooks.rb +42 -0
- data/lib/seam/routes/clients/workspaces.rb +40 -0
- data/lib/seam/routes/resources/access_code.rb +14 -0
- data/lib/seam/routes/resources/acs_access_group.rb +11 -0
- data/lib/seam/routes/resources/acs_credential.rb +14 -0
- data/lib/seam/routes/resources/acs_credential_pool.rb +11 -0
- data/lib/seam/routes/resources/acs_credential_provisioning_automation.rb +11 -0
- data/lib/seam/routes/resources/acs_entrance.rb +13 -0
- data/lib/seam/routes/resources/acs_system.rb +14 -0
- data/lib/seam/routes/resources/acs_user.rb +14 -0
- data/lib/seam/routes/resources/action_attempt.rb +9 -0
- data/lib/seam/routes/resources/client_session.rb +11 -0
- data/lib/seam/routes/resources/connect_webview.rb +11 -0
- data/lib/seam/routes/resources/connected_account.rb +14 -0
- data/lib/seam/routes/resources/device.rb +14 -0
- data/lib/seam/routes/resources/device_provider.rb +9 -0
- data/lib/seam/routes/resources/enrollment_automation.rb +11 -0
- data/lib/seam/routes/resources/event.rb +11 -0
- data/lib/seam/routes/resources/index.rb +33 -0
- data/lib/seam/routes/resources/network.rb +11 -0
- data/lib/seam/routes/resources/noise_threshold.rb +9 -0
- data/lib/seam/routes/resources/phone.rb +14 -0
- data/lib/seam/routes/resources/resource_error.rb +11 -0
- data/lib/seam/routes/resources/resource_errors_support.rb +11 -0
- data/lib/seam/routes/resources/resource_warning.rb +11 -0
- data/lib/seam/routes/resources/resource_warnings_support.rb +11 -0
- data/lib/seam/routes/resources/service_health.rb +9 -0
- data/lib/seam/routes/resources/thermostat_schedule.rb +13 -0
- data/lib/seam/routes/resources/unmanaged_access_code.rb +14 -0
- data/lib/seam/routes/resources/unmanaged_device.rb +14 -0
- data/lib/seam/routes/resources/user_identity.rb +11 -0
- data/lib/seam/routes/resources/webhook.rb +9 -0
- data/lib/seam/routes/resources/workspace.rb +9 -0
- data/lib/seam/routes/routes.rb +94 -0
- data/lib/seam/token.rb +53 -0
- data/lib/seam/version.rb +1 -1
- data/lib/seam/wait_for_action_attempt.rb +32 -0
- data/lib/seam/webhook.rb +23 -0
- data/lib/seam.rb +19 -68
- metadata +115 -70
- data/lib/seam/client.rb +0 -129
- data/lib/seam/clients/access_codes.rb +0 -95
- data/lib/seam/clients/access_codes_simulate.rb +0 -17
- data/lib/seam/clients/access_codes_unmanaged.rb +0 -57
- data/lib/seam/clients/acs.rb +0 -35
- data/lib/seam/clients/acs_access_groups.rb +0 -57
- data/lib/seam/clients/acs_credential_pools.rb +0 -17
- data/lib/seam/clients/acs_credential_provisioning_automations.rb +0 -17
- data/lib/seam/clients/acs_credentials.rb +0 -77
- data/lib/seam/clients/acs_entrances.rb +0 -47
- data/lib/seam/clients/acs_systems.rb +0 -27
- data/lib/seam/clients/acs_users.rb +0 -117
- data/lib/seam/clients/action_attempts.rb +0 -30
- data/lib/seam/clients/base_client.rb +0 -21
- data/lib/seam/clients/client_sessions.rb +0 -77
- data/lib/seam/clients/connect_webviews.rb +0 -47
- data/lib/seam/clients/connected_accounts.rb +0 -47
- data/lib/seam/clients/devices.rb +0 -65
- data/lib/seam/clients/devices_simulate.rb +0 -17
- data/lib/seam/clients/devices_unmanaged.rb +0 -37
- data/lib/seam/clients/events.rb +0 -27
- data/lib/seam/clients/locks.rb +0 -53
- data/lib/seam/clients/networks.rb +0 -27
- data/lib/seam/clients/noise_sensors.rb +0 -15
- data/lib/seam/clients/noise_sensors_noise_thresholds.rb +0 -57
- data/lib/seam/clients/noise_sensors_simulate.rb +0 -17
- data/lib/seam/clients/phones.rb +0 -31
- data/lib/seam/clients/phones_simulate.rb +0 -17
- data/lib/seam/clients/thermostats.rb +0 -106
- data/lib/seam/clients/thermostats_climate_setting_schedules.rb +0 -57
- data/lib/seam/clients/user_identities.rb +0 -131
- data/lib/seam/clients/user_identities_enrollment_automations.rb +0 -47
- data/lib/seam/clients/webhooks.rb +0 -57
- data/lib/seam/clients/workspaces.rb +0 -50
- data/lib/seam/resources/access_code.rb +0 -12
- data/lib/seam/resources/acs_access_group.rb +0 -9
- data/lib/seam/resources/acs_credential.rb +0 -12
- data/lib/seam/resources/acs_credential_pool.rb +0 -9
- data/lib/seam/resources/acs_credential_provisioning_automation.rb +0 -9
- data/lib/seam/resources/acs_entrance.rb +0 -9
- data/lib/seam/resources/acs_system.rb +0 -9
- data/lib/seam/resources/acs_user.rb +0 -9
- data/lib/seam/resources/action_attempt.rb +0 -46
- data/lib/seam/resources/base_resource.rb +0 -58
- data/lib/seam/resources/client_session.rb +0 -9
- data/lib/seam/resources/climate_setting_schedule.rb +0 -11
- data/lib/seam/resources/connect_webview.rb +0 -9
- data/lib/seam/resources/connected_account.rb +0 -12
- data/lib/seam/resources/device.rb +0 -12
- data/lib/seam/resources/device_provider.rb +0 -7
- data/lib/seam/resources/enrollment_automation.rb +0 -9
- data/lib/seam/resources/event.rb +0 -9
- data/lib/seam/resources/network.rb +0 -9
- data/lib/seam/resources/noise_threshold.rb +0 -7
- data/lib/seam/resources/phone.rb +0 -12
- data/lib/seam/resources/resource_error.rb +0 -9
- data/lib/seam/resources/resource_errors_support.rb +0 -9
- data/lib/seam/resources/resource_warning.rb +0 -9
- data/lib/seam/resources/resource_warnings_support.rb +0 -9
- data/lib/seam/resources/service_health.rb +0 -7
- data/lib/seam/resources/unmanaged_access_code.rb +0 -12
- data/lib/seam/resources/unmanaged_device.rb +0 -12
- data/lib/seam/resources/user_identity.rb +0 -9
- data/lib/seam/resources/webhook.rb +0 -7
- data/lib/seam/resources/workspace.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c47615cf01fabbff89ed3fb2c39328d738ec2a4793c98a5dd91f0227806d2fbb
|
4
|
+
data.tar.gz: 6824424bfc7f8cfd753e91b25e8baf8c88f2e61ae9254a4fe0489afaa91609f4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 990c8295e652aba9d0ccc06bf3af2a894ff1a1a095055438115e6a295e1082a04966dbeaffca13e34bc22dc41031a5cdbb1569f3c5a967130dfa507ffd6eb0e8
|
7
|
+
data.tar.gz: e0b2a61c39c454efba706c907779a73ed34781c921e893f2eb621f4ce91413111ea79a325947326c7a055d5438d209335cb6c9682f30ee7a02824b0bfe55e127
|
data/Gemfile.lock
CHANGED
@@ -1,117 +1,113 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
seam (2.0.
|
5
|
-
|
4
|
+
seam (2.0.0b1)
|
5
|
+
faraday (~> 2.7)
|
6
|
+
faraday-retry (~> 2.2)
|
7
|
+
svix (~> 1.30)
|
6
8
|
|
7
9
|
GEM
|
8
10
|
remote: https://rubygems.org/
|
9
11
|
specs:
|
10
|
-
addressable (2.8.
|
11
|
-
public_suffix (>= 2.0.2, <
|
12
|
+
addressable (2.8.7)
|
13
|
+
public_suffix (>= 2.0.2, < 7.0)
|
12
14
|
ansi (1.5.0)
|
13
15
|
ast (2.4.2)
|
14
|
-
|
15
|
-
bigdecimal (3.1.7)
|
16
|
+
bigdecimal (3.1.8)
|
16
17
|
crack (1.0.0)
|
17
18
|
bigdecimal
|
18
19
|
rexml
|
19
20
|
diff-lcs (1.5.1)
|
20
|
-
docile (1.4.
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
21
|
+
docile (1.4.1)
|
22
|
+
faraday (2.12.0)
|
23
|
+
faraday-net_http (>= 2.0, < 3.4)
|
24
|
+
json
|
25
|
+
logger
|
26
|
+
faraday-net_http (3.3.0)
|
27
|
+
net-http
|
28
|
+
faraday-retry (2.2.1)
|
29
|
+
faraday (~> 2.0)
|
26
30
|
gem-release (2.2.2)
|
27
|
-
hashdiff (1.1.
|
28
|
-
|
29
|
-
addressable (~> 2.8)
|
30
|
-
base64 (~> 0.1)
|
31
|
-
http-cookie (~> 1.0)
|
32
|
-
http-form_data (~> 2.2)
|
33
|
-
llhttp-ffi (~> 0.5.0)
|
34
|
-
http-cookie (1.0.5)
|
35
|
-
domain_name (~> 0.5)
|
36
|
-
http-form_data (2.3.0)
|
37
|
-
json (2.7.2)
|
31
|
+
hashdiff (1.1.2)
|
32
|
+
json (2.8.1)
|
38
33
|
language_server-protocol (3.17.0.3)
|
39
34
|
lint_roller (1.1.0)
|
40
|
-
|
41
|
-
ffi-compiler (~> 1.0)
|
42
|
-
rake (~> 13.0)
|
35
|
+
logger (1.6.1)
|
43
36
|
multi_json (1.15.0)
|
44
|
-
|
37
|
+
net-http (0.5.0)
|
38
|
+
uri
|
39
|
+
parallel (1.26.3)
|
45
40
|
parse_gemspec (1.0.0)
|
46
41
|
parse_gemspec-cli (1.0.0)
|
47
42
|
multi_json
|
48
43
|
parse_gemspec
|
49
44
|
thor
|
50
|
-
parser (3.3.0
|
45
|
+
parser (3.3.6.0)
|
51
46
|
ast (~> 2.4.1)
|
52
47
|
racc
|
53
|
-
public_suffix (
|
54
|
-
racc (1.
|
48
|
+
public_suffix (6.0.1)
|
49
|
+
racc (1.8.1)
|
55
50
|
rainbow (3.1.1)
|
56
51
|
rake (13.2.1)
|
57
|
-
regexp_parser (2.9.
|
58
|
-
rexml (3.
|
52
|
+
regexp_parser (2.9.2)
|
53
|
+
rexml (3.3.9)
|
59
54
|
rspec (3.13.0)
|
60
55
|
rspec-core (~> 3.13.0)
|
61
56
|
rspec-expectations (~> 3.13.0)
|
62
57
|
rspec-mocks (~> 3.13.0)
|
63
|
-
rspec-core (3.13.
|
58
|
+
rspec-core (3.13.2)
|
64
59
|
rspec-support (~> 3.13.0)
|
65
|
-
rspec-expectations (3.13.
|
60
|
+
rspec-expectations (3.13.3)
|
66
61
|
diff-lcs (>= 1.2.0, < 2.0)
|
67
62
|
rspec-support (~> 3.13.0)
|
68
|
-
rspec-mocks (3.13.
|
63
|
+
rspec-mocks (3.13.2)
|
69
64
|
diff-lcs (>= 1.2.0, < 2.0)
|
70
65
|
rspec-support (~> 3.13.0)
|
71
66
|
rspec-support (3.13.1)
|
72
|
-
rubocop (1.
|
67
|
+
rubocop (1.66.1)
|
73
68
|
json (~> 2.3)
|
74
69
|
language_server-protocol (>= 3.17.0)
|
75
70
|
parallel (~> 1.10)
|
76
71
|
parser (>= 3.3.0.2)
|
77
72
|
rainbow (>= 2.2.2, < 4.0)
|
78
|
-
regexp_parser (>=
|
79
|
-
|
80
|
-
rubocop-ast (>= 1.31.1, < 2.0)
|
73
|
+
regexp_parser (>= 2.4, < 3.0)
|
74
|
+
rubocop-ast (>= 1.32.2, < 2.0)
|
81
75
|
ruby-progressbar (~> 1.7)
|
82
76
|
unicode-display_width (>= 2.4.0, < 3.0)
|
83
|
-
rubocop-ast (1.
|
84
|
-
parser (>= 3.3.0
|
85
|
-
rubocop-performance (1.
|
77
|
+
rubocop-ast (1.35.0)
|
78
|
+
parser (>= 3.3.1.0)
|
79
|
+
rubocop-performance (1.22.1)
|
86
80
|
rubocop (>= 1.48.1, < 2.0)
|
87
|
-
rubocop-ast (>= 1.
|
81
|
+
rubocop-ast (>= 1.31.1, < 2.0)
|
88
82
|
ruby-progressbar (1.13.0)
|
89
83
|
simplecov (0.22.0)
|
90
84
|
docile (~> 1.1)
|
91
85
|
simplecov-html (~> 0.11)
|
92
86
|
simplecov_json_formatter (~> 0.1)
|
93
|
-
simplecov-console (0.9.
|
87
|
+
simplecov-console (0.9.2)
|
94
88
|
ansi
|
95
89
|
simplecov
|
96
90
|
terminal-table
|
97
|
-
simplecov-html (0.
|
91
|
+
simplecov-html (0.13.1)
|
98
92
|
simplecov_json_formatter (0.1.4)
|
99
|
-
standard (1.
|
93
|
+
standard (1.41.1)
|
100
94
|
language_server-protocol (~> 3.17.0.2)
|
101
95
|
lint_roller (~> 1.0)
|
102
|
-
rubocop (~> 1.
|
96
|
+
rubocop (~> 1.66.0)
|
103
97
|
standard-custom (~> 1.0.0)
|
104
|
-
standard-performance (~> 1.
|
98
|
+
standard-performance (~> 1.5)
|
105
99
|
standard-custom (1.0.2)
|
106
100
|
lint_roller (~> 1.0)
|
107
101
|
rubocop (~> 1.50)
|
108
|
-
standard-performance (1.
|
102
|
+
standard-performance (1.5.0)
|
109
103
|
lint_roller (~> 1.1)
|
110
|
-
rubocop-performance (~> 1.
|
104
|
+
rubocop-performance (~> 1.22.0)
|
105
|
+
svix (1.40.0)
|
111
106
|
terminal-table (3.0.2)
|
112
107
|
unicode-display_width (>= 1.1.1, < 3)
|
113
|
-
thor (1.3.
|
114
|
-
unicode-display_width (2.
|
108
|
+
thor (1.3.2)
|
109
|
+
unicode-display_width (2.6.0)
|
110
|
+
uri (1.0.1)
|
115
111
|
webmock (3.0.1)
|
116
112
|
addressable (>= 2.3.6)
|
117
113
|
crack (>= 0.3.2)
|
@@ -134,4 +130,4 @@ DEPENDENCIES
|
|
134
130
|
webmock (~> 3.0.0)
|
135
131
|
|
136
132
|
BUNDLED WITH
|
137
|
-
2.
|
133
|
+
2.5.16
|
data/README.md
CHANGED
@@ -7,17 +7,337 @@ SDK for the Seam API written in Ruby.
|
|
7
7
|
|
8
8
|
## Description
|
9
9
|
|
10
|
-
|
10
|
+
[Seam](https://seam.co) makes it easy to integrate IoT devices with your applications.
|
11
|
+
This is an official SDK for the Seam API.
|
12
|
+
Please refer to the official [Seam Docs](https://docs.seam.co/latest/) to get started.
|
13
|
+
|
14
|
+
Parts of this SDK are generated from always up-to-date type information
|
15
|
+
provided by [@seamapi/types](https://github.com/seamapi/types/).
|
16
|
+
This ensures all API methods, request shapes, and response shapes are
|
17
|
+
accurate and fully typed.
|
18
|
+
|
19
|
+
<!-- toc -->
|
20
|
+
|
21
|
+
- [Installation](#installation)
|
22
|
+
- [Usage](#usage)
|
23
|
+
- [Examples](#examples)
|
24
|
+
- [List devices](#list-devices)
|
25
|
+
- [Unlock a door](#unlock-a-door)
|
26
|
+
- [Authentication Method](#authentication-method)
|
27
|
+
- [API Key](#api-key)
|
28
|
+
- [Personal Access Token](#personal-access-token)
|
29
|
+
- [Action Attempts](#action-attempts)
|
30
|
+
- [Interacting with Multiple Workspaces](#interacting-with-multiple-workspaces)
|
31
|
+
- [Webhooks](#webhooks)
|
32
|
+
- [Advanced Usage](#advanced-usage)
|
33
|
+
- [Additional Options](#additional-options)
|
34
|
+
- [Setting the endpoint](#setting-the-endpoint)
|
35
|
+
- [Configuring the Faraday Client](#configuring-the-faraday-client)
|
36
|
+
- [Using the Faraday Client](#using-the-faraday-client)
|
37
|
+
- [Overriding the Client](#overriding-the-client)
|
38
|
+
- [Development and Testing](#development-and-testing)
|
39
|
+
- [Quickstart](#quickstart)
|
40
|
+
- [Source code](#source-code)
|
41
|
+
- [Requirements](#requirements)
|
42
|
+
- [Publishing](#publishing)
|
43
|
+
- [Automatic](#automatic)
|
44
|
+
- [Manual](#manual)
|
45
|
+
- [GitHub Actions](#github-actions)
|
46
|
+
- [Secrets for Optional GitHub Actions](#secrets-for-optional-github-actions)
|
47
|
+
- [Contributing](#contributing)
|
48
|
+
- [License](#license)
|
49
|
+
- [Warranty](#warranty)
|
50
|
+
|
51
|
+
<!-- tocstop -->
|
11
52
|
|
12
53
|
## Installation
|
13
54
|
|
14
|
-
Add this as a dependency to your project using [Bundler] with
|
55
|
+
Add this as a dependency to your project using [Bundler] with:
|
15
56
|
|
16
57
|
```
|
17
58
|
$ bundle add seam
|
18
59
|
```
|
19
60
|
|
20
|
-
[
|
61
|
+
[Bundler]: https://bundler.io/
|
62
|
+
|
63
|
+
## Usage
|
64
|
+
|
65
|
+
### Examples
|
66
|
+
|
67
|
+
> [!NOTE]
|
68
|
+
> These examples assume `SEAM_API_KEY` is set in your environment.
|
69
|
+
|
70
|
+
#### List devices
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
require "seam"
|
74
|
+
|
75
|
+
seam = Seam.new
|
76
|
+
devices = seam.devices.list
|
77
|
+
```
|
78
|
+
|
79
|
+
#### Unlock a door
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
require "seam"
|
83
|
+
|
84
|
+
seam = Seam.new
|
85
|
+
lock = seam.locks.get(name: "Front Door")
|
86
|
+
seam.locks.unlock_door(device_id: lock.device_id)
|
87
|
+
```
|
88
|
+
|
89
|
+
### Authentication Method
|
90
|
+
|
91
|
+
The SDK supports API key and personal access token authentication mechanisms.
|
92
|
+
Authentication may be configured by passing the corresponding options directly to the `Seam` constructor, or with the more ergonomic static factory methods.
|
93
|
+
|
94
|
+
#### API Key
|
95
|
+
|
96
|
+
An API key is scoped to a single workspace and should only be used on the server.
|
97
|
+
Obtain one from the Seam Console.
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
# Set the `SEAM_API_KEY` environment variable
|
101
|
+
seam = Seam.new
|
102
|
+
|
103
|
+
# Pass as a keyword argument to the constructor
|
104
|
+
seam = Seam.new(api_key: "your-api-key")
|
105
|
+
|
106
|
+
# Use the factory method
|
107
|
+
seam = Seam.from_api_key("your-api-key")
|
108
|
+
```
|
109
|
+
|
110
|
+
#### Personal Access Token
|
111
|
+
|
112
|
+
A Personal Access Token is scoped to a Seam Console user.
|
113
|
+
Obtain one from the Seam Console.
|
114
|
+
A workspace ID must be provided when using this method and all requests will be scoped to that workspace.
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
# Pass as an option to the constructor
|
118
|
+
seam = Seam.new(
|
119
|
+
personal_access_token: "your-personal-access-token",
|
120
|
+
workspace_id: "your-workspace-id"
|
121
|
+
)
|
122
|
+
|
123
|
+
# Use the factory method
|
124
|
+
seam = Seam.from_personal_access_token(
|
125
|
+
"your-personal-access-token",
|
126
|
+
"your-workspace-id"
|
127
|
+
)
|
128
|
+
```
|
129
|
+
|
130
|
+
### Action Attempts
|
131
|
+
|
132
|
+
Some asynchronous operations, e.g., unlocking a door, return an
|
133
|
+
[action attempt](https://docs.seam.co/latest/core-concepts/action-attempts).
|
134
|
+
Seam tracks the progress of the requested operation and updates the action attempt
|
135
|
+
when it succeeds or fails.
|
136
|
+
|
137
|
+
To make working with action attempts more convenient for applications,
|
138
|
+
this library provides the `wait_for_action_attempt` option and enables it by default.
|
139
|
+
|
140
|
+
When the `wait_for_action_attempt` option is enabled, the SDK:
|
141
|
+
|
142
|
+
- Polls the action attempt up to the `timeout`
|
143
|
+
at the `polling_interval` (both in seconds).
|
144
|
+
- Resolves with a fresh copy of the successful action attempt.
|
145
|
+
- Raises a `Seam::ActionAttemptFailedError` if the action attempt is unsuccessful.
|
146
|
+
- Raises a `Seam::ActionAttemptTimeoutError` if the action attempt is still pending when the `timeout` is reached.
|
147
|
+
- Both errors expose an `action_attempt` property.
|
148
|
+
|
149
|
+
If you already have an action attempt ID
|
150
|
+
and want to wait for it to resolve, simply use:
|
151
|
+
|
152
|
+
```ruby
|
153
|
+
seam.action_attempts.get(action_attempt_id: action_attempt_id)
|
154
|
+
```
|
155
|
+
|
156
|
+
Or, to get the current state of an action attempt by ID without waiting:
|
157
|
+
|
158
|
+
```ruby
|
159
|
+
seam.action_attempts.get(
|
160
|
+
action_attempt_id: action_attempt_id,
|
161
|
+
wait_for_action_attempt: false
|
162
|
+
)
|
163
|
+
```
|
164
|
+
|
165
|
+
To disable this behavior, set the default option for the client:
|
166
|
+
|
167
|
+
```ruby
|
168
|
+
seam = Seam.new(
|
169
|
+
api_key: "your-api-key",
|
170
|
+
wait_for_action_attempt: false
|
171
|
+
)
|
172
|
+
|
173
|
+
seam.locks.unlock_door(device_id: device_id)
|
174
|
+
```
|
175
|
+
|
176
|
+
or the behavior may be configured per-request:
|
177
|
+
|
178
|
+
```ruby
|
179
|
+
seam.locks.unlock_door(
|
180
|
+
device_id: device_id,
|
181
|
+
wait_for_action_attempt: false
|
182
|
+
)
|
183
|
+
```
|
184
|
+
|
185
|
+
The `polling_interval` and `timeout` may be configured for the client or per-request.
|
186
|
+
For example:
|
187
|
+
|
188
|
+
```ruby
|
189
|
+
require "seam"
|
190
|
+
|
191
|
+
seam = Seam.new("your-api-key")
|
192
|
+
|
193
|
+
locks = seam.locks.list
|
194
|
+
|
195
|
+
if locks.empty?
|
196
|
+
raise "No locks in this workspace"
|
197
|
+
end
|
198
|
+
|
199
|
+
lock = locks.first
|
200
|
+
|
201
|
+
begin
|
202
|
+
seam.locks.unlock_door(
|
203
|
+
device_id: lock.device_id,
|
204
|
+
wait_for_action_attempt: {
|
205
|
+
timeout: 5.0,
|
206
|
+
polling_interval: 1.0
|
207
|
+
}
|
208
|
+
)
|
209
|
+
|
210
|
+
puts "Door unlocked"
|
211
|
+
rescue Seam::ActionAttemptFailedError
|
212
|
+
puts "Could not unlock the door"
|
213
|
+
rescue Seam::ActionAttemptTimeoutError
|
214
|
+
puts "Door took too long to unlock"
|
215
|
+
end
|
216
|
+
```
|
217
|
+
|
218
|
+
### Interacting with Multiple Workspaces
|
219
|
+
|
220
|
+
Some Seam API endpoints interact with multiple workspaces. The `Seam::Http::SeamMultiWorkspace` client is not bound to a specific workspace and may use those endpoints with a personal access token authentication method.
|
221
|
+
|
222
|
+
A Personal Access Token is scoped to a Seam Console user. Obtain one from the Seam Console.
|
223
|
+
|
224
|
+
```ruby
|
225
|
+
# Pass as an option to the constructor
|
226
|
+
seam = Seam::Http::SeamMultiWorkspace.new(personal_access_token: "your-personal-access-token")
|
227
|
+
|
228
|
+
# Use the factory method
|
229
|
+
seam = Seam::Http::SeamMultiWorkspace.from_personal_access_token("your-personal-access-token")
|
230
|
+
|
231
|
+
# List workspaces authorized for this Personal Access Token
|
232
|
+
workspaces = seam.workspaces.list
|
233
|
+
```
|
234
|
+
|
235
|
+
### Webhooks
|
236
|
+
|
237
|
+
The Seam API implements webhooks using [Svix](https://www.svix.com).This SDK exports a thin wrapper `Seam::Webhook` around the svix package.
|
238
|
+
Use it to parse and validate Seam webhook events.
|
239
|
+
|
240
|
+
> [!TIP]
|
241
|
+
> This example is for [Sinatra](https://sinatrarb.com/), see the [Svix docs for more examples in specific frameworks](https://docs.svix.com/receiving/verifying-payloads/how).
|
242
|
+
|
243
|
+
```ruby
|
244
|
+
require "sinatra"
|
245
|
+
require "seam"
|
246
|
+
|
247
|
+
webhook = Seam::Webhook.new(ENV["SEAM_WEBHOOK_SECRET"])
|
248
|
+
|
249
|
+
post "/webhook" do
|
250
|
+
begin
|
251
|
+
headers = {
|
252
|
+
"svix-id" => request.env["HTTP_SVIX_ID"],
|
253
|
+
"svix-signature" => request.env["HTTP_SVIX_SIGNATURE"],
|
254
|
+
"svix-timestamp" => request.env["HTTP_SVIX_TIMESTAMP"]
|
255
|
+
}
|
256
|
+
data = webhook.verify(request.body.read, headers)
|
257
|
+
rescue Seam::WebhookVerificationError
|
258
|
+
halt 400, "Bad Request"
|
259
|
+
end
|
260
|
+
|
261
|
+
begin
|
262
|
+
store_event(data)
|
263
|
+
rescue
|
264
|
+
halt 500, "Internal Server Error"
|
265
|
+
end
|
266
|
+
|
267
|
+
204
|
268
|
+
end
|
269
|
+
|
270
|
+
def store_event(data)
|
271
|
+
puts data
|
272
|
+
end
|
273
|
+
```
|
274
|
+
|
275
|
+
### Advanced Usage
|
276
|
+
|
277
|
+
#### Additional Options
|
278
|
+
|
279
|
+
In addition to the various authentication options,
|
280
|
+
the constructor takes some advanced options that affect behavior.
|
281
|
+
|
282
|
+
```ruby
|
283
|
+
seam = Seam.new(
|
284
|
+
api_key: "your-api-key",
|
285
|
+
endpoint: "https://example.com",
|
286
|
+
faraday_options: {},
|
287
|
+
faraday_retry_options: {}
|
288
|
+
)
|
289
|
+
```
|
290
|
+
|
291
|
+
When using the static factory methods,
|
292
|
+
these options may be passed in as keyword arguments.
|
293
|
+
|
294
|
+
```ruby
|
295
|
+
seam = Seam.from_api_key("some-api-key",
|
296
|
+
endpoint: "https://example.com",
|
297
|
+
faraday_options: {},
|
298
|
+
faraday_retry_options: {})
|
299
|
+
```
|
300
|
+
|
301
|
+
#### Setting the endpoint
|
302
|
+
|
303
|
+
Some contexts may need to override the API endpoint,
|
304
|
+
e.g., testing or proxy setups. This option corresponds to the [Faraday](https://lostisland.github.io/faraday/#/) `url` setting.
|
305
|
+
|
306
|
+
Either pass the `endpoint` option, or set the `SEAM_ENDPOINT` environment variable.
|
307
|
+
|
308
|
+
#### Configuring the Faraday Client
|
309
|
+
|
310
|
+
The Faraday client and retry behavior may be configured with custom initiation options
|
311
|
+
via [`faraday_option`][faraday_option] and [`faraday_retry_option`][faraday_retry_option].
|
312
|
+
|
313
|
+
[faraday_option]: https://lostisland.github.io/faraday/#/customization/connection-options?id=connection-options
|
314
|
+
[faraday_retry_option]: https://github.com/lostisland/faraday-retry
|
315
|
+
|
316
|
+
#### Using the Faraday Client
|
317
|
+
|
318
|
+
The Faraday client is exposed and may be used or configured directly:
|
319
|
+
|
320
|
+
```ruby
|
321
|
+
require "seam"
|
322
|
+
require "faraday"
|
323
|
+
|
324
|
+
class MyMiddleware < Faraday::Middleware
|
325
|
+
def on_complete(env)
|
326
|
+
puts env.response.inspect
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
seam = Seam.new
|
331
|
+
|
332
|
+
seam.client.builder.use MyMiddleware
|
333
|
+
|
334
|
+
devices = seam.client.get("/devices/list").body["devices"]
|
335
|
+
```
|
336
|
+
|
337
|
+
#### Overriding the Client
|
338
|
+
|
339
|
+
A Faraday compatible client may be provided to create a `Seam` instance.
|
340
|
+
This API is used internally and is not directly supported.
|
21
341
|
|
22
342
|
## Development and Testing
|
23
343
|
|
data/Rakefile
CHANGED
data/lib/seam/auth.rb
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "options"
|
4
|
+
require_relative "token"
|
5
|
+
|
6
|
+
module Seam
|
7
|
+
module Http
|
8
|
+
module Auth
|
9
|
+
class SeamInvalidTokenError < StandardError
|
10
|
+
def initialize(message)
|
11
|
+
super("Seam received an invalid token: #{message}")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.get_auth_headers(api_key: nil, personal_access_token: nil, workspace_id: nil)
|
16
|
+
if Http::Options.seam_http_options_with_api_key?(api_key: api_key, personal_access_token: personal_access_token)
|
17
|
+
return get_auth_headers_for_api_key(api_key)
|
18
|
+
end
|
19
|
+
|
20
|
+
if Http::Options.seam_http_options_with_personal_access_token?(personal_access_token: personal_access_token, api_key: api_key,
|
21
|
+
workspace_id: workspace_id)
|
22
|
+
return get_auth_headers_for_personal_access_token(personal_access_token, workspace_id)
|
23
|
+
end
|
24
|
+
|
25
|
+
raise Http::Options::SeamInvalidOptionsError.new(
|
26
|
+
"Must specify an api_key or personal_access_token. " \
|
27
|
+
"Attempted reading configuration from the environment, " \
|
28
|
+
"but the environment variable SEAM_API_KEY is not set."
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.get_auth_headers_for_api_key(api_key)
|
33
|
+
if Auth.client_session_token?(api_key)
|
34
|
+
raise SeamInvalidTokenError.new(
|
35
|
+
"A Client Session Token cannot be used as an api_key"
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
raise SeamInvalidTokenError.new("A JWT cannot be used as an api_key") if Auth.jwt?(api_key)
|
40
|
+
|
41
|
+
raise SeamInvalidTokenError.new("An Access Token cannot be used as an api_key") if Auth.access_token?(api_key)
|
42
|
+
|
43
|
+
if Auth.publishable_key?(api_key)
|
44
|
+
raise SeamInvalidTokenError.new(
|
45
|
+
"A Publishable Key cannot be used as an api_key"
|
46
|
+
)
|
47
|
+
end
|
48
|
+
|
49
|
+
unless Auth.seam_token?(api_key)
|
50
|
+
raise SeamInvalidTokenError.new(
|
51
|
+
"Unknown or invalid api_key format, expected token to start with #{Auth::TOKEN_PREFIX}"
|
52
|
+
)
|
53
|
+
end
|
54
|
+
|
55
|
+
{"authorization" => "Bearer #{api_key}"}
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.get_auth_headers_for_personal_access_token(personal_access_token, workspace_id)
|
59
|
+
if Auth.jwt?(personal_access_token)
|
60
|
+
raise SeamInvalidTokenError.new(
|
61
|
+
"A JWT cannot be used as a personal_access_token"
|
62
|
+
)
|
63
|
+
end
|
64
|
+
|
65
|
+
if Auth.client_session_token?(personal_access_token)
|
66
|
+
raise SeamInvalidTokenError.new(
|
67
|
+
"A Client Session Token cannot be used as a personal_access_token"
|
68
|
+
)
|
69
|
+
end
|
70
|
+
|
71
|
+
if Auth.publishable_key?(personal_access_token)
|
72
|
+
raise SeamInvalidTokenError.new(
|
73
|
+
"A Publishable Key cannot be used as a personal_access_token"
|
74
|
+
)
|
75
|
+
end
|
76
|
+
|
77
|
+
unless Auth.access_token?(personal_access_token)
|
78
|
+
raise SeamInvalidTokenError.new(
|
79
|
+
"Unknown or invalid personal_access_token format, expected token to start with #{Auth::ACCESS_TOKEN_PREFIX}"
|
80
|
+
)
|
81
|
+
end
|
82
|
+
|
83
|
+
{
|
84
|
+
"authorization" => "Bearer #{personal_access_token}",
|
85
|
+
"seam-workspace" => workspace_id
|
86
|
+
}
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.get_auth_headers_for_multi_workspace_personal_access_token(personal_access_token)
|
90
|
+
if Auth.jwt?(personal_access_token)
|
91
|
+
raise SeamInvalidTokenError.new(
|
92
|
+
"A JWT cannot be used as a personal_access_token"
|
93
|
+
)
|
94
|
+
end
|
95
|
+
|
96
|
+
if Auth.client_session_token?(personal_access_token)
|
97
|
+
raise SeamInvalidTokenError.new(
|
98
|
+
"A Client Session Token cannot be used as a personal_access_token"
|
99
|
+
)
|
100
|
+
end
|
101
|
+
|
102
|
+
if Auth.publishable_key?(personal_access_token)
|
103
|
+
raise SeamInvalidTokenError.new(
|
104
|
+
"A Publishable Key cannot be used as a personal_access_token"
|
105
|
+
)
|
106
|
+
end
|
107
|
+
|
108
|
+
unless Auth.access_token?(personal_access_token)
|
109
|
+
raise SeamInvalidTokenError.new(
|
110
|
+
"Unknown or invalid personal_access_token format, expected token to start with #{Auth::ACCESS_TOKEN_PREFIX}"
|
111
|
+
)
|
112
|
+
end
|
113
|
+
|
114
|
+
{"authorization" => "Bearer #{personal_access_token}"}
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|