attio 0.2.0 → 0.3.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.
@@ -0,0 +1,183 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Attio
4
+ module Resources
5
+ # Deals resource for managing sales opportunities
6
+ #
7
+ # @example List all deals
8
+ # client.deals.list
9
+ #
10
+ # @example Create a new deal
11
+ # client.deals.create(
12
+ # data: {
13
+ # name: "Enterprise Contract",
14
+ # value: 50000,
15
+ # stage_id: "stage_123",
16
+ # company_id: "company_456"
17
+ # }
18
+ # )
19
+ #
20
+ # @example Update deal stage
21
+ # client.deals.update_stage(id: "deal_123", stage_id: "stage_won")
22
+ class Deals < Base
23
+ # List all deals
24
+ #
25
+ # @param params [Hash] Optional query parameters
26
+ # @option params [Hash] :filter Filter conditions
27
+ # @option params [Array<Hash>] :sorts Sort criteria
28
+ # @option params [Integer] :limit Maximum number of results
29
+ # @option params [String] :offset Pagination offset
30
+ # @return [Hash] The API response
31
+ def list(params = {})
32
+ request(:get, "objects/deals/records", params)
33
+ end
34
+
35
+ # Get a specific deal
36
+ #
37
+ # @param id [String] The deal ID
38
+ # @return [Hash] The deal data
39
+ def get(id:)
40
+ validate_id!(id, "Deal")
41
+ request(:get, "objects/deals/records/#{id}")
42
+ end
43
+
44
+ # Create a new deal
45
+ #
46
+ # @param data [Hash] The deal data
47
+ # @option data [String] :name The deal name (required)
48
+ # @option data [Float] :value The deal value
49
+ # @option data [String] :stage_id The stage ID
50
+ # @option data [String] :company_id Associated company ID
51
+ # @option data [String] :owner_id The owner user ID
52
+ # @option data [Date] :close_date Expected close date
53
+ # @option data [String] :currency Currency code (USD, EUR, etc.)
54
+ # @option data [Float] :probability Win probability (0-100)
55
+ # @return [Hash] The created deal
56
+ def create(data:)
57
+ validate_required_hash!(data, "Data")
58
+ validate_required_string!(data[:name], "Deal name")
59
+
60
+ request(:post, "objects/deals/records", { data: data })
61
+ end
62
+
63
+ # Update a deal
64
+ #
65
+ # @param id [String] The deal ID to update
66
+ # @param data [Hash] The data to update
67
+ # @return [Hash] The updated deal
68
+ def update(id:, data:)
69
+ validate_id!(id, "Deal")
70
+ validate_required_hash!(data, "Data")
71
+
72
+ request(:patch, "objects/deals/records/#{id}", { data: data })
73
+ end
74
+
75
+ # Delete a deal
76
+ #
77
+ # @param id [String] The deal ID to delete
78
+ # @return [Hash] Confirmation of deletion
79
+ def delete(id:)
80
+ validate_id!(id, "Deal")
81
+ request(:delete, "objects/deals/records/#{id}")
82
+ end
83
+
84
+ # Update a deal's stage
85
+ #
86
+ # @param id [String] The deal ID
87
+ # @param stage_id [String] The new stage ID
88
+ # @return [Hash] The updated deal
89
+ def update_stage(id:, stage_id:)
90
+ validate_id!(id, "Deal")
91
+ validate_required_string!(stage_id, "Stage")
92
+
93
+ update(id: id, data: { stage_id: stage_id })
94
+ end
95
+
96
+ # Mark a deal as won
97
+ #
98
+ # @param id [String] The deal ID
99
+ # @param won_date [Date, String] The date the deal was won (defaults to today)
100
+ # @param actual_value [Float] The actual value (optional, defaults to deal value)
101
+ # @return [Hash] The updated deal
102
+ def mark_won(id:, won_date: nil, actual_value: nil)
103
+ validate_id!(id, "Deal")
104
+
105
+ data = { status: "won" }
106
+ data[:won_date] = won_date if won_date
107
+ data[:actual_value] = actual_value if actual_value
108
+
109
+ update(id: id, data: data)
110
+ end
111
+
112
+ # Mark a deal as lost
113
+ #
114
+ # @param id [String] The deal ID
115
+ # @param lost_reason [String] The reason for losing the deal
116
+ # @param lost_date [Date, String] The date the deal was lost (defaults to today)
117
+ # @return [Hash] The updated deal
118
+ def mark_lost(id:, lost_reason: nil, lost_date: nil)
119
+ validate_id!(id, "Deal")
120
+
121
+ data = { status: "lost" }
122
+ data[:lost_reason] = lost_reason if lost_reason
123
+ data[:lost_date] = lost_date if lost_date
124
+
125
+ update(id: id, data: data)
126
+ end
127
+
128
+ # List deals by stage
129
+ #
130
+ # @param stage_id [String] The stage ID to filter by
131
+ # @param params [Hash] Additional query parameters
132
+ # @return [Hash] Deals in the specified stage
133
+ def list_by_stage(stage_id:, params: {})
134
+ validate_required_string!(stage_id, "Stage")
135
+
136
+ filter = { stage_id: { "$eq" => stage_id } }
137
+ merged_params = params.merge(filter: filter)
138
+ list(merged_params)
139
+ end
140
+
141
+ # List deals by company
142
+ #
143
+ # @param company_id [String] The company ID to filter by
144
+ # @param params [Hash] Additional query parameters
145
+ # @return [Hash] Deals for the specified company
146
+ def list_by_company(company_id:, params: {})
147
+ validate_required_string!(company_id, "Company")
148
+
149
+ filter = { company_id: { "$eq" => company_id } }
150
+ merged_params = params.merge(filter: filter)
151
+ list(merged_params)
152
+ end
153
+
154
+ # List deals by owner
155
+ #
156
+ # @param owner_id [String] The owner user ID to filter by
157
+ # @param params [Hash] Additional query parameters
158
+ # @return [Hash] Deals owned by the specified user
159
+ def list_by_owner(owner_id:, params: {})
160
+ validate_required_string!(owner_id, "Owner")
161
+
162
+ filter = { owner_id: { "$eq" => owner_id } }
163
+ merged_params = params.merge(filter: filter)
164
+ list(merged_params)
165
+ end
166
+
167
+ # Calculate pipeline value
168
+ #
169
+ # @param stage_id [String] Optional stage ID to filter by
170
+ # @param owner_id [String] Optional owner ID to filter by
171
+ # @return [Hash] Pipeline statistics including total value, count, and average
172
+ def pipeline_value(stage_id: nil, owner_id: nil)
173
+ params = { filter: {} }
174
+ params[:filter][:stage_id] = { "$eq" => stage_id } if stage_id
175
+ params[:filter][:owner_id] = { "$eq" => owner_id } if owner_id
176
+
177
+ # This would typically be a specialized endpoint, but we'll use list
178
+ # and let the client calculate the statistics
179
+ list(params)
180
+ end
181
+ end
182
+ end
183
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Attio
4
+ module Resources
5
+ # Meta resource for API metadata and identification
6
+ #
7
+ # @example Identify the current API key
8
+ # client.meta.identify
9
+ # # => { "workspace" => { "id" => "...", "name" => "..." }, "user" => { ... } }
10
+ #
11
+ # @example Get API status
12
+ # client.meta.status
13
+ # # => { "status" => "operational", "version" => "v2" }
14
+ class Meta < Base
15
+ # Identify the current API key and get workspace/user information
16
+ #
17
+ # @return [Hash] Information about the authenticated workspace and user
18
+ def identify
19
+ request(:get, "meta/identify")
20
+ end
21
+
22
+ # Get API status and version information
23
+ #
24
+ # @return [Hash] API status and version details
25
+ def status
26
+ request(:get, "meta/status")
27
+ end
28
+
29
+ # Get rate limit information for the current API key
30
+ #
31
+ # @return [Hash] Current rate limit status
32
+ def rate_limits
33
+ request(:get, "meta/rate_limits")
34
+ end
35
+
36
+ # Get workspace configuration and settings
37
+ #
38
+ # @return [Hash] Workspace configuration details
39
+ def workspace_config
40
+ request(:get, "meta/workspace_config")
41
+ end
42
+
43
+ # Validate an API key without making changes
44
+ #
45
+ # @return [Hash] Validation result with key permissions
46
+ def validate_key
47
+ request(:post, "meta/validate", {})
48
+ end
49
+
50
+ # Get available API endpoints and their documentation
51
+ #
52
+ # @return [Hash] List of available endpoints with descriptions
53
+ def endpoints
54
+ request(:get, "meta/endpoints")
55
+ end
56
+
57
+ # Get workspace usage statistics
58
+ #
59
+ # @return [Hash] Usage statistics including record counts, API calls, etc.
60
+ def usage_stats
61
+ request(:get, "meta/usage")
62
+ end
63
+
64
+ # Get feature flags and capabilities for the workspace
65
+ #
66
+ # @return [Hash] Enabled features and capabilities
67
+ def features
68
+ request(:get, "meta/features")
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Attio
4
+ module Resources
5
+ # Workspace Members resource for managing workspace member access
6
+ #
7
+ # @example List all workspace members
8
+ # client.workspace_members.list
9
+ #
10
+ # @example Get a specific member
11
+ # client.workspace_members.get(member_id: "user_123")
12
+ #
13
+ # @example Invite a new member
14
+ # client.workspace_members.invite(
15
+ # email: "new.member@example.com",
16
+ # role: "member"
17
+ # )
18
+ class WorkspaceMembers < Base
19
+ # List all workspace members
20
+ #
21
+ # @param params [Hash] Optional query parameters
22
+ # @option params [Integer] :limit Maximum number of results
23
+ # @option params [String] :offset Pagination offset
24
+ # @return [Hash] The API response
25
+ def list(params = {})
26
+ request(:get, "workspace_members", params)
27
+ end
28
+
29
+ # Get a specific workspace member
30
+ #
31
+ # @param member_id [String] The member ID
32
+ # @return [Hash] The member data
33
+ def get(member_id:)
34
+ validate_id!(member_id, "Member")
35
+ request(:get, "workspace_members/#{member_id}")
36
+ end
37
+
38
+ # Invite a new member to the workspace
39
+ #
40
+ # @param email [String] The email address to invite
41
+ # @param role [String] The role to assign (admin, member, guest)
42
+ # @param data [Hash] Additional member data
43
+ # @return [Hash] The created invitation
44
+ def invite(email:, role: "member", data: {})
45
+ validate_required_string!(email, "Email")
46
+ validate_required_string!(role, "Role")
47
+
48
+ raise ArgumentError, "Role must be one of: admin, member, guest" unless %w[admin member guest].include?(role)
49
+
50
+ body = data.merge(email: email, role: role)
51
+ request(:post, "workspace_members/invitations", body)
52
+ end
53
+
54
+ # Update a workspace member's role or permissions
55
+ #
56
+ # @param member_id [String] The member ID to update
57
+ # @param data [Hash] The data to update
58
+ # @option data [String] :role The new role
59
+ # @option data [Hash] :permissions Custom permissions
60
+ # @return [Hash] The updated member
61
+ def update(member_id:, data:)
62
+ validate_id!(member_id, "Member")
63
+ validate_required_hash!(data, "Data")
64
+
65
+ request(:patch, "workspace_members/#{member_id}", data)
66
+ end
67
+
68
+ # Remove a member from the workspace
69
+ #
70
+ # @param member_id [String] The member ID to remove
71
+ # @return [Hash] Confirmation of removal
72
+ def remove(member_id:)
73
+ validate_id!(member_id, "Member")
74
+ request(:delete, "workspace_members/#{member_id}")
75
+ end
76
+
77
+ # Accept a workspace invitation
78
+ #
79
+ # @param invitation_token [String] The invitation token
80
+ # @return [Hash] The workspace member data
81
+ def accept_invitation(invitation_token:)
82
+ validate_required_string!(invitation_token, "Invitation token")
83
+ request(:post, "workspace_members/invitations/#{invitation_token}/accept")
84
+ end
85
+
86
+ # Resend an invitation
87
+ #
88
+ # @param member_id [String] The member ID with pending invitation
89
+ # @return [Hash] Confirmation of resent invitation
90
+ def resend_invitation(member_id:)
91
+ validate_id!(member_id, "Member")
92
+ request(:post, "workspace_members/#{member_id}/resend_invitation")
93
+ end
94
+
95
+ # Get current member (self)
96
+ #
97
+ # @return [Hash] The current authenticated member's data
98
+ def me
99
+ request(:get, "workspace_members/me")
100
+ end
101
+ end
102
+ end
103
+ end
data/lib/attio/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Attio
4
- VERSION = "0.2.0"
4
+ VERSION = "0.3.0"
5
5
  end
data/lib/attio.rb CHANGED
@@ -18,6 +18,11 @@ require "attio/resources/notes"
18
18
  require "attio/resources/tasks"
19
19
  require "attio/resources/comments"
20
20
  require "attio/resources/threads"
21
+ require "attio/resources/workspace_members"
22
+ require "attio/resources/deals"
23
+ require "attio/resources/meta"
24
+ require "attio/resources/bulk"
25
+ require "attio/rate_limiter"
21
26
 
22
27
  # The main Attio module provides access to the Attio API client.
23
28
  #
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: attio
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ernest Sim
@@ -48,6 +48,7 @@ files:
48
48
  - ".rubocop.yml"
49
49
  - ".yardopts"
50
50
  - CHANGELOG.md
51
+ - CLAUDE.md
51
52
  - CODE_OF_CONDUCT.md
52
53
  - CONCEPTS.md
53
54
  - CONTRIBUTING.md
@@ -114,16 +115,21 @@ files:
114
115
  - lib/attio/errors.rb
115
116
  - lib/attio/http_client.rb
116
117
  - lib/attio/logger.rb
118
+ - lib/attio/rate_limiter.rb
117
119
  - lib/attio/resources/attributes.rb
118
120
  - lib/attio/resources/base.rb
121
+ - lib/attio/resources/bulk.rb
119
122
  - lib/attio/resources/comments.rb
123
+ - lib/attio/resources/deals.rb
120
124
  - lib/attio/resources/lists.rb
125
+ - lib/attio/resources/meta.rb
121
126
  - lib/attio/resources/notes.rb
122
127
  - lib/attio/resources/objects.rb
123
128
  - lib/attio/resources/records.rb
124
129
  - lib/attio/resources/tasks.rb
125
130
  - lib/attio/resources/threads.rb
126
131
  - lib/attio/resources/users.rb
132
+ - lib/attio/resources/workspace_members.rb
127
133
  - lib/attio/resources/workspaces.rb
128
134
  - lib/attio/retry_handler.rb
129
135
  - lib/attio/version.rb