bundleup-sdk 0.2.1 โ†’ 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 738e70d5c25abac9d2886a2b26a67fbd583d12b248ead60ca7d6036a8c8253f5
4
- data.tar.gz: 6dfa44efa033571dfb22bc82e56f42a7433409046ce4af54f3318971aa029dab
3
+ metadata.gz: 6e385086d7a4207cb36ec82ac134eab03155093407c098488ea40478d62f79d3
4
+ data.tar.gz: ca70fa9281ad486160c66a731e81c0ad56f200ad4e8fccf15e818340e43ea5d6
5
5
  SHA512:
6
- metadata.gz: 8a2ce9989f29d744bf039c8607f8ffa5b71a8bf4ae50805c72bfe0411d86652800d2d43acea32cafbe1d72b93114ae3946a3a28c54c4e0d9365c9c7603482312
7
- data.tar.gz: c257583cb4b1006dc260bd7711b4064670ea97723a92adfd4e6e269f19f41dfef20fbc8ccf3366dd4716b5b13c7e43f0ae5795e046ddb6f27c8c6f035eb5b6c8
6
+ metadata.gz: 9245dcc515bff7307c4073bbc223ce3b2e5bdd8e3ff91dbb83cfdf95437c89bc7e03a7c3b8c9c0db0ca2bb0962df0c9597d127c0a3209d2bcb909e934c787f65
7
+ data.tar.gz: e472e19410d920eb5fbbe6abab03c2af1d1ea05945d7249d1be90c7d47ab7375d67dc503ba2698e57ce7b40ed9fed423400847b3dffefde47b51931c5ee74117
data/README.md CHANGED
@@ -10,6 +10,7 @@ Official Ruby SDK for the [BundleUp](https://bundleup.io) API. Connect to 100+ i
10
10
  - [Installation](#installation)
11
11
  - [Requirements](#requirements)
12
12
  - [Features](#features)
13
+ - [Examples](#examples)
13
14
  - [Quick Start](#quick-start)
14
15
  - [Authentication](#authentication)
15
16
  - [Core Concepts](#core-concepts)
@@ -23,7 +24,6 @@ Official Ruby SDK for the [BundleUp](https://bundleup.io) API. Connect to 100+ i
23
24
  - [Development](#development)
24
25
  - [Contributing](#contributing)
25
26
  - [License](#license)
26
- - [Support](#support)
27
27
 
28
28
  ## Installation
29
29
 
@@ -77,6 +77,15 @@ The BundleUp SDK is tested and supported on:
77
77
  - ๐Ÿ“š **Well Documented** - Extensive documentation and examples
78
78
  - ๐Ÿงช **Tested** - Comprehensive test suite with RSpec
79
79
 
80
+ ## Examples
81
+
82
+ Runnable examples are available in the [`examples/`](./examples) directory:
83
+
84
+ - [`examples/basic_usage.rb`](./examples/basic_usage.rb) - Client setup, connections, integrations, and webhooks
85
+ - [`examples/proxy_api.rb`](./examples/proxy_api.rb) - Proxy API GET request with a connection
86
+ - [`examples/unify_api.rb`](./examples/unify_api.rb) - Unify Chat, Git, PM, Ticketing, and Drive endpoint usage
87
+ - [`examples/README.md`](./examples/README.md) - Setup and execution instructions
88
+
80
89
  ## Quick Start
81
90
 
82
91
  Get started with BundleUp in just a few lines of code:
@@ -85,7 +94,7 @@ Get started with BundleUp in just a few lines of code:
85
94
  require 'bundleup'
86
95
 
87
96
  # Initialize the client
88
- client = Bundleup::Client.new(ENV['BUNDLEUP_API_KEY'])
97
+ client = BundleUp::Client.new(ENV['BUNDLEUP_API_KEY'])
89
98
 
90
99
  # List all active connections
91
100
  connections = client.connections.list
@@ -119,10 +128,10 @@ The BundleUp SDK uses API keys for authentication. You can obtain your API key f
119
128
  require 'bundleup'
120
129
 
121
130
  # Initialize with API key
122
- client = Bundleup::Client.new('your_api_key_here')
131
+ client = BundleUp::Client.new('your_api_key_here')
123
132
 
124
133
  # Or use environment variable (recommended)
125
- client = Bundleup::Client.new(ENV['BUNDLEUP_API_KEY'])
134
+ client = BundleUp::Client.new(ENV['BUNDLEUP_API_KEY'])
126
135
  ```
127
136
 
128
137
  ### Security Best Practices
@@ -154,14 +163,14 @@ Then in your application:
154
163
  require 'dotenv/load'
155
164
  require 'bundleup'
156
165
 
157
- client = Bundleup::Client.new(ENV['BUNDLEUP_API_KEY'])
166
+ client = BundleUp::Client.new(ENV['BUNDLEUP_API_KEY'])
158
167
  ```
159
168
 
160
169
  **For Rails applications:**
161
170
 
162
171
  ```ruby
163
172
  # config/initializers/bundleup.rb
164
- BUNDLEUP_CLIENT = Bundleup::Client.new(ENV['BUNDLEUP_API_KEY'])
173
+ BUNDLEUP_CLIENT = BundleUp::Client.new(ENV['BUNDLEUP_API_KEY'])
165
174
  ```
166
175
 
167
176
  ## Core Concepts
@@ -472,7 +481,7 @@ class WebhooksController < ApplicationController
472
481
  skip_before_action :verify_authenticity_token
473
482
 
474
483
  def create
475
- signature = request.headers['X-Bundleup-Signature']
484
+ signature = request.headers['BundleUp-Signature']
476
485
  payload = request.body.read
477
486
 
478
487
  unless verify_signature(payload, signature)
@@ -631,6 +640,43 @@ unify = client.unify('conn_123abc')
631
640
 
632
641
  The Chat API provides a unified interface for chat platforms like Slack, Discord, and Microsoft Teams.
633
642
 
643
+ ##### List Users
644
+
645
+ Retrieve a list of users from the connected chat platform.
646
+
647
+ ```ruby
648
+ result = unify.chat.users(
649
+ limit: 100,
650
+ after: nil,
651
+ include_raw: false
652
+ )
653
+
654
+ puts "Users: #{result['data']}"
655
+ puts "Next cursor: #{result['metadata']['next']}"
656
+ ```
657
+
658
+ **Parameters:**
659
+
660
+ - `limit` (Integer, optional): Maximum number of users to return (default: 100, max: 1000)
661
+ - `after` (String, optional): Pagination cursor from previous response
662
+ - `include_raw` (Boolean, optional): Include raw API response from the integration (default: false)
663
+
664
+ **Response:**
665
+
666
+ ```ruby
667
+ {
668
+ 'data' => [
669
+ {
670
+ 'id' => 'U1234567890',
671
+ 'name' => 'Jane Doe'
672
+ }
673
+ ],
674
+ 'metadata' => {
675
+ 'next' => 'cursor_abc123'
676
+ }
677
+ }
678
+ ```
679
+
634
680
  ##### List Channels
635
681
 
636
682
  Retrieve a list of channels from the connected chat platform.
@@ -691,6 +737,31 @@ end
691
737
  puts "Fetched #{all_channels.length} total channels"
692
738
  ```
693
739
 
740
+ ##### Send Message
741
+
742
+ Send a message to a channel on the connected chat platform.
743
+
744
+ ```ruby
745
+ result = unify.chat.message('C1234567890', 'Hello from BundleUp! :wave:')
746
+
747
+ puts "Message sent: #{result['data']}"
748
+ ```
749
+
750
+ **Parameters:**
751
+
752
+ - `channel_id` (String, required): The ID of the channel to send the message to
753
+ - `text` (String, required): Markdown-formatted message text
754
+
755
+ **Response:**
756
+
757
+ ```ruby
758
+ {
759
+ 'data' => {
760
+ # Raw response data from the chat provider
761
+ }
762
+ }
763
+ ```
764
+
694
765
  #### Git API
695
766
 
696
767
  The Git API provides a unified interface for version control platforms like GitHub, GitLab, and Bitbucket.
@@ -831,20 +902,45 @@ puts "Releases: #{result['data']}"
831
902
  }
832
903
  ```
833
904
 
834
- #### Project Management API
905
+ ##### List Branches
906
+
907
+ ```ruby
908
+ result = unify.git.branches('organization/repo-name', limit: 50)
909
+
910
+ puts "Branches: #{result['data']}"
911
+ ```
912
+
913
+ **Response:**
914
+
915
+ ```ruby
916
+ {
917
+ 'data' => [
918
+ {
919
+ 'name' => 'main',
920
+ 'commit_sha' => 'abc123def456',
921
+ 'protected' => true
922
+ }
923
+ ],
924
+ 'metadata' => {
925
+ 'next' => nil
926
+ }
927
+ }
928
+ ```
929
+
930
+ #### Ticketing API
835
931
 
836
- The PM API provides a unified interface for project management platforms like Jira, Linear, and Asana.
932
+ The Ticketing API provides a unified interface for ticketing and project management platforms like Jira, Linear, and Asana.
837
933
 
838
- ##### List Issues
934
+ ##### List Tickets
839
935
 
840
936
  ```ruby
841
- result = unify.pm.issues(
937
+ result = unify.ticketing.tickets(
842
938
  limit: 100,
843
939
  after: nil,
844
940
  include_raw: false
845
941
  )
846
942
 
847
- puts "Issues: #{result['data']}"
943
+ puts "Tickets: #{result['data']}"
848
944
  ```
849
945
 
850
946
  **Response:**
@@ -871,8 +967,108 @@ puts "Issues: #{result['data']}"
871
967
  **Filtering and sorting:**
872
968
 
873
969
  ```ruby
874
- open_issues = result['data'].select { |issue| issue['status'] == 'open' }
875
- sorted_by_date = result['data'].sort_by { |issue| Time.parse(issue['created_at']) }.reverse
970
+ open_tickets = result['data'].select { |ticket| ticket['status'] == 'open' }
971
+ sorted_by_date = result['data'].sort_by { |ticket| Time.parse(ticket['created_at']) }.reverse
972
+ ```
973
+
974
+ #### CRM API
975
+
976
+ The CRM API provides a unified interface for CRM platforms like Attio, HubSpot, PipeDrive, Salesforce and Zoho.
977
+
978
+ ##### List Companies
979
+
980
+ ```ruby
981
+ result = unify.crm.companies(
982
+ limit: 100,
983
+ after: nil,
984
+ include_raw: false
985
+ )
986
+
987
+ puts "Companies: #{result['data']}"
988
+ ```
989
+
990
+ **Response:**
991
+
992
+ ```ruby
993
+ {
994
+ 'data' => [
995
+ {
996
+ 'id' => '12345',
997
+ 'name' => 'Acme Inc.',
998
+ 'website' => 'https://acme.example.com'
999
+ }
1000
+ ],
1001
+ 'metadata' => {
1002
+ 'next' => nil
1003
+ }
1004
+ }
1005
+ ```
1006
+
1007
+ ##### List Contacts
1008
+
1009
+ ```ruby
1010
+ result = unify.crm.contacts(
1011
+ limit: 100,
1012
+ after: nil,
1013
+ include_raw: false
1014
+ )
1015
+
1016
+ puts "Contacts: #{result['data']}"
1017
+ ```
1018
+
1019
+ **Response:**
1020
+
1021
+ ```ruby
1022
+ {
1023
+ 'data' => [
1024
+ {
1025
+ 'id' => '67890',
1026
+ 'name' => 'Jane Doe',
1027
+ 'email' => 'jane@acme.example.com'
1028
+ }
1029
+ ],
1030
+ 'metadata' => {
1031
+ 'next' => nil
1032
+ }
1033
+ }
1034
+ ```
1035
+
1036
+ #### Drive API
1037
+
1038
+ The Drive API provides a unified interface for file storage platforms like Google Drive, OneDrive, Box, Dropbox and Microsoft SharePoint.
1039
+
1040
+ ##### List Files
1041
+
1042
+ ```ruby
1043
+ result = unify.drive.files(
1044
+ limit: 100,
1045
+ after: nil,
1046
+ include_raw: false
1047
+ )
1048
+
1049
+ puts "Files: #{result['data']}"
1050
+ ```
1051
+
1052
+ **Response:**
1053
+
1054
+ ```ruby
1055
+ {
1056
+ 'data' => [
1057
+ {
1058
+ 'id' => 'file_123',
1059
+ 'name' => 'quarterly-report.pdf',
1060
+ 'mime_type' => 'application/pdf',
1061
+ 'size' => 204800,
1062
+ 'created_at' => '2024-01-15T10:30:00Z',
1063
+ 'updated_at' => '2024-01-20T14:22:00Z',
1064
+ 'url' => 'https://drive.example.com/file_123',
1065
+ 'is_folder' => false
1066
+ }
1067
+ ],
1068
+ 'metadata' => {
1069
+ 'next' => nil
1070
+ }
1071
+ }
876
1072
  ```
877
1073
 
878
1074
  ## Error Handling
@@ -928,10 +1124,22 @@ lib/
928
1124
  โ”‚ โ”œโ”€โ”€ base.rb # Base Unify class
929
1125
  โ”‚ โ”œโ”€โ”€ chat.rb # Chat Unify API
930
1126
  โ”‚ โ”œโ”€โ”€ git.rb # Git Unify API
931
- โ”‚ โ””โ”€โ”€ pm.rb # PM Unify API
1127
+ โ”‚ โ”œโ”€โ”€ ticketing.rb # Ticketing Unify API
1128
+ โ”‚ โ”œโ”€โ”€ crm.rb # CRM Unify API
1129
+ โ”‚ โ””โ”€โ”€ drive.rb # Drive Unify API
1130
+ sig/ # RBS type signatures (mirrors lib/)
932
1131
  spec/ # Test files
933
1132
  ```
934
1133
 
1134
+ ### Type Signatures
1135
+
1136
+ The gem ships [RBS](https://github.com/ruby/rbs) signatures for the Unify API under `sig/bundleup/unify/`. They're optional at runtime (deleting `sig/` doesn't change behavior) but give editors and `rbs` itself static types for `unify.chat.channels`, `unify.git.repos`, and so on.
1137
+
1138
+ ```bash
1139
+ # Validate the signature files
1140
+ bundle exec rake sig
1141
+ ```
1142
+
935
1143
  ### Running Tests
936
1144
 
937
1145
  ```bash
@@ -1019,7 +1227,7 @@ We welcome contributions to the BundleUp Ruby SDK! Here's how you can help:
1019
1227
  This gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
1020
1228
 
1021
1229
  ```
1022
- Copyright (c) 2024 BundleUp
1230
+ Copyright (c) 2026 BundleUp
1023
1231
 
1024
1232
  Permission is hereby granted, free of charge, to any person obtaining a copy
1025
1233
  of this software and associated documentation files (the "Software"), to deal
@@ -1040,39 +1248,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1040
1248
  SOFTWARE.
1041
1249
  ```
1042
1250
 
1043
- ## Support
1044
-
1045
- Need help? We're here for you!
1046
-
1047
- ### Documentation
1048
-
1049
- - **Official Docs**: [https://docs.bundleup.io](https://docs.bundleup.io)
1050
- - **API Reference**: [https://docs.bundleup.io/api](https://docs.bundleup.io/api)
1051
- - **SDK Guides**: [https://docs.bundleup.io/sdk/ruby](https://docs.bundleup.io/sdk/ruby)
1052
-
1053
- ### Community
1054
-
1055
- - **Discord**: [https://discord.gg/bundleup](https://discord.gg/bundleup)
1056
- - **GitHub Discussions**: [https://github.com/bundleup/bundleup-sdk-ruby/discussions](https://github.com/bundleup/bundleup-sdk-ruby/discussions)
1057
- - **Stack Overflow**: Tag your questions with `bundleup`
1058
-
1059
- ### Direct Support
1060
-
1061
- - **Email**: [support@bundleup.io](mailto:support@bundleup.io)
1062
- - **GitHub Issues**: [https://github.com/bundleup/bundleup-sdk-ruby/issues](https://github.com/bundleup/bundleup-sdk-ruby/issues)
1063
- - **Twitter**: [@bundleup_io](https://twitter.com/bundleup_io)
1064
-
1065
- ### Enterprise Support
1066
-
1067
- For enterprise customers, we offer:
1068
-
1069
- - Priority support with SLA
1070
- - Dedicated support channel
1071
- - Architecture consultation
1072
- - Custom integration assistance
1073
-
1074
- Contact [enterprise@bundleup.io](mailto:enterprise@bundleup.io) for more information.
1075
-
1076
1251
  ## Code of Conduct
1077
1252
 
1078
1253
  Everyone interacting in the BundleUp project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/bundleup/bundleup-sdk-ruby/blob/main/CODE_OF_CONDUCT).
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Bundleup
3
+ module BundleUp
4
4
  # Client for core BundleUp API resources.
5
5
  class Client
6
6
  attr_reader :api_key
@@ -12,15 +12,15 @@ module Bundleup
12
12
  end
13
13
 
14
14
  def connections
15
- @connections ||= Bundleup::Resources::Connection.new(@api_key)
15
+ @connections ||= BundleUp::Resources::Connection.new(@api_key)
16
16
  end
17
17
 
18
18
  def integrations
19
- @integrations ||= Bundleup::Resources::Integration.new(@api_key)
19
+ @integrations ||= BundleUp::Resources::Integration.new(@api_key)
20
20
  end
21
21
 
22
22
  def webhooks
23
- @webhooks ||= Bundleup::Resources::Webhook.new(@api_key)
23
+ @webhooks ||= BundleUp::Resources::Webhook.new(@api_key)
24
24
  end
25
25
 
26
26
  def proxy(connection_id)
@@ -28,7 +28,7 @@ module Bundleup
28
28
  raise ArgumentError, 'Connection ID is required to create a Proxy instance.'
29
29
  end
30
30
 
31
- Bundleup::Proxy.new(@api_key, connection_id)
31
+ BundleUp::Proxy.new(@api_key, connection_id)
32
32
  end
33
33
 
34
34
  def unify(connection_id)
@@ -36,7 +36,7 @@ module Bundleup
36
36
  raise ArgumentError, 'Connection ID is required to create a Unify instance.'
37
37
  end
38
38
 
39
- Bundleup::Unify::Client.new(@api_key, connection_id)
39
+ BundleUp::Unify::Client.new(@api_key, connection_id)
40
40
  end
41
41
  end
42
42
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Bundleup
3
+ module BundleUp
4
4
  # Client for proxy API requests.
5
5
  class Proxy
6
6
  BASE_URL = 'https://proxy.bundleup.io'
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Bundleup
3
+ module BundleUp
4
4
  module Resources
5
5
  # Base class for API resources.
6
6
  class Base
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Bundleup
3
+ module BundleUp
4
4
  module Resources
5
5
  # Client for connection API endpoints.
6
6
  class Connection < Base
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Bundleup
3
+ module BundleUp
4
4
  module Resources
5
5
  # Client for integration API endpoints.
6
6
  class Integration < Base
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Bundleup
3
+ module BundleUp
4
4
  module Resources
5
5
  # Client for webhook API endpoints.
6
6
  class Webhook < Base
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Bundleup
3
+ module BundleUp
4
4
  module Unify
5
5
  # Base class for Unify API clients.
6
6
  class Base
@@ -1,9 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Bundleup
3
+ module BundleUp
4
4
  module Unify
5
5
  # Client for chat-related Unify endpoints.
6
6
  class Chat < Base
7
+ # Fetches users from the connected chat provider.
8
+ def users(params = {})
9
+ response = connection.get('chat/users') do |req|
10
+ req.params = params
11
+ end
12
+
13
+ raise "Failed to fetch chat/users: #{response.status}" unless response.success?
14
+
15
+ response.body
16
+ end
17
+
7
18
  # Fetches channels from the connected chat provider.
8
19
  def channels(params = {})
9
20
  response = connection.get('chat/channels') do |req|
@@ -14,6 +25,19 @@ module Bundleup
14
25
 
15
26
  response.body
16
27
  end
28
+
29
+ # Sends a message to a channel on the connected chat provider.
30
+ def message(channel_id, text)
31
+ raise ArgumentError, 'channel_id is required to send a message.' if channel_id.nil?
32
+
33
+ encoded_channel_id = URI.encode_www_form_component(channel_id)
34
+
35
+ response = connection.post("chat/channels/#{encoded_channel_id}/message", { text: text }.to_json)
36
+
37
+ raise "Failed to post chat/channels/#{encoded_channel_id}/message: #{response.status}" unless response.success?
38
+
39
+ response.body
40
+ end
17
41
  end
18
42
  end
19
43
  end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BundleUp
4
+ module Unify
5
+ # Client for CRM-related Unify endpoints.
6
+ class CRM < Base
7
+ # Fetches companies from the connected CRM provider.
8
+ def companies(params = {})
9
+ response = connection.get('crm/companies') do |req|
10
+ req.params = params
11
+ end
12
+
13
+ raise "Failed to fetch crm/companies: #{response.status}" unless response.success?
14
+
15
+ response.body
16
+ end
17
+
18
+ # Fetches contacts from the connected CRM provider.
19
+ def contacts(params = {})
20
+ response = connection.get('crm/contacts') do |req|
21
+ req.params = params
22
+ end
23
+
24
+ raise "Failed to fetch crm/contacts: #{response.status}" unless response.success?
25
+
26
+ response.body
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BundleUp
4
+ module Unify
5
+ # Client for Drive-related Unify endpoints.
6
+ class Drive < Base
7
+ # Fetches files from the connected Drive provider.
8
+ def files(params = {})
9
+ response = connection.get('drive/files') do |req|
10
+ req.params = params
11
+ end
12
+
13
+ raise "Failed to fetch drive/files: #{response.status}" unless response.success?
14
+
15
+ response.body
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Bundleup
3
+ module BundleUp
4
4
  module Unify
5
5
  # Client for Git Unify endpoints.
6
6
  class Git < Base
@@ -53,6 +53,19 @@ module Bundleup
53
53
 
54
54
  response.body
55
55
  end
56
+
57
+ # Fetches branches for a specific repository from the connected Git provider.
58
+ def branches(repo_name, params = {})
59
+ encoded_repo_name = URI.encode_www_form_component(repo_name)
60
+
61
+ response = connection.get("git/repos/#{encoded_repo_name}/branches") do |req|
62
+ req.params = params
63
+ end
64
+
65
+ raise "Failed to fetch git/repos/#{encoded_repo_name}/branches: #{response.status}" unless response.success?
66
+
67
+ response.body
68
+ end
56
69
  end
57
70
  end
58
71
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BundleUp
4
+ module Unify
5
+ # Client for ticketing Unify endpoints.
6
+ class Ticketing < Base
7
+ # Fetches tickets from the connected ticketing tool.
8
+ def tickets(params = {})
9
+ response = connection.get('ticketing/tickets') do |req|
10
+ req.params = params
11
+ end
12
+
13
+ raise "Failed to fetch ticketing/tickets: #{response.status}" unless response.success?
14
+
15
+ response.body
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,15 +1,44 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Bundleup
3
+ module BundleUp
4
4
  module Unify
5
5
  # Client for Unify API endpoints.
6
6
  class Client
7
7
  attr_reader :api_key, :connection_id
8
8
 
9
9
  def initialize(api_key, connection_id)
10
- @pm = Bundleup::Unify::PM.new(api_key, connection_id)
11
- @chat = Bundleup::Unify::Chat.new(api_key, connection_id)
12
- @git = Bundleup::Unify::Git.new(api_key, connection_id)
10
+ @ticketing = BundleUp::Unify::Ticketing.new(api_key, connection_id)
11
+ @chat = BundleUp::Unify::Chat.new(api_key, connection_id)
12
+ @git = BundleUp::Unify::Git.new(api_key, connection_id)
13
+ @crm = BundleUp::Unify::CRM.new(api_key, connection_id)
14
+ @drive = BundleUp::Unify::Drive.new(api_key, connection_id)
15
+ @api_key = api_key
16
+ @connection_id = connection_id
17
+ end
18
+
19
+ # Access the Chat API for the connection.
20
+ def chat
21
+ @chat ||= BundleUp::Unify::Chat.new(api_key, connection_id)
22
+ end
23
+
24
+ # Access the Git API for the connection.
25
+ def git
26
+ @git ||= BundleUp::Unify::Git.new(api_key, connection_id)
27
+ end
28
+
29
+ # Access the CRM API for the connection.
30
+ def crm
31
+ @crm ||= BundleUp::Unify::CRM.new(api_key, connection_id)
32
+ end
33
+
34
+ # Access the Ticketing API for the connection.
35
+ def ticketing
36
+ @ticketing ||= BundleUp::Unify::Ticketing.new(api_key, connection_id)
37
+ end
38
+
39
+ # Access the Drive API for the connection.
40
+ def drive
41
+ @drive ||= BundleUp::Unify::Drive.new(api_key, connection_id)
13
42
  end
14
43
  end
15
44
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Bundleup
4
- VERSION = '0.2.1'
3
+ module BundleUp
4
+ VERSION = '0.3.0'
5
5
  end
data/lib/bundleup.rb CHANGED
@@ -17,8 +17,10 @@ require_relative 'bundleup/resources/webhook'
17
17
  require_relative 'bundleup/unify/base'
18
18
  require_relative 'bundleup/unify/chat'
19
19
  require_relative 'bundleup/unify/git'
20
- require_relative 'bundleup/unify/pm'
20
+ require_relative 'bundleup/unify/ticketing'
21
+ require_relative 'bundleup/unify/crm'
22
+ require_relative 'bundleup/unify/drive'
21
23
 
22
24
  # Main module for the BundleUp SDK.
23
- module Bundleup
25
+ module BundleUp
24
26
  end
@@ -0,0 +1,17 @@
1
+ module BundleUp
2
+ module Unify
3
+ class Base
4
+ BASE_URL: String
5
+ API_VERSION: String
6
+
7
+ attr_reader api_key: String
8
+ attr_reader connection_id: String
9
+
10
+ def initialize: (String api_key, String connection_id) -> void
11
+
12
+ private
13
+
14
+ def connection: () -> Faraday::Connection
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,13 @@
1
+ module BundleUp
2
+ module Unify
3
+ class Chat < Base
4
+ type chat_user = { id: String, name: String }
5
+ type chat_channel = { id: String, name: String }
6
+ type metadata = { next: String? }
7
+
8
+ def users: (?Hash[Symbol, untyped] params) -> { data: Array[chat_user], metadata: metadata }
9
+ def channels: (?Hash[Symbol, untyped] params) -> { data: Array[chat_channel], metadata: metadata }
10
+ def message: (String channel_id, String text) -> { data: Hash[String, untyped] }
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module BundleUp
2
+ module Unify
3
+ class CRM < Base
4
+ type crm_company = { id: String, name: String, website: String? }
5
+ type crm_contact = { id: String, name: String, email: String? }
6
+ type metadata = { next: String? }
7
+
8
+ def companies: (?Hash[Symbol, untyped] params) -> { data: Array[crm_company], metadata: metadata }
9
+ def contacts: (?Hash[Symbol, untyped] params) -> { data: Array[crm_contact], metadata: metadata }
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,20 @@
1
+ module BundleUp
2
+ module Unify
3
+ class Drive < Base
4
+ type drive_file = {
5
+ id: String,
6
+ name: String,
7
+ mime_type: String?,
8
+ size: Integer?,
9
+ created_at: String?,
10
+ updated_at: String?,
11
+ url: String?,
12
+ is_folder: bool
13
+ }
14
+
15
+ type metadata = { next: String? }
16
+
17
+ def files: (?Hash[Symbol, untyped] params) -> { data: Array[drive_file], metadata: metadata }
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,53 @@
1
+ module BundleUp
2
+ module Unify
3
+ class Git < Base
4
+ type git_repo = {
5
+ id: Integer | String,
6
+ name: String,
7
+ full_name: String,
8
+ description: String?,
9
+ url: String,
10
+ created_at: String,
11
+ updated_at: String,
12
+ pushed_at: String
13
+ }
14
+
15
+ type git_pull = {
16
+ id: Integer,
17
+ number: Integer,
18
+ title: String,
19
+ description: String?,
20
+ draft: bool,
21
+ state: String,
22
+ url: String,
23
+ user: String,
24
+ created_at: String,
25
+ updated_at: String,
26
+ merged_at: String?
27
+ }
28
+
29
+ type git_tag = { name: String, commit_sha: String }
30
+
31
+ type git_release = {
32
+ id: Integer,
33
+ name: String,
34
+ tag_name: String,
35
+ description: String,
36
+ prerelease: bool,
37
+ url: String,
38
+ created_at: String,
39
+ released_at: String
40
+ }
41
+
42
+ type git_branch = { name: String, commit_sha: String, protected: bool }
43
+
44
+ type metadata = { next: String? }
45
+
46
+ def repos: (?Hash[Symbol, untyped] params) -> { data: Array[git_repo], metadata: metadata }
47
+ def pulls: (String repo_name, ?Hash[Symbol, untyped] params) -> { data: Array[git_pull], metadata: metadata }
48
+ def tags: (String repo_name, ?Hash[Symbol, untyped] params) -> { data: Array[git_tag], metadata: metadata }
49
+ def releases: (String repo_name, ?Hash[Symbol, untyped] params) -> { data: Array[git_release], metadata: metadata }
50
+ def branches: (String repo_name, ?Hash[Symbol, untyped] params) -> { data: Array[git_branch], metadata: metadata }
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,19 @@
1
+ module BundleUp
2
+ module Unify
3
+ class Ticketing < Base
4
+ type ticketing_ticket = {
5
+ id: String,
6
+ title: String,
7
+ status: String,
8
+ url: String,
9
+ description: String?,
10
+ created_at: String,
11
+ updated_at: String
12
+ }
13
+
14
+ type metadata = { next: String? }
15
+
16
+ def issues: (?Hash[Symbol, untyped] params) -> { data: Array[ticketing_ticket], metadata: metadata }
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,16 @@
1
+ module BundleUp
2
+ module Unify
3
+ class Client
4
+ attr_reader api_key: String
5
+ attr_reader connection_id: String
6
+
7
+ def initialize: (String api_key, String connection_id) -> void
8
+
9
+ def chat: () -> Chat
10
+ def git: () -> Git
11
+ def pm: () -> PM
12
+ def crm: () -> CRM
13
+ def drive: () -> Drive
14
+ end
15
+ end
16
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bundleup-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - BundleUp
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-02-27 00:00:00.000000000 Z
11
+ date: 2026-07-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '13.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rbs
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rspec
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +80,20 @@ dependencies:
66
80
  - - "~>"
67
81
  - !ruby/object:Gem::Version
68
82
  version: '1.50'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop-capybara
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "<"
88
+ - !ruby/object:Gem::Version
89
+ version: '2.23'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "<"
95
+ - !ruby/object:Gem::Version
96
+ version: '2.23'
69
97
  - !ruby/object:Gem::Dependency
70
98
  name: rubocop-rake
71
99
  requirement: !ruby/object:Gem::Requirement
@@ -148,9 +176,18 @@ files:
148
176
  - lib/bundleup/unify.rb
149
177
  - lib/bundleup/unify/base.rb
150
178
  - lib/bundleup/unify/chat.rb
179
+ - lib/bundleup/unify/crm.rb
180
+ - lib/bundleup/unify/drive.rb
151
181
  - lib/bundleup/unify/git.rb
152
- - lib/bundleup/unify/pm.rb
182
+ - lib/bundleup/unify/ticketing.rb
153
183
  - lib/bundleup/version.rb
184
+ - sig/bundleup/unify.rbs
185
+ - sig/bundleup/unify/base.rbs
186
+ - sig/bundleup/unify/chat.rbs
187
+ - sig/bundleup/unify/crm.rbs
188
+ - sig/bundleup/unify/drive.rbs
189
+ - sig/bundleup/unify/git.rbs
190
+ - sig/bundleup/unify/ticketing.rbs
154
191
  homepage: https://github.com/bundleup/bundleup-sdk-ruby
155
192
  licenses:
156
193
  - MIT
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Bundleup
4
- module Unify
5
- # Client for project management Unify endpoints.
6
- class PM < Base
7
- # Fetches issues from the connected project management tool.
8
- def issues(params = {})
9
- response = connection.get('pm/issues') do |req|
10
- req.params = params
11
- end
12
-
13
- raise "Failed to fetch pm/issues: #{response.status}" unless response.success?
14
-
15
- response.body
16
- end
17
- end
18
- end
19
- end