bundleup-sdk 0.4.2 → 0.4.3
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/README.md +103 -2
- data/lib/bundleup/unify/calendar.rb +35 -0
- data/lib/bundleup/unify/chat.rb +20 -0
- data/lib/bundleup/unify/ticketing.rb +24 -0
- data/lib/bundleup/unify.rb +6 -0
- data/lib/bundleup/version.rb +1 -1
- data/lib/bundleup.rb +1 -0
- data/sig/bundleup/unify/calendar.rbs +23 -0
- data/sig/bundleup/unify/chat.rbs +11 -0
- data/sig/bundleup/unify/ticketing.rbs +17 -1
- data/sig/bundleup/unify.rbs +1 -0
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6a81131b46ad1f04a1714e8e7a07d87d69ee3419648e966daa9099cba31fb4a9
|
|
4
|
+
data.tar.gz: b1861d43ace1fd90f86e89e8b161b91c135f1fc53215cf0dad3defd95351a048
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 13c18248fe861fb462cf3d9019764d13a7925031b49aa40d37f5ab7c3b106e019407140873dda6467057777313bc58cc6cb661daac8f102ff462b318aec4c413
|
|
7
|
+
data.tar.gz: c3bc826ddfb41e39616049a651b180dffd36bb3ee939f27ee315bd350400ae25dbec72666025f22860944d20f82e1945dc20f856b7a2c2cc0302cb671b7b0f9f
|
data/README.md
CHANGED
|
@@ -83,7 +83,7 @@ Runnable examples are available in the [`examples/`](./examples) directory:
|
|
|
83
83
|
|
|
84
84
|
- [`examples/basic_usage.rb`](./examples/basic_usage.rb) - Client setup, connections, integrations, and webhooks
|
|
85
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
|
|
86
|
+
- [`examples/unify_api.rb`](./examples/unify_api.rb) - Unify Chat, Git, PM, Ticketing, Drive, and Calendar endpoint usage
|
|
87
87
|
- [`examples/README.md`](./examples/README.md) - Setup and execution instructions
|
|
88
88
|
|
|
89
89
|
## Quick Start
|
|
@@ -737,6 +737,35 @@ end
|
|
|
737
737
|
puts "Fetched #{all_channels.length} total channels"
|
|
738
738
|
```
|
|
739
739
|
|
|
740
|
+
##### List Messages
|
|
741
|
+
|
|
742
|
+
Messages in one channel, newest first. `author.name` is nil on Slack, which returns only a user id on a message.
|
|
743
|
+
|
|
744
|
+
```ruby
|
|
745
|
+
result = unify.chat.messages('C123', limit: 100, after: nil, include_raw: false)
|
|
746
|
+
|
|
747
|
+
puts "Messages: #{result['data']}"
|
|
748
|
+
```
|
|
749
|
+
|
|
750
|
+
**Response:**
|
|
751
|
+
|
|
752
|
+
```ruby
|
|
753
|
+
{
|
|
754
|
+
'data' => [
|
|
755
|
+
{
|
|
756
|
+
'id' => '1755712345.123456',
|
|
757
|
+
'text' => 'Deploy finished',
|
|
758
|
+
'author' => { 'id' => 'U024BE7LH', 'name' => nil },
|
|
759
|
+
'created_at' => '2026-08-20T18:32:25.123Z',
|
|
760
|
+
'thread_id' => nil
|
|
761
|
+
}
|
|
762
|
+
],
|
|
763
|
+
'metadata' => {
|
|
764
|
+
'next' => 'cursor_def456'
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
```
|
|
768
|
+
|
|
740
769
|
##### Send Message
|
|
741
770
|
|
|
742
771
|
Send a message to a channel on the connected chat platform.
|
|
@@ -971,6 +1000,34 @@ open_tickets = result['data'].select { |ticket| ticket['status'] == 'open' }
|
|
|
971
1000
|
sorted_by_date = result['data'].sort_by { |ticket| Time.parse(ticket['created_at']) }.reverse
|
|
972
1001
|
```
|
|
973
1002
|
|
|
1003
|
+
##### Get a Ticket
|
|
1004
|
+
|
|
1005
|
+
Fetch one ticket by ID. Not supported by Basecamp, whose API only serves a to-do underneath its project.
|
|
1006
|
+
|
|
1007
|
+
```ruby
|
|
1008
|
+
result = unify.ticketing.ticket('PROJ-123')
|
|
1009
|
+
|
|
1010
|
+
puts "Ticket: #{result['data']}"
|
|
1011
|
+
```
|
|
1012
|
+
|
|
1013
|
+
**Response:**
|
|
1014
|
+
|
|
1015
|
+
```ruby
|
|
1016
|
+
{
|
|
1017
|
+
'data' => {
|
|
1018
|
+
'id' => 'PROJ-123',
|
|
1019
|
+
'url' => 'https://jira.example.com/browse/PROJ-123',
|
|
1020
|
+
'title' => 'Fix login bug',
|
|
1021
|
+
'status' => 'in_progress',
|
|
1022
|
+
'description' => 'Users are unable to log in',
|
|
1023
|
+
'created_at' => '2024-01-15T10:30:00Z',
|
|
1024
|
+
'updated_at' => '2024-01-20T14:22:00Z'
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
```
|
|
1028
|
+
|
|
1029
|
+
A single resource carries no pagination, so there is no `metadata` on this response.
|
|
1030
|
+
|
|
974
1031
|
#### CRM API
|
|
975
1032
|
|
|
976
1033
|
The CRM API provides a unified interface for CRM platforms like Attio, HubSpot, PipeDrive, Salesforce and Zoho.
|
|
@@ -1071,6 +1128,49 @@ puts "Files: #{result['data']}"
|
|
|
1071
1128
|
}
|
|
1072
1129
|
```
|
|
1073
1130
|
|
|
1131
|
+
#### Calendar API
|
|
1132
|
+
|
|
1133
|
+
The Calendar API provides a unified interface for calendar and scheduling platforms like Google Calendar, Outlook, Calendly and Zoom.
|
|
1134
|
+
|
|
1135
|
+
##### List Events
|
|
1136
|
+
|
|
1137
|
+
`starts_after` and `starts_before` are required — the endpoint refuses an unbounded listing.
|
|
1138
|
+
|
|
1139
|
+
```ruby
|
|
1140
|
+
result = unify.calendar.events(
|
|
1141
|
+
starts_after: '2026-09-01T00:00:00Z',
|
|
1142
|
+
starts_before: '2026-09-08T00:00:00Z',
|
|
1143
|
+
limit: 100,
|
|
1144
|
+
after: nil,
|
|
1145
|
+
include_raw: false
|
|
1146
|
+
)
|
|
1147
|
+
|
|
1148
|
+
puts "Events: #{result['data']}"
|
|
1149
|
+
```
|
|
1150
|
+
|
|
1151
|
+
**Response:**
|
|
1152
|
+
|
|
1153
|
+
```ruby
|
|
1154
|
+
{
|
|
1155
|
+
'data' => [
|
|
1156
|
+
{
|
|
1157
|
+
'id' => 'evt_123',
|
|
1158
|
+
'title' => 'Design review',
|
|
1159
|
+
'description' => 'Walk through the new onboarding flow',
|
|
1160
|
+
'start_date' => '2026-09-01T15:00:00Z',
|
|
1161
|
+
'end_date' => '2026-09-01T16:00:00Z',
|
|
1162
|
+
'status' => 'confirmed',
|
|
1163
|
+
'url' => 'https://calendar.google.com/event?eid=...'
|
|
1164
|
+
}
|
|
1165
|
+
],
|
|
1166
|
+
'metadata' => {
|
|
1167
|
+
'next' => nil
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
```
|
|
1171
|
+
|
|
1172
|
+
Recurring events are expanded into their occurrences. All-day events carry a `YYYY-MM-DD` date rather than a timestamp. Attendees, conferencing links and organizers are available through `include_raw` or the Proxy API.
|
|
1173
|
+
|
|
1074
1174
|
## Error Handling
|
|
1075
1175
|
|
|
1076
1176
|
The SDK raises exceptions for errors. Always wrap SDK calls in rescue blocks for proper error handling.
|
|
@@ -1126,7 +1226,8 @@ lib/
|
|
|
1126
1226
|
│ ├── git.rb # Git Unify API
|
|
1127
1227
|
│ ├── ticketing.rb # Ticketing Unify API
|
|
1128
1228
|
│ ├── crm.rb # CRM Unify API
|
|
1129
|
-
│
|
|
1229
|
+
│ ├── drive.rb # Drive Unify API
|
|
1230
|
+
│ └── calendar.rb # Calendar Unify API
|
|
1130
1231
|
sig/ # RBS type signatures (mirrors lib/)
|
|
1131
1232
|
spec/ # Test files
|
|
1132
1233
|
```
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BundleUp
|
|
4
|
+
module Unify
|
|
5
|
+
# Client for Calendar-related Unify endpoints.
|
|
6
|
+
class Calendar < Base
|
|
7
|
+
# Fetches events from the connected calendar provider.
|
|
8
|
+
#
|
|
9
|
+
# +params+ must carry +starts_after+ and +starts_before+ (ISO 8601) —
|
|
10
|
+
# the endpoint refuses an unbounded listing.
|
|
11
|
+
def events(params = {})
|
|
12
|
+
raise ArgumentError, 'starts_after and starts_before are required to fetch events.' if window_missing?(params)
|
|
13
|
+
|
|
14
|
+
response = connection.get('calendar/events') do |req|
|
|
15
|
+
req.params = params
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
raise "Failed to fetch calendar/events: #{response.status}" unless response.success?
|
|
19
|
+
|
|
20
|
+
response.body
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def window_missing?(params)
|
|
26
|
+
params ||= {}
|
|
27
|
+
|
|
28
|
+
%i[starts_after starts_before].any? do |key|
|
|
29
|
+
value = params[key] || params[key.to_s]
|
|
30
|
+
value.nil? || value.to_s.empty?
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
data/lib/bundleup/unify/chat.rb
CHANGED
|
@@ -26,6 +26,26 @@ module BundleUp
|
|
|
26
26
|
response.body
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
+
# Fetches messages in a channel from the connected chat provider.
|
|
30
|
+
#
|
|
31
|
+
# Newest first. +author.name+ is nil on Slack, which returns only a user
|
|
32
|
+
# id on a message.
|
|
33
|
+
def messages(channel_id, params = {})
|
|
34
|
+
raise ArgumentError, 'channel_id is required to fetch messages.' if channel_id.nil?
|
|
35
|
+
|
|
36
|
+
encoded_channel_id = URI.encode_www_form_component(channel_id)
|
|
37
|
+
|
|
38
|
+
response = connection.get("chat/channels/#{encoded_channel_id}/messages") do |req|
|
|
39
|
+
req.params = params
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
unless response.success?
|
|
43
|
+
raise "Failed to fetch chat/channels/#{encoded_channel_id}/messages: #{response.status}"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
response.body
|
|
47
|
+
end
|
|
48
|
+
|
|
29
49
|
# Sends a message to a channel on the connected chat provider.
|
|
30
50
|
def message(channel_id, text)
|
|
31
51
|
raise ArgumentError, 'channel_id is required to send a message.' if channel_id.nil?
|
|
@@ -14,6 +14,30 @@ module BundleUp
|
|
|
14
14
|
|
|
15
15
|
response.body
|
|
16
16
|
end
|
|
17
|
+
|
|
18
|
+
# Fetches a single ticket by ID from the connected ticketing tool.
|
|
19
|
+
#
|
|
20
|
+
# Not supported by Basecamp, whose API only serves a to-do underneath its
|
|
21
|
+
# project — an id on its own cannot address one.
|
|
22
|
+
def ticket(ticket_id, params = {})
|
|
23
|
+
raise ArgumentError, 'ticket_id is required to fetch a ticket.' if blank?(ticket_id)
|
|
24
|
+
|
|
25
|
+
encoded_id = URI.encode_www_form_component(ticket_id)
|
|
26
|
+
|
|
27
|
+
response = connection.get("ticketing/tickets/#{encoded_id}") do |req|
|
|
28
|
+
req.params = params
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
raise "Failed to fetch ticketing/tickets/#{encoded_id}: #{response.status}" unless response.success?
|
|
32
|
+
|
|
33
|
+
response.body
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def blank?(value)
|
|
39
|
+
value.nil? || value.to_s.empty?
|
|
40
|
+
end
|
|
17
41
|
end
|
|
18
42
|
end
|
|
19
43
|
end
|
data/lib/bundleup/unify.rb
CHANGED
|
@@ -12,6 +12,7 @@ module BundleUp
|
|
|
12
12
|
@git = BundleUp::Unify::Git.new(api_key, connection_id)
|
|
13
13
|
@crm = BundleUp::Unify::CRM.new(api_key, connection_id)
|
|
14
14
|
@drive = BundleUp::Unify::Drive.new(api_key, connection_id)
|
|
15
|
+
@calendar = BundleUp::Unify::Calendar.new(api_key, connection_id)
|
|
15
16
|
@api_key = api_key
|
|
16
17
|
@connection_id = connection_id
|
|
17
18
|
end
|
|
@@ -41,6 +42,11 @@ module BundleUp
|
|
|
41
42
|
@drive ||= BundleUp::Unify::Drive.new(api_key, connection_id)
|
|
42
43
|
end
|
|
43
44
|
|
|
45
|
+
# Access the Calendar API for the connection.
|
|
46
|
+
def calendar
|
|
47
|
+
@calendar ||= BundleUp::Unify::Calendar.new(api_key, connection_id)
|
|
48
|
+
end
|
|
49
|
+
|
|
44
50
|
# Fetch the account this connection is authenticated as.
|
|
45
51
|
#
|
|
46
52
|
# `me` is the one unified method every provider implements, so it hangs off
|
data/lib/bundleup/version.rb
CHANGED
data/lib/bundleup.rb
CHANGED
|
@@ -21,6 +21,7 @@ require_relative 'bundleup/unify/git'
|
|
|
21
21
|
require_relative 'bundleup/unify/ticketing'
|
|
22
22
|
require_relative 'bundleup/unify/crm'
|
|
23
23
|
require_relative 'bundleup/unify/drive'
|
|
24
|
+
require_relative 'bundleup/unify/calendar'
|
|
24
25
|
require_relative 'bundleup/unify/mcp'
|
|
25
26
|
require_relative 'bundleup/unify/me'
|
|
26
27
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module BundleUp
|
|
2
|
+
module Unify
|
|
3
|
+
class Calendar < Base
|
|
4
|
+
type calendar_event = {
|
|
5
|
+
id: String,
|
|
6
|
+
title: String?,
|
|
7
|
+
description: String?,
|
|
8
|
+
start_date: String?,
|
|
9
|
+
end_date: String?,
|
|
10
|
+
status: String?,
|
|
11
|
+
url: String?
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
type metadata = { next: String? }
|
|
15
|
+
|
|
16
|
+
def events: (?Hash[Symbol, untyped] params) -> { data: Array[calendar_event], metadata: metadata }
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def window_missing?: (Hash[Symbol, untyped]?) -> bool
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
data/sig/bundleup/unify/chat.rbs
CHANGED
|
@@ -3,10 +3,21 @@ module BundleUp
|
|
|
3
3
|
class Chat < Base
|
|
4
4
|
type chat_user = { id: String, name: String }
|
|
5
5
|
type chat_channel = { id: String, name: String }
|
|
6
|
+
type chat_author = { id: String?, name: String? }
|
|
7
|
+
|
|
8
|
+
type chat_message = {
|
|
9
|
+
id: String,
|
|
10
|
+
text: String?,
|
|
11
|
+
author: chat_author?,
|
|
12
|
+
created_at: String?,
|
|
13
|
+
thread_id: String?
|
|
14
|
+
}
|
|
15
|
+
|
|
6
16
|
type metadata = { next: String? }
|
|
7
17
|
|
|
8
18
|
def users: (?Hash[Symbol, untyped] params) -> { data: Array[chat_user], metadata: metadata }
|
|
9
19
|
def channels: (?Hash[Symbol, untyped] params) -> { data: Array[chat_channel], metadata: metadata }
|
|
20
|
+
def messages: (String channel_id, ?Hash[Symbol, untyped] params) -> { data: Array[chat_message], metadata: metadata }
|
|
10
21
|
def message: (String channel_id, String text) -> { data: Hash[String, untyped] }
|
|
11
22
|
end
|
|
12
23
|
end
|
|
@@ -11,9 +11,25 @@ module BundleUp
|
|
|
11
11
|
updated_at: String
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
type ticket = {
|
|
15
|
+
id: String,
|
|
16
|
+
title: String,
|
|
17
|
+
status: String?,
|
|
18
|
+
url: String?,
|
|
19
|
+
description: String?,
|
|
20
|
+
created_at: String?,
|
|
21
|
+
updated_at: String?
|
|
22
|
+
}
|
|
23
|
+
|
|
14
24
|
type metadata = { next: String? }
|
|
15
25
|
|
|
16
|
-
def
|
|
26
|
+
def tickets: (?Hash[Symbol, untyped] params) -> { data: Array[ticketing_ticket], metadata: metadata }
|
|
27
|
+
|
|
28
|
+
def ticket: (String ticket_id, ?Hash[Symbol, untyped] params) -> { data: ticket }
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def blank?: (untyped) -> bool
|
|
17
33
|
end
|
|
18
34
|
end
|
|
19
35
|
end
|
data/sig/bundleup/unify.rbs
CHANGED
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.4.
|
|
4
|
+
version: 0.4.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- BundleUp
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-08-
|
|
11
|
+
date: 2026-08-27 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: faraday
|
|
@@ -177,6 +177,7 @@ files:
|
|
|
177
177
|
- lib/bundleup/resources/webhook.rb
|
|
178
178
|
- lib/bundleup/unify.rb
|
|
179
179
|
- lib/bundleup/unify/base.rb
|
|
180
|
+
- lib/bundleup/unify/calendar.rb
|
|
180
181
|
- lib/bundleup/unify/chat.rb
|
|
181
182
|
- lib/bundleup/unify/crm.rb
|
|
182
183
|
- lib/bundleup/unify/drive.rb
|
|
@@ -187,6 +188,7 @@ files:
|
|
|
187
188
|
- lib/bundleup/version.rb
|
|
188
189
|
- sig/bundleup/unify.rbs
|
|
189
190
|
- sig/bundleup/unify/base.rbs
|
|
191
|
+
- sig/bundleup/unify/calendar.rbs
|
|
190
192
|
- sig/bundleup/unify/chat.rbs
|
|
191
193
|
- sig/bundleup/unify/crm.rbs
|
|
192
194
|
- sig/bundleup/unify/drive.rbs
|