basecamp-sdk 0.16.0 → 0.18.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 +4 -4
- data/lib/basecamp/generated/metadata.json +42 -1
- data/lib/basecamp/generated/services/people_service.rb +30 -0
- data/lib/basecamp/generated/types.rb +112 -2
- data/lib/basecamp/version.rb +1 -1
- data/lib/basecamp.rb +32 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ba36902883801b00a7c8120a32d6dfe05622b606114a71362a22aa1762973c27
|
|
4
|
+
data.tar.gz: 5daa7de8062a988f4250bb531ec00dfedff2c90e8f119b909b91c30f6dcbd80e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: aa16fb909d155e9cfa0b186c8dedfdcca35e203c10ff31abf2eb9977856680a23e9c45bb587be190f45b4fb8a8493cf01c76c9d74ecd91d309abc8a512517545
|
|
7
|
+
data.tar.gz: cc4edb0ab7549aa49cbbea6a3a3def0700dd58fa369f90cc3d0dc52ac0fc788178d9fe786560775ad4e3a5640e035d1ee64a1430092c2d72afce2f1a30af6604
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://basecamp.com/schemas/sdk-metadata.json",
|
|
3
3
|
"version": "1.0.0",
|
|
4
|
-
"generated": "2026-09-
|
|
4
|
+
"generated": "2026-09-10T03:48:29Z",
|
|
5
5
|
"operations": {
|
|
6
6
|
"GetAccount": {
|
|
7
7
|
"retry": {
|
|
@@ -1746,6 +1746,34 @@
|
|
|
1746
1746
|
"natural": true
|
|
1747
1747
|
}
|
|
1748
1748
|
},
|
|
1749
|
+
"EnableProjectClients": {
|
|
1750
|
+
"retry": {
|
|
1751
|
+
"maxAttempts": 3,
|
|
1752
|
+
"baseDelayMs": 1000,
|
|
1753
|
+
"backoff": "exponential",
|
|
1754
|
+
"retryOn": [
|
|
1755
|
+
429,
|
|
1756
|
+
503
|
|
1757
|
+
]
|
|
1758
|
+
},
|
|
1759
|
+
"idempotent": {
|
|
1760
|
+
"natural": true
|
|
1761
|
+
}
|
|
1762
|
+
},
|
|
1763
|
+
"DisableProjectClients": {
|
|
1764
|
+
"retry": {
|
|
1765
|
+
"maxAttempts": 3,
|
|
1766
|
+
"baseDelayMs": 1000,
|
|
1767
|
+
"backoff": "exponential",
|
|
1768
|
+
"retryOn": [
|
|
1769
|
+
429,
|
|
1770
|
+
503
|
|
1771
|
+
]
|
|
1772
|
+
},
|
|
1773
|
+
"idempotent": {
|
|
1774
|
+
"natural": true
|
|
1775
|
+
}
|
|
1776
|
+
},
|
|
1749
1777
|
"ToggleGauge": {
|
|
1750
1778
|
"retry": {
|
|
1751
1779
|
"maxAttempts": 2,
|
|
@@ -1803,6 +1831,19 @@
|
|
|
1803
1831
|
"maxPageSize": 50
|
|
1804
1832
|
}
|
|
1805
1833
|
},
|
|
1834
|
+
"UpdateProjectClientAccess": {
|
|
1835
|
+
"retry": {
|
|
1836
|
+
"maxAttempts": 3,
|
|
1837
|
+
"baseDelayMs": 1000,
|
|
1838
|
+
"backoff": "exponential",
|
|
1839
|
+
"retryOn": [
|
|
1840
|
+
503
|
|
1841
|
+
]
|
|
1842
|
+
},
|
|
1843
|
+
"idempotent": {
|
|
1844
|
+
"natural": true
|
|
1845
|
+
}
|
|
1846
|
+
},
|
|
1806
1847
|
"UpdateProjectAccess": {
|
|
1807
1848
|
"retry": {
|
|
1808
1849
|
"maxAttempts": 3,
|
|
@@ -107,6 +107,24 @@ module Basecamp
|
|
|
107
107
|
end
|
|
108
108
|
end
|
|
109
109
|
|
|
110
|
+
# Enable clients on a project so client users can be added to it
|
|
111
|
+
# @param project_id [Integer] project id ID
|
|
112
|
+
# @return [Hash] response data
|
|
113
|
+
def enable_project_clients(project_id:)
|
|
114
|
+
with_operation(service: "people", operation: "enable_project_clients", is_mutation: true, project_id: project_id) do
|
|
115
|
+
http_post("/projects/#{project_id}/client_enablement.json").json
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Disable clients on a project
|
|
120
|
+
# @param project_id [Integer] project id ID
|
|
121
|
+
# @return [Hash] response data
|
|
122
|
+
def disable_project_clients(project_id:)
|
|
123
|
+
with_operation(service: "people", operation: "disable_project_clients", is_mutation: true, project_id: project_id) do
|
|
124
|
+
http_delete("/projects/#{project_id}/client_enablement.json").json
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
110
128
|
# List all active people on a project
|
|
111
129
|
# @param project_id [Integer] project id ID
|
|
112
130
|
# @param page [Integer, nil] Page number for paginating through results. Defaults to 1. A positive value selects exactly that page, not a starting offset; see SPEC section 8.
|
|
@@ -119,6 +137,18 @@ module Basecamp
|
|
|
119
137
|
end
|
|
120
138
|
end
|
|
121
139
|
|
|
140
|
+
# Update project client access (grant/revoke/create client users)
|
|
141
|
+
# @param project_id [Integer] project id ID
|
|
142
|
+
# @param grant [Array, nil] Existing client people IDs to add to the project.
|
|
143
|
+
# @param revoke [Array, nil] Client people IDs to remove from the project.
|
|
144
|
+
# @param create [Array, nil] New clients to invite by email.
|
|
145
|
+
# @return [Hash] response data
|
|
146
|
+
def update_project_client_access(project_id:, grant: nil, revoke: nil, create: nil)
|
|
147
|
+
with_operation(service: "people", operation: "update_project_client_access", is_mutation: true, project_id: project_id) do
|
|
148
|
+
http_put("/projects/#{project_id}/people/client_users.json", body: compact_params(grant: grant, revoke: revoke, create: create)).json
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
122
152
|
# Update project access (grant/revoke/create people)
|
|
123
153
|
# @param project_id [Integer] project id ID
|
|
124
154
|
# @param grant [Array, nil] grant
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
# Auto-generated from OpenAPI spec. Do not edit manually.
|
|
4
|
-
# Generated: 2026-09-
|
|
4
|
+
# Generated: 2026-09-10T03:48:29Z
|
|
5
5
|
|
|
6
6
|
require "json"
|
|
7
7
|
require "time"
|
|
@@ -1135,6 +1135,58 @@ module Basecamp
|
|
|
1135
1135
|
end
|
|
1136
1136
|
end
|
|
1137
1137
|
|
|
1138
|
+
# ClientInvitationError
|
|
1139
|
+
class ClientInvitationError
|
|
1140
|
+
include TypeHelpers
|
|
1141
|
+
attr_accessor :email_address, :messages
|
|
1142
|
+
|
|
1143
|
+
# @return [Array<Symbol>]
|
|
1144
|
+
def self.required_fields
|
|
1145
|
+
%i[email_address messages].freeze
|
|
1146
|
+
end
|
|
1147
|
+
|
|
1148
|
+
def initialize(data = {})
|
|
1149
|
+
@email_address = data["email_address"]
|
|
1150
|
+
@messages = data["messages"]
|
|
1151
|
+
end
|
|
1152
|
+
|
|
1153
|
+
def to_h
|
|
1154
|
+
{
|
|
1155
|
+
"email_address" => @email_address,
|
|
1156
|
+
"messages" => @messages,
|
|
1157
|
+
}.reject { |k, v| v.nil? && !["email_address"].include?(k) }
|
|
1158
|
+
end
|
|
1159
|
+
|
|
1160
|
+
def to_json(*args)
|
|
1161
|
+
to_h.to_json(*args)
|
|
1162
|
+
end
|
|
1163
|
+
end
|
|
1164
|
+
|
|
1165
|
+
# ClientInvitationErrors
|
|
1166
|
+
class ClientInvitationErrors
|
|
1167
|
+
include TypeHelpers
|
|
1168
|
+
attr_accessor :errors
|
|
1169
|
+
|
|
1170
|
+
# @return [Array<Symbol>]
|
|
1171
|
+
def self.required_fields
|
|
1172
|
+
%i[errors].freeze
|
|
1173
|
+
end
|
|
1174
|
+
|
|
1175
|
+
def initialize(data = {})
|
|
1176
|
+
@errors = parse_array(data["errors"], "ClientInvitationError")
|
|
1177
|
+
end
|
|
1178
|
+
|
|
1179
|
+
def to_h
|
|
1180
|
+
{
|
|
1181
|
+
"errors" => @errors,
|
|
1182
|
+
}.compact
|
|
1183
|
+
end
|
|
1184
|
+
|
|
1185
|
+
def to_json(*args)
|
|
1186
|
+
to_h.to_json(*args)
|
|
1187
|
+
end
|
|
1188
|
+
end
|
|
1189
|
+
|
|
1138
1190
|
# ClientReply
|
|
1139
1191
|
class ClientReply
|
|
1140
1192
|
include TypeHelpers
|
|
@@ -1374,6 +1426,37 @@ module Basecamp
|
|
|
1374
1426
|
end
|
|
1375
1427
|
end
|
|
1376
1428
|
|
|
1429
|
+
# CreateClientRequest
|
|
1430
|
+
class CreateClientRequest
|
|
1431
|
+
include TypeHelpers
|
|
1432
|
+
attr_accessor :email_address, :company_name, :name, :title
|
|
1433
|
+
|
|
1434
|
+
# @return [Array<Symbol>]
|
|
1435
|
+
def self.required_fields
|
|
1436
|
+
%i[email_address].freeze
|
|
1437
|
+
end
|
|
1438
|
+
|
|
1439
|
+
def initialize(data = {})
|
|
1440
|
+
@email_address = data["email_address"]
|
|
1441
|
+
@company_name = data["company_name"]
|
|
1442
|
+
@name = data["name"]
|
|
1443
|
+
@title = data["title"]
|
|
1444
|
+
end
|
|
1445
|
+
|
|
1446
|
+
def to_h
|
|
1447
|
+
{
|
|
1448
|
+
"email_address" => @email_address,
|
|
1449
|
+
"company_name" => @company_name,
|
|
1450
|
+
"name" => @name,
|
|
1451
|
+
"title" => @title,
|
|
1452
|
+
}.compact
|
|
1453
|
+
end
|
|
1454
|
+
|
|
1455
|
+
def to_json(*args)
|
|
1456
|
+
to_h.to_json(*args)
|
|
1457
|
+
end
|
|
1458
|
+
end
|
|
1459
|
+
|
|
1377
1460
|
# CreatePersonRequest
|
|
1378
1461
|
class CreatePersonRequest
|
|
1379
1462
|
include TypeHelpers
|
|
@@ -3249,6 +3332,31 @@ module Basecamp
|
|
|
3249
3332
|
end
|
|
3250
3333
|
end
|
|
3251
3334
|
|
|
3335
|
+
# ProjectClientEnablement
|
|
3336
|
+
class ProjectClientEnablement
|
|
3337
|
+
include TypeHelpers
|
|
3338
|
+
attr_accessor :clients_enabled
|
|
3339
|
+
|
|
3340
|
+
# @return [Array<Symbol>]
|
|
3341
|
+
def self.required_fields
|
|
3342
|
+
%i[clients_enabled].freeze
|
|
3343
|
+
end
|
|
3344
|
+
|
|
3345
|
+
def initialize(data = {})
|
|
3346
|
+
@clients_enabled = parse_boolean(data["clients_enabled"])
|
|
3347
|
+
end
|
|
3348
|
+
|
|
3349
|
+
def to_h
|
|
3350
|
+
{
|
|
3351
|
+
"clients_enabled" => @clients_enabled,
|
|
3352
|
+
}.compact
|
|
3353
|
+
end
|
|
3354
|
+
|
|
3355
|
+
def to_json(*args)
|
|
3356
|
+
to_h.to_json(*args)
|
|
3357
|
+
end
|
|
3358
|
+
end
|
|
3359
|
+
|
|
3252
3360
|
# ProjectConstruction
|
|
3253
3361
|
class ProjectConstruction
|
|
3254
3362
|
include TypeHelpers
|
|
@@ -3283,7 +3391,7 @@ module Basecamp
|
|
|
3283
3391
|
# ProjectConstructionAttributes
|
|
3284
3392
|
class ProjectConstructionAttributes
|
|
3285
3393
|
include TypeHelpers
|
|
3286
|
-
attr_accessor :name, :description
|
|
3394
|
+
attr_accessor :name, :description, :start_date
|
|
3287
3395
|
|
|
3288
3396
|
# @return [Array<Symbol>]
|
|
3289
3397
|
def self.required_fields
|
|
@@ -3293,12 +3401,14 @@ module Basecamp
|
|
|
3293
3401
|
def initialize(data = {})
|
|
3294
3402
|
@name = data["name"]
|
|
3295
3403
|
@description = data["description"]
|
|
3404
|
+
@start_date = data["start_date"]
|
|
3296
3405
|
end
|
|
3297
3406
|
|
|
3298
3407
|
def to_h
|
|
3299
3408
|
{
|
|
3300
3409
|
"name" => @name,
|
|
3301
3410
|
"description" => @description,
|
|
3411
|
+
"start_date" => @start_date,
|
|
3302
3412
|
}.compact
|
|
3303
3413
|
end
|
|
3304
3414
|
|
data/lib/basecamp/version.rb
CHANGED
data/lib/basecamp.rb
CHANGED
|
@@ -245,7 +245,9 @@ module Basecamp
|
|
|
245
245
|
|
|
246
246
|
data = JSON.parse(body)
|
|
247
247
|
errors = data.is_a?(Hash) ? data["errors"] : nil
|
|
248
|
-
if errors.is_a?(
|
|
248
|
+
if errors.is_a?(Array)
|
|
249
|
+
parse_row_errors(errors)
|
|
250
|
+
elsif errors.is_a?(Hash)
|
|
249
251
|
field_errors = errors.each_with_object({}) do |(field, values), result|
|
|
250
252
|
next unless values.is_a?(Array)
|
|
251
253
|
|
|
@@ -260,6 +262,35 @@ module Basecamp
|
|
|
260
262
|
nil
|
|
261
263
|
end
|
|
262
264
|
|
|
265
|
+
# Extracts a row-keyed errors list — the batch-invite rendering
|
|
266
|
+
# {"errors" => [{"email_address" => "...", "messages" => ["..."]}, ...]}
|
|
267
|
+
# (SPEC section 6 step 1b), one element per rejected row. Rows are keyed by
|
|
268
|
+
# their email_address when it is a non-empty string, else by an integer
|
|
269
|
+
# index, else by their position in the list; a repeated key appends.
|
|
270
|
+
# All-or-nothing: one element without a usable messages array means this is
|
|
271
|
+
# some other list, and the slot stays absent.
|
|
272
|
+
# @param rows [Array] the parsed "errors" array
|
|
273
|
+
# @return [Hash{String => Array<String>}, nil]
|
|
274
|
+
def self.parse_row_errors(rows)
|
|
275
|
+
return nil if rows.empty?
|
|
276
|
+
|
|
277
|
+
rows.each_with_index.each_with_object({}) do |(row, position), result|
|
|
278
|
+
return nil unless row.is_a?(Hash) && row["messages"].is_a?(Array)
|
|
279
|
+
|
|
280
|
+
messages = row["messages"].select { |message| message.is_a?(String) && !message.empty? }
|
|
281
|
+
return nil if messages.empty?
|
|
282
|
+
|
|
283
|
+
key = if row["email_address"].is_a?(String) && !row["email_address"].empty?
|
|
284
|
+
row["email_address"]
|
|
285
|
+
elsif row["index"].is_a?(Integer)
|
|
286
|
+
row["index"].to_s
|
|
287
|
+
else
|
|
288
|
+
position.to_s
|
|
289
|
+
end
|
|
290
|
+
(result[key] ||= []).concat(messages)
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
|
|
263
294
|
# Extracts an unwrapped field map — the `render json: @webhook.errors`
|
|
264
295
|
# rendering, where the whole body is {"field" => ["msg", ...]}. The gate is
|
|
265
296
|
# all-or-nothing by design (SPEC section 6 step 2): with no "errors" key to
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: basecamp-sdk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.18.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Basecamp
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-09-
|
|
11
|
+
date: 2026-09-10 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: faraday
|