basecamp-sdk 0.23.0 → 0.25.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 +1 -1
- data/lib/basecamp/generated/services/boosts_service.rb +2 -2
- data/lib/basecamp/generated/services/card_columns_service.rb +7 -4
- data/lib/basecamp/generated/services/checkins_service.rb +4 -5
- data/lib/basecamp/generated/services/lineup_service.rb +6 -8
- data/lib/basecamp/generated/services/my_notifications_service.rb +1 -1
- data/lib/basecamp/generated/types.rb +4 -2
- data/lib/basecamp/oauth/exchange.rb +43 -7
- data/lib/basecamp/version.rb +1 -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: 7713550a3bc2d6b5dd732e3bdadb679d5016316e9f4004677c028a30daa65371
|
|
4
|
+
data.tar.gz: 71b74a2b499c484f245669d9b317df4f826c799f2d2bbda0cce140a75b22884f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a5f430f32c8ef3e13f0b3690ec31223bc942f06bc907708fe33fbfa84b99a86dcfe56a2734ef0e8224f5cfdfdc41ce4c28703e8321c6ba88330bba4bedf775f0
|
|
7
|
+
data.tar.gz: 834ea9c748c9d64ce67089e765875bf8c6c56a52ce0d895629b1c02f4d6e2acbdcb63b566a563c19823ce1c3199016b02fba3c92136bbbd5cb67cf6d950a0744
|
|
@@ -48,7 +48,7 @@ module Basecamp
|
|
|
48
48
|
end
|
|
49
49
|
end
|
|
50
50
|
|
|
51
|
-
# List boosts on a specific event within a recording
|
|
51
|
+
# List boosts on a specific event within a recording. Only boostable events carry boosts: those whose action is completed, adopted, column_changed or moved_in (their JSON includes boosts_count and boosts_url). Any other event answers 403 Forbidden; an event on a recording the person cannot see answers 404.
|
|
52
52
|
# @param recording_id [Integer] recording id ID
|
|
53
53
|
# @param event_id [Integer] event id ID
|
|
54
54
|
# @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.
|
|
@@ -61,7 +61,7 @@ module Basecamp
|
|
|
61
61
|
end
|
|
62
62
|
end
|
|
63
63
|
|
|
64
|
-
# Create a boost on a specific event within a recording
|
|
64
|
+
# Create a boost on a specific event within a recording. Only boostable events accept one: those whose action is completed, adopted, column_changed or moved_in (their JSON includes boosts_count and boosts_url). Any other event answers 403 Forbidden, as does an event on a recording whose comments are closed; an event on a recording the person cannot see answers 404.
|
|
65
65
|
# @param recording_id [Integer] recording id ID
|
|
66
66
|
# @param event_id [Integer] event id ID
|
|
67
67
|
# @param content [String] content
|
|
@@ -89,11 +89,14 @@ module Basecamp
|
|
|
89
89
|
end
|
|
90
90
|
end
|
|
91
91
|
|
|
92
|
-
# Move a column
|
|
92
|
+
# Move a column to a slot within its card table. target_id is the card table's own id (the same as cardTableId), not a column; position is the 1-based slot among the columns, not counting Triage, Not Now or Done.
|
|
93
93
|
# @param card_table_id [Integer] card table id ID
|
|
94
|
-
# @param source_id [Integer]
|
|
95
|
-
# @param target_id [Integer]
|
|
96
|
-
#
|
|
94
|
+
# @param source_id [Integer] The column to move.
|
|
95
|
+
# @param target_id [Integer] The card table the column moves within: the same id as `cardTableId`.
|
|
96
|
+
# Basecamp refuses any other destination, a column included, with 422.
|
|
97
|
+
# @param position [Integer, nil] 1-based slot among the card table's columns, not counting Triage,
|
|
98
|
+
# Not Now or Done. 1 puts the column first; a slot past the last puts it
|
|
99
|
+
# last. Default: 1.
|
|
97
100
|
# @return [void]
|
|
98
101
|
def move(card_table_id:, source_id:, target_id:, position: nil)
|
|
99
102
|
with_operation(service: "cardcolumns", operation: "move", is_mutation: true, resource_id: card_table_id) do
|
|
@@ -81,15 +81,14 @@ module Basecamp
|
|
|
81
81
|
end
|
|
82
82
|
end
|
|
83
83
|
|
|
84
|
-
# Update an existing question
|
|
84
|
+
# Update an existing question's title, schedule or both. A schedule replaces the whole schedule, so send every part of it: one without frequency or time_of_day is refused, and one without start_date re-anchors the recurrence on today. Pausing and resuming are PauseQuestion and ResumeQuestion.
|
|
85
85
|
# @param question_id [Integer] question id ID
|
|
86
|
-
# @param title [String, nil] title
|
|
86
|
+
# @param title [String, nil] The question text. An update carries a title, a schedule or both.
|
|
87
87
|
# @param schedule [Hash, nil] schedule
|
|
88
|
-
# @param paused [Boolean, nil] paused
|
|
89
88
|
# @return [Hash] response data
|
|
90
|
-
def update_question(question_id:, title: nil, schedule: nil
|
|
89
|
+
def update_question(question_id:, title: nil, schedule: nil)
|
|
91
90
|
with_operation(service: "checkins", operation: "update_question", is_mutation: true, resource_id: question_id) do
|
|
92
|
-
http_put("/questions/#{question_id}", body: compact_params(title: title, schedule: schedule
|
|
91
|
+
http_put("/questions/#{question_id}", body: compact_params(title: title, schedule: schedule)).json(operation: "UpdateQuestion")
|
|
93
92
|
end
|
|
94
93
|
end
|
|
95
94
|
|
|
@@ -15,26 +15,24 @@ module Basecamp
|
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
# Create a new lineup marker
|
|
18
|
+
# Create a new lineup marker. Returns the created marker.
|
|
19
19
|
# @param name [String] name
|
|
20
20
|
# @param date [String] date
|
|
21
|
-
# @return [
|
|
21
|
+
# @return [Hash] response data
|
|
22
22
|
def create(name:, date:)
|
|
23
23
|
with_operation(service: "lineup", operation: "create", is_mutation: true) do
|
|
24
|
-
http_post("/lineup/markers.json", body: compact_params(name: name, date: date))
|
|
25
|
-
nil
|
|
24
|
+
http_post("/lineup/markers.json", body: compact_params(name: name, date: date)).json(operation: "CreateLineupMarker")
|
|
26
25
|
end
|
|
27
26
|
end
|
|
28
27
|
|
|
29
|
-
# Update an existing lineup marker
|
|
28
|
+
# Update an existing lineup marker. Returns the updated marker.
|
|
30
29
|
# @param marker_id [Integer] marker id ID
|
|
31
30
|
# @param name [String, nil] name
|
|
32
31
|
# @param date [String, nil] date
|
|
33
|
-
# @return [
|
|
32
|
+
# @return [Hash] response data
|
|
34
33
|
def update(marker_id:, name: nil, date: nil)
|
|
35
34
|
with_operation(service: "lineup", operation: "update", is_mutation: true, resource_id: marker_id) do
|
|
36
|
-
http_put("/lineup/markers/#{marker_id}", body: compact_params(name: name, date: date))
|
|
37
|
-
nil
|
|
35
|
+
http_put("/lineup/markers/#{marker_id}", body: compact_params(name: name, date: date)).json(operation: "UpdateLineupMarker")
|
|
38
36
|
end
|
|
39
37
|
end
|
|
40
38
|
|
|
@@ -7,7 +7,7 @@ module Basecamp
|
|
|
7
7
|
# @generated from OpenAPI spec
|
|
8
8
|
class MyNotificationsService < BaseService
|
|
9
9
|
|
|
10
|
-
# Get the current user's
|
|
10
|
+
# Get the current user's notifications (the "Hey!" menu in Basecamp 4).
|
|
11
11
|
# @param page [Integer, nil] Page number for paginating through read items. Defaults to 1. This
|
|
12
12
|
# operation is not auto-paginated in any SDK, so a page is returned as
|
|
13
13
|
# asked for and later pages are not followed.
|
|
@@ -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-10-
|
|
4
|
+
# Generated: 2026-10-15T16:04:42Z
|
|
5
5
|
|
|
6
6
|
require "json"
|
|
7
7
|
require "time"
|
|
@@ -3299,7 +3299,7 @@ module Basecamp
|
|
|
3299
3299
|
include TypeHelpers
|
|
3300
3300
|
# @!attribute [rw] clientside
|
|
3301
3301
|
# @deprecated This shape is deprecated since 2024-01: Use Client Visibility feature instead
|
|
3302
|
-
attr_accessor :app_url, :created_at, :id, :name, :status, :updated_at, :url, :bookmark_url, :bookmarked, :client_company, :clients_enabled, :clientside, :description, :dock, :end_date, :purpose, :star_url, :starred, :start_date
|
|
3302
|
+
attr_accessor :app_url, :created_at, :id, :name, :status, :updated_at, :url, :bookmark_url, :bookmarked, :client_company, :clients_enabled, :clientside, :description, :dock, :end_date, :purpose, :star_url, :starred, :start_date, :timesheet_enabled
|
|
3303
3303
|
|
|
3304
3304
|
# @return [Array<Symbol>]
|
|
3305
3305
|
def self.required_fields
|
|
@@ -3326,6 +3326,7 @@ module Basecamp
|
|
|
3326
3326
|
@star_url = data["star_url"]
|
|
3327
3327
|
@starred = parse_boolean(data["starred"])
|
|
3328
3328
|
@start_date = data["start_date"]
|
|
3329
|
+
@timesheet_enabled = parse_boolean(data["timesheet_enabled"])
|
|
3329
3330
|
end
|
|
3330
3331
|
|
|
3331
3332
|
def to_h
|
|
@@ -3349,6 +3350,7 @@ module Basecamp
|
|
|
3349
3350
|
"star_url" => @star_url,
|
|
3350
3351
|
"starred" => @starred,
|
|
3351
3352
|
"start_date" => @start_date,
|
|
3353
|
+
"timesheet_enabled" => @timesheet_enabled,
|
|
3352
3354
|
}.compact
|
|
3353
3355
|
end
|
|
3354
3356
|
|
|
@@ -288,9 +288,16 @@ module Basecamp
|
|
|
288
288
|
end
|
|
289
289
|
|
|
290
290
|
def parse_token_response(status, body)
|
|
291
|
-
|
|
291
|
+
# A failed request is classified from its status and OAuth error
|
|
292
|
+
# object BEFORE the body is parsed as a token: a refusal whose body is
|
|
293
|
+
# not JSON (a bare 401, an HTML error page) must surface as that
|
|
294
|
+
# refusal, not as a malformed token response.
|
|
295
|
+
handle_error_response(status, body) unless (200..299).cover?(status)
|
|
292
296
|
|
|
293
|
-
|
|
297
|
+
data = JSON.parse(body)
|
|
298
|
+
unless data.is_a?(Hash)
|
|
299
|
+
raise OauthError.new("api_error", "Token response is not a JSON object", http_status: status)
|
|
300
|
+
end
|
|
294
301
|
|
|
295
302
|
unless data["access_token"].is_a?(String) && !data["access_token"].empty?
|
|
296
303
|
raise OauthError.new(
|
|
@@ -344,20 +351,49 @@ module Basecamp
|
|
|
344
351
|
), cause: nil
|
|
345
352
|
end
|
|
346
353
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
354
|
+
# The OAuth error codes a caller resolves by signing in again: the grant
|
|
355
|
+
# is invalid, expired or revoked (+invalid_grant+), the client failed to
|
|
356
|
+
# authenticate (+invalid_client+) or may not use this grant
|
|
357
|
+
# (+unauthorized_client+), or the resource owner refused
|
|
358
|
+
# (+access_denied+). Classified by code, not status: RFC 6749 §5.2
|
|
359
|
+
# answers +invalid_client+ with a 400 unless the client authenticated
|
|
360
|
+
# through the Authorization header, so a 401 cannot be the only signal.
|
|
361
|
+
# Matches every other SDK's token endpoint (conformance/oauth-token).
|
|
362
|
+
AUTH_ERROR_CODES = %w[invalid_grant invalid_client unauthorized_client access_denied].freeze
|
|
363
|
+
|
|
364
|
+
# Classifies a non-2xx token endpoint response: "auth" for an error code
|
|
365
|
+
# in AUTH_ERROR_CODES on any status, or for any 401 whatever its body
|
|
366
|
+
# (Launchpad and other servers refuse with a bare status); "api_error"
|
|
367
|
+
# for everything else. The body is read only for the RFC 6749 +error+
|
|
368
|
+
# and +error_description+ members and is never echoed — a body that is
|
|
369
|
+
# not an OAuth error object contributes nothing.
|
|
370
|
+
def handle_error_response(status, body)
|
|
371
|
+
data = oauth_error_object(body)
|
|
372
|
+
error_code = data["error"] if data["error"].is_a?(String)
|
|
373
|
+
description = data["error_description"] if data["error_description"].is_a?(String)
|
|
374
|
+
error_msg = Basecamp::Security.truncate(description || error_code || "Token request failed")
|
|
375
|
+
|
|
376
|
+
if status == 401 || AUTH_ERROR_CODES.include?(error_code)
|
|
351
377
|
raise OauthError.new(
|
|
352
378
|
"auth",
|
|
353
379
|
error_msg,
|
|
354
380
|
http_status: status,
|
|
355
|
-
hint: "The authorization
|
|
381
|
+
hint: "The authorization server refused this grant or client: authorize again, or check the client credentials"
|
|
356
382
|
)
|
|
357
383
|
end
|
|
358
384
|
|
|
359
385
|
raise OauthError.new("api_error", error_msg, http_status: status)
|
|
360
386
|
end
|
|
387
|
+
|
|
388
|
+
# The response body as an OAuth error object, or {} when it is not one.
|
|
389
|
+
# The parser error is discarded, never chained: its message embeds the
|
|
390
|
+
# offending input.
|
|
391
|
+
def oauth_error_object(body)
|
|
392
|
+
parsed = JSON.parse(body)
|
|
393
|
+
parsed.is_a?(Hash) ? parsed : {}
|
|
394
|
+
rescue JSON::ParserError
|
|
395
|
+
{}
|
|
396
|
+
end
|
|
361
397
|
end
|
|
362
398
|
end
|
|
363
399
|
end
|
data/lib/basecamp/version.rb
CHANGED
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.25.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-10-
|
|
11
|
+
date: 2026-10-15 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: faraday
|