|
7 | 7 | # frozen_string_literal: true |
8 | 8 |
|
9 | 9 | require_relative 'parameter' |
| 10 | +require_relative 'body' |
10 | 11 | require_relative 'operation' |
11 | 12 |
|
12 | | -# A collection of operations that comprise a single API Action |
13 | | -# AKA operation-group |
14 | | -class Action |
15 | | - # @param [SpecHash] spec Parsed OpenAPI spec |
16 | | - def self.actions=(spec) |
17 | | - operations = spec.paths.flat_map do |url, ops| |
18 | | - ops.filter_map { |verb, op| Operation.new(op, url, verb) unless op['x-ignorable'] } |
| 13 | +module Api |
| 14 | + # A collection of operations that comprise a single API Action |
| 15 | + # AKA operation-group |
| 16 | + class Action |
| 17 | + SUCCESS_CODES = %w[200 201 202 203 204 205 206 207 208 226].freeze |
| 18 | + |
| 19 | + # @param [SpecHash] spec Parsed OpenAPI spec |
| 20 | + def self.actions=(spec) |
| 21 | + operations = spec.paths.flat_map do |url, ops| |
| 22 | + ops.filter_map { |verb, op| Operation.new(op, url, verb) unless op['x-ignorable'] } |
| 23 | + end |
| 24 | + @actions = operations.group_by(&:group).values.map { |ops| Action.new(ops) } |
19 | 25 | end |
20 | | - @actions = operations.group_by(&:group).values.map { |ops| Action.new(ops) }.index_by(&:full_name) |
21 | | - end |
22 | 26 |
|
23 | | - # @return [Hash<String, Action>] API Actions indexed by operation-group |
24 | | - def self.actions |
25 | | - raise 'Actions not set' unless @actions |
26 | | - @actions |
27 | | - end |
| 27 | + # @return [Array<Action>] API Actions |
| 28 | + def self.all |
| 29 | + raise 'Actions not set' unless @actions |
| 30 | + @actions |
| 31 | + end |
28 | 32 |
|
29 | | - # @return [Array<Operation>] Operations in the action |
30 | | - attr_reader :operations |
| 33 | + def self.by_full_name |
| 34 | + @by_full_name ||= all.index_by(&:full_name).to_h |
| 35 | + end |
31 | 36 |
|
32 | | - # @param [Array<Operation>] operations |
33 | | - def initialize(operations) |
34 | | - @operations = operations |
35 | | - @operation = operations.first |
36 | | - @spec = @operation&.spec |
37 | | - end |
| 37 | + def self.by_namespace |
| 38 | + @by_namespace ||= all.group_by(&:namespace) |
| 39 | + end |
38 | 40 |
|
39 | | - # @return [Array<Parameter>] Input arguments. |
40 | | - def arguments; @arguments ||= Parameter.from_operations(@operations.map(&:spec)); end |
| 41 | + # @return [Array<Api::Operation>] Operations in the action |
| 42 | + attr_reader :operations |
41 | 43 |
|
42 | | - # @return [String] Full name of the action (i.e. namespace.action) |
43 | | - def full_name; @operation&.group; end |
| 44 | + # @param [Array<Api::Operation>] operations |
| 45 | + def initialize(operations) |
| 46 | + @operations = operations |
| 47 | + @operation = operations.first || {} |
| 48 | + @spec = @operation&.spec |
| 49 | + end |
44 | 50 |
|
45 | | - # return [String] Name of the action |
46 | | - def name; @operation&.action; end |
| 51 | + def query_parameters |
| 52 | + @operations.map(&:spec).flat_map(&:parameters).filter { |param| !param['x-global'] && param.in == 'query' } |
| 53 | + .group_by(&:name).values |
| 54 | + .map { |params| Parameter.from_param_specs(params, @operations.size) } |
| 55 | + end |
47 | 56 |
|
48 | | - # @return [String] Namespace of the action |
49 | | - def namespace; @operation&.namespace; end |
| 57 | + def path_parameters |
| 58 | + @operations.map(&:spec).flat_map(&:parameters).filter { |param| param.in == 'path' } |
| 59 | + .group_by(&:name).values |
| 60 | + .map { |params| Parameter.from_param_specs(params, @operations.size) } |
| 61 | + end |
50 | 62 |
|
51 | | - # @return [Array<String>] Sorted unique HTTP verbs |
52 | | - def http_verbs; @operations.map(&:http_verb).uniq.sort; end |
| 63 | + # @return [Api::Body, nil] Request body |
| 64 | + def request_body |
| 65 | + @request_body ||= |
| 66 | + begin |
| 67 | + operation = @operations.find { |op| op.spec.requestBody.present? } |
| 68 | + required = @operations.all? { |op| op.spec.requestBody.required } |
| 69 | + operation.nil? ? nil : Body.new(operation.spec.requestBody.content, required:) |
| 70 | + end |
| 71 | + end |
| 72 | + |
| 73 | + # @return [Api::Body] Response body |
| 74 | + def response_body |
| 75 | + @response_body ||= |
| 76 | + begin |
| 77 | + spec = @operations.first.spec |
| 78 | + code = SUCCESS_CODES.find { |c| spec.responses[c].present? } |
| 79 | + Body.new(@operations.first.spec.responses[code].content, required: nil) |
| 80 | + end |
| 81 | + end |
| 82 | + |
| 83 | + # @return [String] Full name of the action (i.e. namespace.action) |
| 84 | + def full_name; @operation.group; end |
53 | 85 |
|
54 | | - # @return [Array<String>] Unique URLs |
55 | | - def urls; @operations.map(&:url).uniq; end |
| 86 | + # return [String] Name of the action |
| 87 | + def name; @operation.action; end |
56 | 88 |
|
57 | | - # @return [String] Description of the action |
58 | | - def description; @spec&.description; end |
| 89 | + # @return [String] Namespace of the action |
| 90 | + def namespace; @operation.namespace || ''; end |
59 | 91 |
|
60 | | - # @return [Boolean] Whether the action is deprecated |
61 | | - def deprecated; @spec&.deprecated; end |
| 92 | + # @return [Array<String>] Sorted unique HTTP verbs |
| 93 | + def http_verbs; @operations.map(&:http_verb).uniq.sort; end |
62 | 94 |
|
63 | | - # @return [String] Deprecation message |
64 | | - def deprecation_message; @spec['x-deprecation-message']; end |
| 95 | + # @return [Array<String>] Unique URLs |
| 96 | + def urls; @operations.map(&:url).uniq; end |
65 | 97 |
|
66 | | - # @return [String] API reference |
67 | | - def api_reference; @operation&.external_docs&.url; end |
| 98 | + # @return [String] Description of the action |
| 99 | + def description; @spec.description; end |
| 100 | + |
| 101 | + # @return [Boolean] Whether the action is deprecated |
| 102 | + def deprecated; @spec.deprecated; end |
| 103 | + |
| 104 | + # @return [String] Deprecation message |
| 105 | + def deprecation_message; @spec['x-deprecation-message']; end |
| 106 | + |
| 107 | + # @return [String] API reference |
| 108 | + def api_reference; @operation.external_docs.url; end |
| 109 | + end |
68 | 110 | end |
0 commit comments