webfunction 1.0.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 +7 -0
- data/.rubocop.yml +42 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +598 -0
- data/Rakefile +12 -0
- data/lib/web_function.rb +1 -0
- data/lib/webfunction/argument.rb +123 -0
- data/lib/webfunction/attribute.rb +113 -0
- data/lib/webfunction/client.rb +155 -0
- data/lib/webfunction/documented_error.rb +67 -0
- data/lib/webfunction/endpoint.rb +243 -0
- data/lib/webfunction/flaggable.rb +40 -0
- data/lib/webfunction/object_schema.rb +135 -0
- data/lib/webfunction/package.rb +196 -0
- data/lib/webfunction/page.rb +134 -0
- data/lib/webfunction/pipeline.rb +91 -0
- data/lib/webfunction/promise.rb +150 -0
- data/lib/webfunction/request.rb +177 -0
- data/lib/webfunction/type/any.rb +48 -0
- data/lib/webfunction/type/array_of.rb +58 -0
- data/lib/webfunction/type/base.rb +89 -0
- data/lib/webfunction/type/union.rb +54 -0
- data/lib/webfunction/type.rb +140 -0
- data/lib/webfunction/utils.rb +67 -0
- data/lib/webfunction/version.rb +5 -0
- data/lib/webfunction.rb +52 -0
- data/sig/webfunction.rbs +4 -0
- metadata +131 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module WebFunction
|
|
4
|
+
# Arguments are used to define Web Function {Endpoint} request parameters.
|
|
5
|
+
#
|
|
6
|
+
# See the [arguments section][0] on the Web Function website for more details.
|
|
7
|
+
#
|
|
8
|
+
# [0]: https://webfunction.org/package#arguments
|
|
9
|
+
#
|
|
10
|
+
class Argument
|
|
11
|
+
include Flaggable
|
|
12
|
+
|
|
13
|
+
def initialize(name:, type:, group: nil, choices: [], flags: [], docs: nil)
|
|
14
|
+
@name = name
|
|
15
|
+
@type = Type.parse(type)
|
|
16
|
+
@group = group
|
|
17
|
+
@choices = choices
|
|
18
|
+
@flags = flags
|
|
19
|
+
@docs = docs.to_s
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class << self
|
|
23
|
+
# Instantiate a new Argument from a hash, typically coming from a {Package}.
|
|
24
|
+
#
|
|
25
|
+
# @param argument [Hash]
|
|
26
|
+
#
|
|
27
|
+
# @return [Argument, nil]
|
|
28
|
+
#
|
|
29
|
+
def from_hash(argument)
|
|
30
|
+
unless argument.is_a?(Hash)
|
|
31
|
+
return
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
unless argument["name"]
|
|
35
|
+
return
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
unless argument["type"]
|
|
39
|
+
return
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
new(
|
|
43
|
+
name: argument["name"],
|
|
44
|
+
type: argument["type"],
|
|
45
|
+
group: argument["group"],
|
|
46
|
+
choices: [*argument["choices"]],
|
|
47
|
+
flags: Utils.normalize_array_of_strings(argument["flags"]),
|
|
48
|
+
docs: argument["docs"],
|
|
49
|
+
)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Instantiate a collection of Argument from an array of hash, typically coming from a {Package}. Uses
|
|
53
|
+
# {Argument#from_hash} under the hood.
|
|
54
|
+
#
|
|
55
|
+
# @param arguments [Array<Hash>]
|
|
56
|
+
#
|
|
57
|
+
# @return [Array<Argument>]
|
|
58
|
+
#
|
|
59
|
+
def from_array(arguments)
|
|
60
|
+
Utils.normalize_array arguments do |argument|
|
|
61
|
+
from_hash(argument)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# The name of the argument.
|
|
67
|
+
#
|
|
68
|
+
# @return [String]
|
|
69
|
+
#
|
|
70
|
+
attr_reader :name
|
|
71
|
+
|
|
72
|
+
# The type of the argument. It must be one of:
|
|
73
|
+
#
|
|
74
|
+
# - object
|
|
75
|
+
# - array
|
|
76
|
+
# - string
|
|
77
|
+
# - number
|
|
78
|
+
# - boolean
|
|
79
|
+
#
|
|
80
|
+
# @return [String]
|
|
81
|
+
#
|
|
82
|
+
attr_reader :type
|
|
83
|
+
|
|
84
|
+
# A name used to categorize or group similar arguments together. This should be used by documentation tools to
|
|
85
|
+
# organize related arguments.
|
|
86
|
+
#
|
|
87
|
+
# @return [String]
|
|
88
|
+
#
|
|
89
|
+
attr_reader :group
|
|
90
|
+
|
|
91
|
+
# An array specifying the exact, case-sensitive values that are permitted for this argument. Each value in the
|
|
92
|
+
# choices array must conform to the data type specified in the argument's type key.
|
|
93
|
+
#
|
|
94
|
+
# Note that if the argument type is array, choices may contain strings or numbers representing the allowed values
|
|
95
|
+
# that can be included in the array.
|
|
96
|
+
#
|
|
97
|
+
# @return [Array]
|
|
98
|
+
#
|
|
99
|
+
attr_reader :choices
|
|
100
|
+
|
|
101
|
+
# Description of the argument. It must be formatted as markdown.
|
|
102
|
+
#
|
|
103
|
+
# @return [String]
|
|
104
|
+
#
|
|
105
|
+
attr_reader :docs
|
|
106
|
+
|
|
107
|
+
# Whether the argument is required.
|
|
108
|
+
#
|
|
109
|
+
# @return [Boolean]
|
|
110
|
+
#
|
|
111
|
+
def required?
|
|
112
|
+
flag?("required")
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Whether the argument is optional.
|
|
116
|
+
#
|
|
117
|
+
# @return [Boolean]
|
|
118
|
+
#
|
|
119
|
+
def optional?
|
|
120
|
+
!required?
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module WebFunction
|
|
4
|
+
# Attributes define output fields that may be produced and returned by a Web Function {Endpoint} when the type of the
|
|
5
|
+
# return is `object`.
|
|
6
|
+
#
|
|
7
|
+
# See the [attributes section][0] on the Web Function website for more details about attribute definitions,
|
|
8
|
+
# recognized keys, and usage.
|
|
9
|
+
#
|
|
10
|
+
# [0]: https://webfunction.org/package#attributes
|
|
11
|
+
#
|
|
12
|
+
class Attribute
|
|
13
|
+
include Flaggable
|
|
14
|
+
|
|
15
|
+
def initialize(name:, type:, values: [], flags: [], docs: nil)
|
|
16
|
+
@name = name
|
|
17
|
+
@type = Type.parse(type)
|
|
18
|
+
@values = values
|
|
19
|
+
@flags = flags
|
|
20
|
+
@docs = docs.to_s
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
class << self
|
|
24
|
+
# Creates a new Attribute from a hash. Typically coming from a {Package}.
|
|
25
|
+
#
|
|
26
|
+
# @param attribute [Hash] The attribute hash
|
|
27
|
+
#
|
|
28
|
+
# @return [Attribute] A new Attribute instance
|
|
29
|
+
#
|
|
30
|
+
def from_hash(attribute)
|
|
31
|
+
unless attribute.is_a?(Hash)
|
|
32
|
+
return
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
unless attribute["name"]
|
|
36
|
+
return
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
unless attribute["type"]
|
|
40
|
+
return
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
new(
|
|
44
|
+
name: attribute["name"],
|
|
45
|
+
type: attribute["type"],
|
|
46
|
+
values: [*attribute["values"]],
|
|
47
|
+
flags: Utils.normalize_array_of_strings(attribute["flags"]),
|
|
48
|
+
docs: attribute["docs"],
|
|
49
|
+
)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Creates a new Attribute from an array of hashes. Typically coming from a {Package}. Uses {Attribute#from_hash}
|
|
53
|
+
# under the hood.
|
|
54
|
+
#
|
|
55
|
+
# @param attributes [Array<Hash>] The attribute array of hashes
|
|
56
|
+
#
|
|
57
|
+
# @return [Array<Attribute>] A new array of Attribute instances
|
|
58
|
+
#
|
|
59
|
+
def from_array(attributes)
|
|
60
|
+
Utils.normalize_array attributes do |attribute|
|
|
61
|
+
from_hash(attribute)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# The name of the attribute as it will appear in the endpoint's output
|
|
67
|
+
# object.
|
|
68
|
+
#
|
|
69
|
+
# This is required for the argument to be valid.
|
|
70
|
+
#
|
|
71
|
+
# @return [String]
|
|
72
|
+
#
|
|
73
|
+
attr_reader :name
|
|
74
|
+
|
|
75
|
+
# The type of value returned for this attribute. Must be one of:
|
|
76
|
+
#
|
|
77
|
+
# - object
|
|
78
|
+
# - array
|
|
79
|
+
# - string
|
|
80
|
+
# - number
|
|
81
|
+
# - boolean
|
|
82
|
+
#
|
|
83
|
+
# This is required for the argument to be valid.
|
|
84
|
+
#
|
|
85
|
+
# @return [String]
|
|
86
|
+
#
|
|
87
|
+
attr_reader :type
|
|
88
|
+
|
|
89
|
+
# An array specifying the exact, case-sensitive values that may be returned for this attribute. Each value in the
|
|
90
|
+
# values array must conform to the data type specified in the "type" key.
|
|
91
|
+
#
|
|
92
|
+
# This is useful for attributes that can only take a select set of values (enums or constants).
|
|
93
|
+
#
|
|
94
|
+
# @return [Array]
|
|
95
|
+
#
|
|
96
|
+
attr_reader :values
|
|
97
|
+
|
|
98
|
+
# A markdown string describing this attribute and its purpose in the output object. Used by documentation tools,
|
|
99
|
+
# and highly recommended.
|
|
100
|
+
#
|
|
101
|
+
# @return [String]
|
|
102
|
+
#
|
|
103
|
+
attr_reader :docs
|
|
104
|
+
|
|
105
|
+
# Whether the attribute can be null.
|
|
106
|
+
#
|
|
107
|
+
# @return [Boolean]
|
|
108
|
+
#
|
|
109
|
+
def nullable?
|
|
110
|
+
flag?("nullable")
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module WebFunction
|
|
4
|
+
# A {Client} is a wrapper around a Web Function {Package} that provides a convenient interface for invoking endpoints.
|
|
5
|
+
#
|
|
6
|
+
# @example
|
|
7
|
+
# client = WebFunction::Client.from_package_endpoint("https://api.webfunction.com/package")
|
|
8
|
+
# client.list_items(a: "b") # => { "c" => "d" }
|
|
9
|
+
#
|
|
10
|
+
class Client < BasicObject
|
|
11
|
+
def initialize(base_url:, endpoints: [], package: nil, bearer_auth: nil, version: nil, pipeline: nil)
|
|
12
|
+
@package = package
|
|
13
|
+
@base_url = base_url
|
|
14
|
+
@endpoints = endpoints.to_h { |e| [e.gsub("-", "_").to_sym, e] }
|
|
15
|
+
@bearer_auth = bearer_auth
|
|
16
|
+
@version = version
|
|
17
|
+
@pipeline = pipeline
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class << self
|
|
21
|
+
# Creates a new {Client} from an endpoint.
|
|
22
|
+
#
|
|
23
|
+
# @param url [String] The URL of the package endpoint
|
|
24
|
+
# @param bearer_auth [String] The bearer authentication token
|
|
25
|
+
# @param version [String] The API version to use
|
|
26
|
+
# @param pipelined [Boolean] Whether to have the client use call pipelining
|
|
27
|
+
#
|
|
28
|
+
# @return [Client]
|
|
29
|
+
#
|
|
30
|
+
def from_package_endpoint(url, bearer_auth: nil, version: nil, pipelined: false)
|
|
31
|
+
response = ::WebFunction::Request.execute(url, bearer_auth: bearer_auth, version: version)
|
|
32
|
+
package = ::WebFunction::Package.from_hash(response)
|
|
33
|
+
|
|
34
|
+
from_package(package, bearer_auth: bearer_auth, version: version, pipelined: pipelined)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Creates a new {Client} from an url.
|
|
38
|
+
#
|
|
39
|
+
# @param url [String] The URL of the package endpoint
|
|
40
|
+
# @param bearer_auth [String] The bearer authentication token
|
|
41
|
+
# @param version [String] The API version to use
|
|
42
|
+
# @param pipelined [Boolean] Whether to have the client use call pipelining
|
|
43
|
+
#
|
|
44
|
+
# @return [Client]
|
|
45
|
+
#
|
|
46
|
+
def from_url(url, bearer_auth: nil, version: nil, pipelined: false)
|
|
47
|
+
body = ::WebFunction::Utils.get_body_from_url(url, extra_query_params: { api_version: version })
|
|
48
|
+
package = ::WebFunction::Package.from_hash(::JSON.parse(body))
|
|
49
|
+
|
|
50
|
+
from_package(package, bearer_auth: bearer_auth, version: version, pipelined: pipelined)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Creates a new {Client} from a {Package}.
|
|
54
|
+
#
|
|
55
|
+
# @param package [Package] A package
|
|
56
|
+
# @param bearer_auth [String] The bearer authentication token
|
|
57
|
+
# @param version [String] The API version to use
|
|
58
|
+
# @param pipelined [Boolean] Whether to have the client use call pipelining
|
|
59
|
+
#
|
|
60
|
+
# @return [Client]
|
|
61
|
+
#
|
|
62
|
+
def from_package(package, bearer_auth: nil, version: nil, pipelined: nil)
|
|
63
|
+
pipeline = nil
|
|
64
|
+
|
|
65
|
+
if pipelined
|
|
66
|
+
pipeline = package.pipeline
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
client = new(
|
|
70
|
+
package: package,
|
|
71
|
+
base_url: package.base_url,
|
|
72
|
+
endpoints: package.endpoints.map(&:name),
|
|
73
|
+
bearer_auth: bearer_auth,
|
|
74
|
+
version: version,
|
|
75
|
+
pipeline: pipeline,
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
package.endpoints.each do |endpoint|
|
|
79
|
+
endpoint.client = client
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
client
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Call an endpoint by name with the given arguments.
|
|
87
|
+
#
|
|
88
|
+
# @param endpoint_name [String] The name of the endpoint to call
|
|
89
|
+
# @param args [Hash] The arguments to send to the endpoint
|
|
90
|
+
#
|
|
91
|
+
# @return [Object, Page] The decoded response returned by the endpoint.
|
|
92
|
+
# Paginated responses are wrapped in a {Page}.
|
|
93
|
+
#
|
|
94
|
+
def call(endpoint_name, args = {})
|
|
95
|
+
url = ::URI.join(@base_url, endpoint_name).to_s
|
|
96
|
+
request = ::WebFunction::Request.new(url,
|
|
97
|
+
bearer_auth: @bearer_auth,
|
|
98
|
+
version: @version,
|
|
99
|
+
args: args,
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
if @pipeline
|
|
103
|
+
@pipeline.add_step(request.as_pipeline_step)
|
|
104
|
+
else
|
|
105
|
+
request.execute
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# The package that this client is wrapping.
|
|
110
|
+
#
|
|
111
|
+
# @return [Package]
|
|
112
|
+
#
|
|
113
|
+
attr_reader :package
|
|
114
|
+
|
|
115
|
+
# The bearer authentication token.
|
|
116
|
+
#
|
|
117
|
+
# @param bearer_auth [String] The bearer authentication token
|
|
118
|
+
#
|
|
119
|
+
attr_writer :bearer_auth
|
|
120
|
+
|
|
121
|
+
# The API version to use.
|
|
122
|
+
#
|
|
123
|
+
# @param version [String] The API version to use
|
|
124
|
+
#
|
|
125
|
+
attr_writer :version
|
|
126
|
+
|
|
127
|
+
# The pipeline to use.
|
|
128
|
+
#
|
|
129
|
+
# @param pipeline [Pipeline] The pipeline to use
|
|
130
|
+
#
|
|
131
|
+
attr_writer :pipeline
|
|
132
|
+
|
|
133
|
+
def methods # :nodoc:
|
|
134
|
+
@endpoints.keys
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def nil? # :nodoc:
|
|
138
|
+
false
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def respond_to_missing?(method_name, include_private = false) # :nodoc:
|
|
142
|
+
@endpoints[method_name]
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def method_missing(method_name, *args) # :nodoc:
|
|
146
|
+
endpoint_name = @endpoints[method_name]
|
|
147
|
+
|
|
148
|
+
unless endpoint_name
|
|
149
|
+
super
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
call(endpoint_name, args.first)
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module WebFunction
|
|
4
|
+
# Represents an error definition as described in a Web Function package.
|
|
5
|
+
#
|
|
6
|
+
# An error definition documents the possible errors that an endpoint might return, including a machine-readable error
|
|
7
|
+
# code and a human-readable description.
|
|
8
|
+
#
|
|
9
|
+
# See the [error definition documentation][0] on the Web Function website for more details, including recognized keys
|
|
10
|
+
# and usage recommendations.
|
|
11
|
+
#
|
|
12
|
+
# [0]: https://webfunction.org/package#error-definition
|
|
13
|
+
#
|
|
14
|
+
class DocumentedError
|
|
15
|
+
def initialize(code:, docs: nil)
|
|
16
|
+
@code = code
|
|
17
|
+
@docs = docs.to_s
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class << self
|
|
21
|
+
# Creates a new DocumentedError from a hash.
|
|
22
|
+
#
|
|
23
|
+
# @param error [Hash] The error hash
|
|
24
|
+
#
|
|
25
|
+
# @return [DocumentedError] A new DocumentedError instance
|
|
26
|
+
#
|
|
27
|
+
def from_hash(error)
|
|
28
|
+
unless error.is_a?(Hash)
|
|
29
|
+
return
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
unless error["code"]
|
|
33
|
+
return
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
new(
|
|
37
|
+
code: error["code"],
|
|
38
|
+
docs: error["docs"],
|
|
39
|
+
)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Creates a new DocumentedError from an array of hashes. Uses {DocumentedError#from_hash} under the hood.
|
|
43
|
+
#
|
|
44
|
+
# @param errors [Array<Hash>] The error array of hashes
|
|
45
|
+
#
|
|
46
|
+
# @return [Array<DocumentedError>] A new array of DocumentedError instances
|
|
47
|
+
#
|
|
48
|
+
def from_array(errors)
|
|
49
|
+
Utils.normalize_array errors do |error|
|
|
50
|
+
from_hash(error)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# The machine-readable code of the error.
|
|
56
|
+
#
|
|
57
|
+
# @return [String]
|
|
58
|
+
#
|
|
59
|
+
attr_reader :code
|
|
60
|
+
|
|
61
|
+
# The documentation of the error.
|
|
62
|
+
#
|
|
63
|
+
# @return [String]
|
|
64
|
+
#
|
|
65
|
+
attr_reader :docs
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module WebFunction
|
|
4
|
+
# Represents an endpoint as described in a Web Function package.
|
|
5
|
+
#
|
|
6
|
+
# An endpoint defines an operation that can be performed via a Web Function API. Endpoints declare their name,
|
|
7
|
+
# documentation, arguments (inputs), attributes (outputs), and the possible errors that may occur when invoking them.
|
|
8
|
+
#
|
|
9
|
+
# Endpoints are described as objects in each package under the `"endpoints"` key. For more information, see:
|
|
10
|
+
#
|
|
11
|
+
# - [Web Function package docs](https://webfunction.org/package)
|
|
12
|
+
# - [Web Function endpoint docs](https://webfunction.org/endpoint)
|
|
13
|
+
#
|
|
14
|
+
# This class provides methods for accessing endpoint metadata (name, docs, arguments, attributes, errors) and
|
|
15
|
+
# supports invocation via HTTP.
|
|
16
|
+
#
|
|
17
|
+
# Typical tasks include:
|
|
18
|
+
#
|
|
19
|
+
# - Querying endpoint name or documentation
|
|
20
|
+
# - Enumerating the arguments or attributes definitions
|
|
21
|
+
# - Invoking the endpoint through HTTP using required inputs
|
|
22
|
+
#
|
|
23
|
+
# See: https://webfunction.org/endpoint for more details on endpoint structure and contract.
|
|
24
|
+
#
|
|
25
|
+
class Endpoint
|
|
26
|
+
include Flaggable
|
|
27
|
+
|
|
28
|
+
def initialize(name:, returns:, flags: [], group: nil, docs: nil, arguments: [], attributes: [], errors: [])
|
|
29
|
+
@name = name
|
|
30
|
+
@returns = Type.parse(returns)
|
|
31
|
+
@flags = flags
|
|
32
|
+
@group = group
|
|
33
|
+
@docs = docs
|
|
34
|
+
@arguments = arguments.to_h { |a| [a.name, a] }
|
|
35
|
+
@attributes = attributes.to_h { |a| [a.name, a] }
|
|
36
|
+
@errors = errors.to_h { |e| [e.code, e] }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
class << self
|
|
40
|
+
# Invokes an endpoint through HTTP using the given URL, bearer authentication, version, and arguments.
|
|
41
|
+
#
|
|
42
|
+
# @param url [String] The URL of the endpoint to invoke
|
|
43
|
+
# @param bearer_auth [String] The bearer authentication token
|
|
44
|
+
# @param version [String] The API version to use
|
|
45
|
+
# @param args [Hash] The arguments to send to the endpoint
|
|
46
|
+
#
|
|
47
|
+
# @return [Object] The response returned by the endpoint
|
|
48
|
+
#
|
|
49
|
+
def invoke(url, bearer_auth: nil, version: nil, args: {})
|
|
50
|
+
Request.execute(url, bearer_auth: bearer_auth, version: version, args: args)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Creates a new Endpoint from a hash.
|
|
54
|
+
#
|
|
55
|
+
# @param endpoint [Hash] The endpoint hash
|
|
56
|
+
#
|
|
57
|
+
# @return [Endpoint] A new Endpoint instance
|
|
58
|
+
#
|
|
59
|
+
def from_hash(endpoint)
|
|
60
|
+
unless endpoint.is_a?(Hash)
|
|
61
|
+
return
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
unless endpoint["name"]
|
|
65
|
+
return
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
unless endpoint["returns"]
|
|
69
|
+
return
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
new(
|
|
73
|
+
name: endpoint["name"],
|
|
74
|
+
returns: endpoint["returns"],
|
|
75
|
+
flags: Utils.normalize_array_of_strings(endpoint["flags"]),
|
|
76
|
+
group: endpoint["group"],
|
|
77
|
+
docs: endpoint["docs"].to_s,
|
|
78
|
+
arguments: Argument.from_array(endpoint["arguments"]),
|
|
79
|
+
attributes: Attribute.from_array(endpoint["attributes"]),
|
|
80
|
+
errors: DocumentedError.from_array(endpoint["errors"]),
|
|
81
|
+
)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Creates a new Endpoint from an array of hashes. Uses {Endpoint#from_hash} under the hood.
|
|
85
|
+
#
|
|
86
|
+
# @param endpoints [Array<Hash>] The endpoint array of hashes
|
|
87
|
+
#
|
|
88
|
+
# @return [Array<Endpoint>] A new array of Endpoint instances
|
|
89
|
+
#
|
|
90
|
+
def from_array(endpoints)
|
|
91
|
+
Utils.normalize_array endpoints do |endpoint|
|
|
92
|
+
from_hash(endpoint)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# The {Client} used to invoke this endpoint. It is assigned when the endpoint is loaded from a package and is
|
|
98
|
+
# required by {#call}.
|
|
99
|
+
#
|
|
100
|
+
# @return [Client, nil]
|
|
101
|
+
#
|
|
102
|
+
attr_accessor :client
|
|
103
|
+
|
|
104
|
+
# The suffix for the endpoint URL, appended to the package's base URL to form the full endpoint URL. Endpoint names
|
|
105
|
+
# are unique within a package; overloading (two endpoints sharing the same name) is not permitted.
|
|
106
|
+
#
|
|
107
|
+
# @return [String]
|
|
108
|
+
#
|
|
109
|
+
attr_reader :name
|
|
110
|
+
|
|
111
|
+
# The JSON type(s) returned by the endpoint. A non-empty array whose entries are each one of:
|
|
112
|
+
#
|
|
113
|
+
# - object
|
|
114
|
+
# - array
|
|
115
|
+
# - string
|
|
116
|
+
# - number
|
|
117
|
+
# - boolean
|
|
118
|
+
# - null
|
|
119
|
+
#
|
|
120
|
+
# @return [Array<String>]
|
|
121
|
+
#
|
|
122
|
+
attr_reader :returns
|
|
123
|
+
|
|
124
|
+
# A name used to categorize or group similar endpoints together. This should be used by documentation tools to
|
|
125
|
+
# organize related endpoints.
|
|
126
|
+
#
|
|
127
|
+
# @return [String, nil]
|
|
128
|
+
#
|
|
129
|
+
attr_reader :group
|
|
130
|
+
|
|
131
|
+
# Documentation for the endpoint. It must be formatted as markdown.
|
|
132
|
+
#
|
|
133
|
+
# @return [String]
|
|
134
|
+
#
|
|
135
|
+
attr_reader :docs
|
|
136
|
+
|
|
137
|
+
# Invokes the endpoint through its assigned {#client}, passing the given arguments.
|
|
138
|
+
#
|
|
139
|
+
# @param args [Hash] The arguments to send to the endpoint.
|
|
140
|
+
#
|
|
141
|
+
# @raise [RuntimeError] If no client has been assigned to the endpoint.
|
|
142
|
+
#
|
|
143
|
+
# @return [Object] The decoded response returned by the endpoint.
|
|
144
|
+
#
|
|
145
|
+
def call(args = {})
|
|
146
|
+
unless client
|
|
147
|
+
raise "Client must be set to invoke an endpoint"
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
client.call(name, args)
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# The list of errors specific to this endpoint. Clients SHOULD only refer to this list if the endpoint uses the
|
|
154
|
+
# `error_triple` flag. See the error specification for more information.
|
|
155
|
+
#
|
|
156
|
+
# @return [Array<DocumentedError>]
|
|
157
|
+
#
|
|
158
|
+
def errors
|
|
159
|
+
@errors.values
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Looks up a single endpoint error by its machine-readable code.
|
|
163
|
+
#
|
|
164
|
+
# @param code [String, Symbol] The error code to look up.
|
|
165
|
+
#
|
|
166
|
+
# @return [DocumentedError, nil] The matching error, or `nil` if none is found.
|
|
167
|
+
#
|
|
168
|
+
def error(code)
|
|
169
|
+
@errors[code.to_s]
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# The attributes of the object returned by the endpoint. Relevant when the endpoint returns an `object`.
|
|
173
|
+
#
|
|
174
|
+
# @return [Array<Attribute>]
|
|
175
|
+
#
|
|
176
|
+
def attributes
|
|
177
|
+
@attributes.values
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# Looks up a single returned attribute by name.
|
|
181
|
+
#
|
|
182
|
+
# @param name [String, Symbol] The name of the attribute to look up.
|
|
183
|
+
#
|
|
184
|
+
# @return [Attribute, nil] The matching attribute, or `nil` if none is found.
|
|
185
|
+
#
|
|
186
|
+
def attribute(name)
|
|
187
|
+
@attributes[name.to_s]
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# The arguments required by the endpoint. The array is empty when the endpoint requires no arguments.
|
|
191
|
+
#
|
|
192
|
+
# @return [Array<Argument>]
|
|
193
|
+
#
|
|
194
|
+
def arguments
|
|
195
|
+
@arguments.values
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# Looks up a single argument by name.
|
|
199
|
+
#
|
|
200
|
+
# @param name [String, Symbol] The name of the argument to look up.
|
|
201
|
+
#
|
|
202
|
+
# @return [Argument, nil] The matching argument, or `nil` if none is found.
|
|
203
|
+
#
|
|
204
|
+
def argument(name)
|
|
205
|
+
@arguments[name.to_s]
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# Whether the endpoint requires authentication via a bearer token, i.e. whether it declares the `bearer_auth` flag.
|
|
209
|
+
#
|
|
210
|
+
# @return [Boolean]
|
|
211
|
+
#
|
|
212
|
+
def bearer_auth?
|
|
213
|
+
flag?("bearer_auth")
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
# Whether the endpoint returns a bearer token in its response, i.e. whether it declares the `capture_bearer` flag.
|
|
217
|
+
# See the authentication specification for more information.
|
|
218
|
+
#
|
|
219
|
+
# @return [Boolean]
|
|
220
|
+
#
|
|
221
|
+
def capture_bearer?
|
|
222
|
+
flag?("capture_bearer")
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
# Whether the endpoint supports pagination, i.e. whether it declares the `paginated` flag.
|
|
226
|
+
#
|
|
227
|
+
# @return [Boolean]
|
|
228
|
+
#
|
|
229
|
+
def paginated?
|
|
230
|
+
flag?("paginated")
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
# Whether the endpoint is intended for internal use and is not part of the public API, i.e. whether it declares the
|
|
234
|
+
# `private` flag. Documentation tooling SHOULD omit endpoints with this flag from generated or
|
|
235
|
+
# published documentation.
|
|
236
|
+
#
|
|
237
|
+
# @return [Boolean]
|
|
238
|
+
#
|
|
239
|
+
def private?
|
|
240
|
+
flag?("private")
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
end
|