Skip to content

Commit d8d6eaf

Browse files
committed
feat: Accept the token as the first argument to the client constructors
The other Seam SDKs take the api key as the first positional argument, and the README showed Seam.new("your-api-key"), but every Ruby constructor was keyword-only and raised ArgumentError on that call. Accept the api key as the first argument to Seam.new, Seam::Http.new, and Seam::Http::SingleWorkspace.new, and the personal access token as the first argument to Seam::Http::WithoutWorkspace.new, with every other option still passed by keyword. Giving the token both ways raises the SDK's invalid options error. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SQW83gyXeUG61RDrHEky97
1 parent 11cc541 commit d8d6eaf

7 files changed

Lines changed: 90 additions & 9 deletions

File tree

‎README.md‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ Obtain one from the Seam Console.
114114
# Set the `SEAM_API_KEY` environment variable
115115
seam = Seam.new
116116

117+
# Pass as the first argument to the constructor
118+
seam = Seam.new("your-api-key")
119+
117120
# Pass as a keyword argument to the constructor
118121
seam = Seam.new(api_key: "your-api-key")
119122

@@ -226,7 +229,7 @@ For example:
226229
```ruby
227230
require "seam"
228231

229-
seam = Seam.new(api_key: "your-api-key")
232+
seam = Seam.new("your-api-key")
230233

231234
locks = seam.locks.list
232235

@@ -423,6 +426,9 @@ Obtain one from the Seam Console.
423426
# Set the `SEAM_PERSONAL_ACCESS_TOKEN` environment variable
424427
seam = Seam::Http::WithoutWorkspace.new
425428

429+
# Pass as the first argument to the constructor
430+
seam = Seam::Http::WithoutWorkspace.new("your-personal-access-token")
431+
426432
# Pass as a keyword argument to the constructor
427433
seam = Seam::Http::WithoutWorkspace.new(
428434
personal_access_token: "your-personal-access-token"

‎lib/seam.rb‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
require_relative "seam/wait_for_action_attempt"
1111

1212
module Seam
13-
def self.new(**args)
14-
Seam::Http.new(**args)
13+
def self.new(api_key = nil, **options)
14+
Seam::Http.new(api_key, **options)
1515
end
1616

1717
def self.from_api_key(api_key, endpoint: nil, wait_for_action_attempt: true, timeout: nil, faraday_options: {},

‎lib/seam/http.rb‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55

66
module Seam
77
module Http
8-
def self.new(**args)
9-
Http::SingleWorkspace.new(**args)
8+
def self.new(api_key = nil, **options)
9+
Http::SingleWorkspace.new(api_key, **options)
1010
end
1111

1212
def self.from_api_key(api_key, endpoint: nil, wait_for_action_attempt: true, timeout: nil, faraday_options: {},

‎lib/seam/http_single_workspace.rb‎

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,20 @@ class SingleWorkspace
1919
OPTION_NOT_PROVIDED = Object.new.freeze
2020
private_constant :OPTION_NOT_PROVIDED
2121

22-
def initialize(client: nil, api_key: OPTION_NOT_PROVIDED, personal_access_token: OPTION_NOT_PROVIDED,
23-
workspace_id: OPTION_NOT_PROVIDED, endpoint: OPTION_NOT_PROVIDED,
22+
def initialize(positional_api_key = nil, client: nil, api_key: OPTION_NOT_PROVIDED,
23+
personal_access_token: OPTION_NOT_PROVIDED, workspace_id: OPTION_NOT_PROVIDED, endpoint: OPTION_NOT_PROVIDED,
2424
wait_for_action_attempt: OPTION_NOT_PROVIDED, timeout: OPTION_NOT_PROVIDED,
2525
faraday_options: OPTION_NOT_PROVIDED, faraday_retry_options: OPTION_NOT_PROVIDED)
26+
unless positional_api_key.nil?
27+
unless api_key.equal?(OPTION_NOT_PROVIDED)
28+
raise Http::Options::SeamInvalidOptionsError.new(
29+
"The api_key was given both as a positional argument and as the api_key option"
30+
)
31+
end
32+
33+
api_key = positional_api_key
34+
end
35+
2636
supplied_options = {
2737
api_key: api_key,
2838
personal_access_token: personal_access_token,

‎lib/seam/http_without_workspace.rb‎

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,19 @@ class WithoutWorkspace
1515
OPTION_NOT_PROVIDED = Object.new.freeze
1616
private_constant :OPTION_NOT_PROVIDED
1717

18-
def initialize(client: nil, personal_access_token: OPTION_NOT_PROVIDED, endpoint: OPTION_NOT_PROVIDED,
19-
wait_for_action_attempt: OPTION_NOT_PROVIDED, timeout: OPTION_NOT_PROVIDED,
18+
def initialize(positional_personal_access_token = nil, client: nil, personal_access_token: OPTION_NOT_PROVIDED,
19+
endpoint: OPTION_NOT_PROVIDED, wait_for_action_attempt: OPTION_NOT_PROVIDED, timeout: OPTION_NOT_PROVIDED,
2020
faraday_options: OPTION_NOT_PROVIDED, faraday_retry_options: OPTION_NOT_PROVIDED)
21+
unless positional_personal_access_token.nil?
22+
unless personal_access_token.equal?(OPTION_NOT_PROVIDED)
23+
raise Http::Options::SeamInvalidOptionsError.new(
24+
"The personal_access_token was given both as a positional argument and as the personal_access_token option"
25+
)
26+
end
27+
28+
personal_access_token = positional_personal_access_token
29+
end
30+
2131
supplied_options = {
2232
personal_access_token: personal_access_token,
2333
endpoint: endpoint,

‎spec/seam_client/api_key_spec.rb‎

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,43 @@
2222
expect(device.device_id).to eq(seed["august_device_1"])
2323
end
2424

25+
it "accepts the api key as the first argument" do
26+
seam = Seam.new(seed["seam_apikey1_token"], endpoint: endpoint, wait_for_action_attempt: false)
27+
28+
device = seam.devices.get(device_id: seed["august_device_1"])
29+
30+
expect(device.device_id).to eq(seed["august_device_1"])
31+
expect(seam.defaults.wait_for_action_attempt).to be false
32+
end
33+
34+
it "accepts the api key as the first argument on every constructor" do
35+
[Seam::Http, Seam::Http::SingleWorkspace].each do |klass|
36+
seam = klass.new(seed["seam_apikey1_token"], endpoint: endpoint)
37+
38+
expect(seam.devices.get(device_id: seed["august_device_1"]).device_id).to eq(seed["august_device_1"])
39+
end
40+
end
41+
42+
it "rejects an api key given both as the first argument and as an option" do
43+
expect { Seam.new("seam_some_api_key", api_key: "seam_other_api_key") }.to raise_error(
44+
Seam::Http::Options::SeamInvalidOptionsError,
45+
"Seam received invalid options: The api_key was given both as a positional argument and as the api_key option"
46+
)
47+
end
48+
49+
it "rejects an api key given as the first argument alongside a client" do
50+
expect { Seam.new("seam_some_api_key", client: Faraday.new) }.to raise_error(
51+
Seam::Http::Options::SeamInvalidOptionsError,
52+
/The client option cannot be used with any other option, but received: api_key/
53+
)
54+
end
55+
56+
it "treats a nil first argument as no api key" do
57+
seam = Seam.new(nil, api_key: seed["seam_apikey1_token"], endpoint: endpoint)
58+
59+
expect(seam.devices.get(device_id: seed["august_device_1"]).device_id).to eq(seed["august_device_1"])
60+
end
61+
2562
it "returns resources with parsed attributes" do
2663
devices = seam.devices.list
2764

@@ -44,6 +81,10 @@
4481
Seam.from_api_key("ey")
4582
end.to raise_error(Seam::Http::Auth::SeamInvalidTokenError, /JWT/)
4683

84+
expect do
85+
Seam.new("ey")
86+
end.to raise_error(Seam::Http::Auth::SeamInvalidTokenError, /JWT/)
87+
4788
expect do
4889
Seam.from_api_key("seam_cst_token")
4990
end.to raise_error(Seam::Http::Auth::SeamInvalidTokenError, /Client Session Token/)

‎spec/seam_client/client_without_workspace_spec.rb‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,20 @@
2525
expect(seam.workspaces.list.length).to be > 0
2626
end
2727

28+
it "accepts the personal access token as the first argument" do
29+
seam = described_class.new(seed["seam_at1_token"], endpoint: endpoint)
30+
31+
expect(seam.workspaces.list.length).to be > 0
32+
end
33+
34+
it "rejects a personal access token given both as the first argument and as an option" do
35+
expect { described_class.new("seam_at1_token", personal_access_token: "seam_at2_token") }.to raise_error(
36+
Seam::Http::Options::SeamInvalidOptionsError,
37+
"Seam received invalid options: The personal_access_token was given both as a positional argument " \
38+
"and as the personal_access_token option"
39+
)
40+
end
41+
2842
it "accepts an injected client with request defaults" do
2943
client = Faraday.new
3044

0 commit comments

Comments
 (0)