basecamp-sdk 0.19.0 → 0.20.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/client.rb +0 -5
- data/lib/basecamp/generated/services/lineup_service.rb +8 -0
- data/lib/basecamp/version.rb +1 -1
- data/scripts/generate-metadata.rb +95 -12
- data/scripts/generate-services.rb +121 -22
- metadata +2 -3
- data/lib/basecamp/generated/services/automation_service.rb +0 -19
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a1df4a43587230e1bfbf0403175de3fdf93b50635c42a91a71d3c2e29bb835c8
|
|
4
|
+
data.tar.gz: c2a9eb831ecd48967fdb706a808fe13a923570f97edcf7b6ed96b7e2372dfcd2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 25fb53f7d538f519dfd7f7091e687dec7a0f9ce59f65df4c612f44fcea5cf2f3d65d8b8257dcccb8a0bc2b535e340efe911b9f435ef54f022ac0f9752953f6d5
|
|
7
|
+
data.tar.gz: 6a7f120b233a4d4dc07f5a233c97ee4c8fb3861181143bdd492a7e48998903eb8e0a465b6cfc8816511ef03ecfa0657c0af951b05f3d5a761019130332401a27
|
data/lib/basecamp/client.rb
CHANGED
|
@@ -516,11 +516,6 @@ module Basecamp
|
|
|
516
516
|
service(:lineup) { Services::LineupService.new(self) }
|
|
517
517
|
end
|
|
518
518
|
|
|
519
|
-
# @return [Services::AutomationService]
|
|
520
|
-
def automation
|
|
521
|
-
service(:automation) { Services::AutomationService.new(self) }
|
|
522
|
-
end
|
|
523
|
-
|
|
524
519
|
# @return [Services::MessageTypesService]
|
|
525
520
|
def message_types
|
|
526
521
|
service(:message_types) { Services::MessageTypesService.new(self) }
|
|
@@ -7,6 +7,14 @@ module Basecamp
|
|
|
7
7
|
# @generated from OpenAPI spec
|
|
8
8
|
class LineupService < BaseService
|
|
9
9
|
|
|
10
|
+
# List all lineup markers for the account
|
|
11
|
+
# @return [Array<Hash>] response data
|
|
12
|
+
def list_lineup_markers()
|
|
13
|
+
with_operation(service: "lineup", operation: "list_lineup_markers", is_mutation: false) do
|
|
14
|
+
http_get("/lineup/markers.json", operation: "ListLineupMarkers").json(operation: "ListLineupMarkers")
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
10
18
|
# Create a new lineup marker
|
|
11
19
|
# @param name [String] name
|
|
12
20
|
# @param date [String] date
|
data/lib/basecamp/version.rb
CHANGED
|
@@ -13,7 +13,46 @@ require 'time'
|
|
|
13
13
|
|
|
14
14
|
# Extract metadata from OpenAPI spec
|
|
15
15
|
class MetadataExtractor
|
|
16
|
-
|
|
16
|
+
# A Path Item Object is read by EXCLUSION: its non-operation fields are a
|
|
17
|
+
# closed, spec-defined set, its extensions are `x-` prefixed, and every other
|
|
18
|
+
# field is an operation. A verb list here dropped an operation's metadata in
|
|
19
|
+
# silence for any method outside the five it knew (#925). Nothing in this
|
|
20
|
+
# file is verb-specific — metadata is keyed by operationId — so the walk is
|
|
21
|
+
# total and no verb bound belongs here.
|
|
22
|
+
NON_OPERATION_FIELDS = %w[summary description servers parameters].freeze
|
|
23
|
+
|
|
24
|
+
# Membership is decided above, by exclusion. The shared declaration every
|
|
25
|
+
# generator reads (spec/generated-verbs.json) is ORDERED, and that order is
|
|
26
|
+
# reused here to keep metadata.json byte-stable. Order is not membership: a
|
|
27
|
+
# verb absent from the declaration sorts deterministically to the end by name
|
|
28
|
+
# and is still extracted, because nothing in this file is verb-specific.
|
|
29
|
+
# The self-test points this at a crafted declaration to prove the bound is
|
|
30
|
+
# sourced from the shared file rather than a private literal; production runs
|
|
31
|
+
# never set it.
|
|
32
|
+
GENERATED_VERBS_FILE = ENV.fetch(
|
|
33
|
+
'BASECAMP_GENERATED_VERBS', File.expand_path('../../spec/generated-verbs.json', __dir__)
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
METHOD_ORDER = begin
|
|
37
|
+
verbs = JSON.parse(File.read(GENERATED_VERBS_FILE, encoding: 'UTF-8'))['verbs']
|
|
38
|
+
# An HTTP method is a TOKEN, so the rule is a positive character class rather
|
|
39
|
+
# than a blankness predicate: `[a-z]+`, identical in all six loaders. Two
|
|
40
|
+
# review rounds chased "blank" across languages — Kotlin and Rust rejected a
|
|
41
|
+
# space while the others accepted it, then Ruby's ASCII `strip` accepted a
|
|
42
|
+
# non-breaking space the Unicode-aware ones rejected — and the next
|
|
43
|
+
# disagreement was guaranteed, because every language defines whitespace
|
|
44
|
+
# differently (Java's Character.isWhitespace excludes U+00A0; Rust's
|
|
45
|
+
# char::is_whitespace includes it; Ruby's String#strip is ASCII-only). A
|
|
46
|
+
# closed positive rule has no such seam: "", " ", "\u00a0", "GET" and 1 are
|
|
47
|
+
# all rejected the same way everywhere.
|
|
48
|
+
unless verbs.is_a?(Array) && !verbs.empty? && verbs.all? { |v| v.is_a?(String) && v.match?(/\A[a-z]+\z/) }
|
|
49
|
+
abort "Error: #{GENERATED_VERBS_FILE} must declare a non-empty `verbs` array of lowercase " \
|
|
50
|
+
'ASCII method names (/\A[a-z]+\z/).'
|
|
51
|
+
end
|
|
52
|
+
verbs.freeze
|
|
53
|
+
rescue Errno::ENOENT, JSON::ParserError => e
|
|
54
|
+
abort "Error: cannot read the generated-verb declaration #{GENERATED_VERBS_FILE}: #{e.message}"
|
|
55
|
+
end
|
|
17
56
|
|
|
18
57
|
def initialize(openapi_path)
|
|
19
58
|
# Read as UTF-8 regardless of process locale (LC_ALL=C would otherwise read
|
|
@@ -24,13 +63,9 @@ class MetadataExtractor
|
|
|
24
63
|
def extract
|
|
25
64
|
operations = {}
|
|
26
65
|
|
|
27
|
-
(@openapi['paths'] || {}).
|
|
28
|
-
|
|
29
|
-
operation = path_item[method]
|
|
30
|
-
next unless operation
|
|
31
|
-
|
|
66
|
+
(@openapi['paths'] || {}).each do |path, path_item|
|
|
67
|
+
each_operation(path, path_item) do |_method, operation|
|
|
32
68
|
operation_id = operation['operationId']
|
|
33
|
-
next unless operation_id
|
|
34
69
|
|
|
35
70
|
metadata = extract_operation_metadata(operation)
|
|
36
71
|
operations[operation_id] = metadata if metadata.any?
|
|
@@ -61,11 +96,8 @@ class MetadataExtractor
|
|
|
61
96
|
# in "[]" names an array of people. "$" is the body itself.
|
|
62
97
|
def person_id_sites
|
|
63
98
|
sites = {}
|
|
64
|
-
(@openapi['paths'] || {}).
|
|
65
|
-
|
|
66
|
-
operation = path_item[method]
|
|
67
|
-
next unless operation && operation['operationId']
|
|
68
|
-
|
|
99
|
+
(@openapi['paths'] || {}).each do |path, path_item|
|
|
100
|
+
each_operation(path, path_item) do |_method, operation|
|
|
69
101
|
paths = (operation['responses'] || {}).flat_map do |code, response|
|
|
70
102
|
next [] unless code.to_s.start_with?('2')
|
|
71
103
|
|
|
@@ -117,6 +149,57 @@ class MetadataExtractor
|
|
|
117
149
|
raise "person id site under additionalProperties at #{nested.first} has no runtime path syntax" if nested.any?
|
|
118
150
|
end
|
|
119
151
|
|
|
152
|
+
# Yields [verb, operation] for every operation in a path item. A field that is
|
|
153
|
+
# neither a known non-operation field nor a readable operation object stops
|
|
154
|
+
# the run by name rather than being stepped over.
|
|
155
|
+
def each_operation(path, path_item)
|
|
156
|
+
unless path_item.is_a?(Hash)
|
|
157
|
+
abort "Error: openapi.json path #{path} is a #{path_item.class}, not a path item object."
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
if path_item.key?('$ref')
|
|
161
|
+
abort "Error: openapi.json path #{path} is a $ref to #{path_item['$ref'].inspect}. " \
|
|
162
|
+
'This extractor cannot resolve a path-item reference, and skipping it would leave ' \
|
|
163
|
+
'every operation behind it without runtime metadata.'
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# OpenAPI 3.2's `additionalOperations` is a MAP of method to Operation, not an
|
|
167
|
+
# operation. Read as one it carries no operationId, so it would drop every
|
|
168
|
+
# operation inside it without saying so. Refuse by name until the walk learns
|
|
169
|
+
# the map shape.
|
|
170
|
+
if path_item.key?('additionalOperations')
|
|
171
|
+
abort "Error: openapi.json path #{path} declares `additionalOperations`, which OpenAPI 3.2 " \
|
|
172
|
+
'defines as a map of method to Operation. This walk reads a path-item field as a ' \
|
|
173
|
+
'single operation, so it would drop every operation inside it. Teach the walk the map ' \
|
|
174
|
+
'shape, or take the field out of the spec.'
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
fields = path_item.keys.reject { |f| NON_OPERATION_FIELDS.include?(f) || f.start_with?('x-') }
|
|
178
|
+
fields.sort_by! { |f| [ METHOD_ORDER.index(f) || METHOD_ORDER.length, f ] }
|
|
179
|
+
|
|
180
|
+
fields.each do |field|
|
|
181
|
+
operation = path_item[field]
|
|
182
|
+
|
|
183
|
+
unless operation.is_a?(Hash)
|
|
184
|
+
abort "Error: openapi.json path #{path} field #{field.inspect} is a #{operation.class}, " \
|
|
185
|
+
'which is neither a known non-operation field nor an operation object. If a later ' \
|
|
186
|
+
'OpenAPI version added it, add it to NON_OPERATION_FIELDS with a reason.'
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# An operation has to be IDENTIFIABLE. OpenAPI lets operationId be omitted,
|
|
190
|
+
# and every walker here used to step over one that was — a silent drop of a
|
|
191
|
+
# real operation, which is #925 wearing a different field.
|
|
192
|
+
op_id = operation['operationId']
|
|
193
|
+
unless op_id.is_a?(String) && !op_id.empty?
|
|
194
|
+
abort "Error: openapi.json declares #{field.upcase} #{path} with no operationId. " \
|
|
195
|
+
'Everything downstream is keyed by it, and skipping the operation would drop it ' \
|
|
196
|
+
'from the SDK in silence.'
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
yield field, operation
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
120
203
|
private
|
|
121
204
|
|
|
122
205
|
def extract_operation_metadata(operation)
|
|
@@ -17,7 +17,54 @@ require 'set'
|
|
|
17
17
|
|
|
18
18
|
# Service generator for Ruby SDK
|
|
19
19
|
class ServiceGenerator
|
|
20
|
-
|
|
20
|
+
# A Path Item Object is read by EXCLUSION. Its non-operation fields are a
|
|
21
|
+
# closed, spec-defined set and its extensions are `x-` prefixed, so every
|
|
22
|
+
# OTHER field is an operation. Enumerating the verbs instead is the defect
|
|
23
|
+
# this replaces (#925): Smithy's `@http` trait takes the method as a
|
|
24
|
+
# free-form string it "will use literally and will perform no validation
|
|
25
|
+
# on", so a model author writing `method: "HEAD"` produced a valid model, a
|
|
26
|
+
# valid openapi.json, and no method on any service — the verb was not in the
|
|
27
|
+
# list, so the operation was stepped over in silence.
|
|
28
|
+
NON_OPERATION_FIELDS = %w[summary description servers parameters].freeze
|
|
29
|
+
|
|
30
|
+
# Discovery above is total; emission is bounded by the ONE declaration every
|
|
31
|
+
# generator reads (spec/generated-verbs.json), whose header carries the
|
|
32
|
+
# reasoning. Each verb in it has an `Http` helper (`http_get`, `http_post`, …)
|
|
33
|
+
# the emitted method body calls. An operation on any other verb stops this
|
|
34
|
+
# generator by name instead of vanishing from the SDK — a loud refusal is the
|
|
35
|
+
# acceptable outcome, a silent drop never was.
|
|
36
|
+
#
|
|
37
|
+
# The declaration is ORDERED, and that order is emission order. Ordering is a
|
|
38
|
+
# different job from deciding membership and cannot reproduce #925: membership
|
|
39
|
+
# is decided by exclusion above, so a verb absent from the declaration is
|
|
40
|
+
# refused, never skipped.
|
|
41
|
+
# The self-test points this at a crafted declaration to prove the bound is
|
|
42
|
+
# sourced from the shared file rather than a private literal; production runs
|
|
43
|
+
# never set it.
|
|
44
|
+
GENERATED_VERBS_FILE = ENV.fetch(
|
|
45
|
+
'BASECAMP_GENERATED_VERBS', File.expand_path('../../spec/generated-verbs.json', __dir__)
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
EMITTABLE_METHODS = begin
|
|
49
|
+
verbs = JSON.parse(File.read(GENERATED_VERBS_FILE, encoding: 'UTF-8'))['verbs']
|
|
50
|
+
# An HTTP method is a TOKEN, so the rule is a positive character class rather
|
|
51
|
+
# than a blankness predicate: `[a-z]+`, identical in all six loaders. Two
|
|
52
|
+
# review rounds chased "blank" across languages — Kotlin and Rust rejected a
|
|
53
|
+
# space while the others accepted it, then Ruby's ASCII `strip` accepted a
|
|
54
|
+
# non-breaking space the Unicode-aware ones rejected — and the next
|
|
55
|
+
# disagreement was guaranteed, because every language defines whitespace
|
|
56
|
+
# differently (Java's Character.isWhitespace excludes U+00A0; Rust's
|
|
57
|
+
# char::is_whitespace includes it; Ruby's String#strip is ASCII-only). A
|
|
58
|
+
# closed positive rule has no such seam: "", " ", "\u00a0", "GET" and 1 are
|
|
59
|
+
# all rejected the same way everywhere.
|
|
60
|
+
unless verbs.is_a?(Array) && !verbs.empty? && verbs.all? { |v| v.is_a?(String) && v.match?(/\A[a-z]+\z/) }
|
|
61
|
+
abort "Error: #{GENERATED_VERBS_FILE} must declare a non-empty `verbs` array of lowercase " \
|
|
62
|
+
'ASCII method names (/\A[a-z]+\z/).'
|
|
63
|
+
end
|
|
64
|
+
verbs.freeze
|
|
65
|
+
rescue Errno::ENOENT, JSON::ParserError => e
|
|
66
|
+
abort "Error: cannot read the generated-verb declaration #{GENERATED_VERBS_FILE}: #{e.message}"
|
|
67
|
+
end
|
|
21
68
|
|
|
22
69
|
# Schema reference cache for resolving $ref
|
|
23
70
|
attr_reader :schemas
|
|
@@ -33,7 +80,6 @@ class ServiceGenerator
|
|
|
33
80
|
'Schedule' => 'Schedules',
|
|
34
81
|
'People' => 'People',
|
|
35
82
|
'Projects' => 'Projects',
|
|
36
|
-
'Automation' => 'Automation',
|
|
37
83
|
'ClientFeatures' => 'ClientFeatures',
|
|
38
84
|
'Boosts' => 'Boosts',
|
|
39
85
|
'Untagged' => 'Miscellaneous'
|
|
@@ -72,22 +118,11 @@ class ServiceGenerator
|
|
|
72
118
|
'CloudFiles' => %w[GetCloudFile CreateCloudFile UpdateCloudFile],
|
|
73
119
|
'GoogleDocuments' => %w[GetGoogleDocument CreateGoogleDocument UpdateGoogleDocument]
|
|
74
120
|
},
|
|
75
|
-
'
|
|
76
|
-
'Tools' => %w[GetTool UpdateTool DeleteTool CreateTool EnableTool DisableTool RepositionTool]
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
'Events' => %w[ListEvents]
|
|
80
|
-
'Lineup' => %w[CreateLineupMarker UpdateLineupMarker DeleteLineupMarker],
|
|
81
|
-
'Search' => %w[Search GetSearchMetadata],
|
|
82
|
-
'Templates' => %w[
|
|
83
|
-
ListTemplates CreateTemplate GetTemplate UpdateTemplate
|
|
84
|
-
DeleteTemplate CreateProjectFromTemplate GetProjectConstruction
|
|
85
|
-
GetTemplateLibrary CreateTemplateLibraryCopy GetTemplateLibraryCopy
|
|
86
|
-
],
|
|
87
|
-
'Checkins' => %w[
|
|
88
|
-
GetQuestionnaire ListQuestions CreateQuestion GetQuestion
|
|
89
|
-
UpdateQuestion ListAnswers CreateAnswer GetAnswer UpdateAnswer
|
|
90
|
-
]
|
|
121
|
+
'Dock' => {
|
|
122
|
+
'Tools' => %w[GetTool UpdateTool DeleteTool CreateTool EnableTool DisableTool RepositionTool]
|
|
123
|
+
},
|
|
124
|
+
'Recordings' => {
|
|
125
|
+
'Events' => %w[ListEvents]
|
|
91
126
|
},
|
|
92
127
|
'Messages' => {
|
|
93
128
|
'Messages' => %w[GetMessage UpdateMessage CreateMessage ListMessages PinMessage UnpinMessage],
|
|
@@ -366,14 +401,78 @@ class ServiceGenerator
|
|
|
366
401
|
|
|
367
402
|
private
|
|
368
403
|
|
|
404
|
+
# Yields [verb, operation] for every operation in a path item, identifying an
|
|
405
|
+
# operation by what it is NOT (see NON_OPERATION_FIELDS). Anything this
|
|
406
|
+
# generator cannot render aborts the run naming the operation.
|
|
407
|
+
def each_operation(path, path_item)
|
|
408
|
+
unless path_item.is_a?(Hash)
|
|
409
|
+
abort "Error: openapi.json path #{path} is a #{path_item.class}, not a path item object."
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
# A `$ref` path item points at operations this generator cannot see without
|
|
413
|
+
# resolving the reference. Skipping it is the same silent under-count the
|
|
414
|
+
# exclusion walk exists to prevent, so refuse until someone teaches it to
|
|
415
|
+
# follow one.
|
|
416
|
+
if path_item.key?('$ref')
|
|
417
|
+
abort "Error: openapi.json path #{path} is a $ref to #{path_item['$ref'].inspect}. " \
|
|
418
|
+
'This generator cannot resolve a path-item reference, and skipping it would hide ' \
|
|
419
|
+
'every operation behind it from the SDK. Inline the path item, or teach this ' \
|
|
420
|
+
'generator to resolve local references.'
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
# OpenAPI 3.2's `additionalOperations` is a MAP of method to Operation, not an
|
|
424
|
+
# operation. Read as one it carries no operationId, so it would drop every
|
|
425
|
+
# operation inside it without saying so. Refuse by name until the walk learns
|
|
426
|
+
# the map shape.
|
|
427
|
+
if path_item.key?('additionalOperations')
|
|
428
|
+
abort "Error: openapi.json path #{path} declares `additionalOperations`, which OpenAPI 3.2 " \
|
|
429
|
+
'defines as a map of method to Operation. This walk reads a path-item field as a ' \
|
|
430
|
+
'single operation, so it would drop every operation inside it. Teach the walk the map ' \
|
|
431
|
+
'shape, or take the field out of the spec.'
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
fields = path_item.keys.reject { |f| NON_OPERATION_FIELDS.include?(f) || f.start_with?('x-') }
|
|
435
|
+
fields.sort_by! { |f| [ EMITTABLE_METHODS.index(f) || EMITTABLE_METHODS.length, f ] }
|
|
436
|
+
|
|
437
|
+
fields.each do |field|
|
|
438
|
+
operation = path_item[field]
|
|
439
|
+
|
|
440
|
+
unless operation.is_a?(Hash)
|
|
441
|
+
abort "Error: openapi.json path #{path} field #{field.inspect} is a #{operation.class}, " \
|
|
442
|
+
'which is neither a known non-operation field nor an operation object. If a later ' \
|
|
443
|
+
'OpenAPI version added it, add it to NON_OPERATION_FIELDS with a reason.'
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
unless EMITTABLE_METHODS.include?(field)
|
|
447
|
+
op_id = operation['operationId'] || '(no operationId)'
|
|
448
|
+
abort "Error: openapi.json declares #{field.upcase} #{path} (#{op_id}), and this generator " \
|
|
449
|
+
"emits only #{EMITTABLE_METHODS.map(&:upcase).join('/')}. Generating the rest of the " \
|
|
450
|
+
'SDK without it would drop the operation from every Ruby client in silence, which is ' \
|
|
451
|
+
'the failure #925 closed. Give Basecamp::Http a ' \
|
|
452
|
+
"http_#{field} helper, add #{field.inspect} to spec/generated-verbs.json (read that " \
|
|
453
|
+
'file first — the other five SDKs need the same helper), or take the operation out ' \
|
|
454
|
+
'of the Smithy model.'
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
# An operation has to be IDENTIFIABLE. OpenAPI lets operationId be omitted,
|
|
458
|
+
# and every walker here used to step over one that was — a silent drop of a
|
|
459
|
+
# real operation, which is #925 wearing a different field.
|
|
460
|
+
op_id = operation['operationId']
|
|
461
|
+
unless op_id.is_a?(String) && !op_id.empty?
|
|
462
|
+
abort "Error: openapi.json declares #{field.upcase} #{path} with no operationId. " \
|
|
463
|
+
'Everything downstream is keyed by it, and skipping the operation would drop it ' \
|
|
464
|
+
'from the SDK in silence.'
|
|
465
|
+
end
|
|
466
|
+
|
|
467
|
+
yield field, operation
|
|
468
|
+
end
|
|
469
|
+
end
|
|
470
|
+
|
|
369
471
|
def group_operations
|
|
370
472
|
services = {}
|
|
371
473
|
|
|
372
474
|
@openapi['paths'].each do |path, path_item|
|
|
373
|
-
|
|
374
|
-
operation = path_item[method]
|
|
375
|
-
next unless operation
|
|
376
|
-
|
|
475
|
+
each_operation(path, path_item) do |method, operation|
|
|
377
476
|
tag = operation['tags']&.first || 'Untagged'
|
|
378
477
|
parsed = parse_operation(path, method, operation)
|
|
379
478
|
|
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.20.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-20 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: faraday
|
|
@@ -183,7 +183,6 @@ files:
|
|
|
183
183
|
- lib/basecamp/generated/metadata.json
|
|
184
184
|
- lib/basecamp/generated/services/account_service.rb
|
|
185
185
|
- lib/basecamp/generated/services/attachments_service.rb
|
|
186
|
-
- lib/basecamp/generated/services/automation_service.rb
|
|
187
186
|
- lib/basecamp/generated/services/base_service.rb
|
|
188
187
|
- lib/basecamp/generated/services/bookmarks_service.rb
|
|
189
188
|
- lib/basecamp/generated/services/boosts_service.rb
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Basecamp
|
|
4
|
-
module Services
|
|
5
|
-
# Service for Automation operations
|
|
6
|
-
#
|
|
7
|
-
# @generated from OpenAPI spec
|
|
8
|
-
class AutomationService < BaseService
|
|
9
|
-
|
|
10
|
-
# List all lineup markers for the account
|
|
11
|
-
# @return [Array<Hash>] response data
|
|
12
|
-
def list_lineup_markers()
|
|
13
|
-
with_operation(service: "automation", operation: "list_lineup_markers", is_mutation: false) do
|
|
14
|
-
http_get("/lineup/markers.json", operation: "ListLineupMarkers").json(operation: "ListLineupMarkers")
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|