web_function 0.4.1 → 0.5.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/exe/wfn +35 -0
- data/lib/web_function/argument.rb +81 -3
- data/lib/web_function/attribute.rb +74 -3
- data/lib/web_function/client.rb +31 -11
- data/lib/web_function/documented_error.rb +26 -2
- data/lib/web_function/endpoint.rb +166 -44
- data/lib/web_function/package.rb +30 -4
- data/lib/web_function/promise.rb +1 -1
- data/lib/web_function/version.rb +1 -1
- data/lib/web_function.rb +13 -3
- 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: c451f0b269e4441e7982d789b8fb4a4d827543e9d9f8769aa2bc4350a667435b
|
|
4
|
+
data.tar.gz: 1fe79584e5f3cd31f5792c63c7fed415cc999ccafbf736bb41f8a024c0c65690
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 07f4280c1e265f99898667f4860f1772088ae729fc41080ab27e2f6db1bd88d3611efc5314d2ab6b43c222c38be2f612772fd4167c41f8a5d17db6dd06aefa7c
|
|
7
|
+
data.tar.gz: 0b529bea38f2866549209a7d01fa5a8b126b17b79c4791ebf60ebd2407136dfabc7657c82efebea3275bbf9ad9b686943d797ccd3b397e2c6e124aab338a307f
|
data/exe/wfn
CHANGED
|
@@ -2,3 +2,38 @@
|
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "web_function"
|
|
5
|
+
require "json"
|
|
6
|
+
|
|
7
|
+
# Usage:
|
|
8
|
+
# wfn call --auth token endpoint_url key1=value1 [key2=value2 ...]
|
|
9
|
+
|
|
10
|
+
auth_token = nil
|
|
11
|
+
auth_idx = ARGV.index("--auth")
|
|
12
|
+
if auth_idx
|
|
13
|
+
auth_token = ARGV[auth_idx + 1]
|
|
14
|
+
ARGV.slice!(auth_idx, 2)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
command = ARGV[0]
|
|
18
|
+
|
|
19
|
+
case command
|
|
20
|
+
when "call"
|
|
21
|
+
endpoint_url = ARGV[1]
|
|
22
|
+
args = JSON.parse(ARGV[2] || "{}")
|
|
23
|
+
|
|
24
|
+
begin
|
|
25
|
+
response = WebFunction::Endpoint.invoke(endpoint_url, bearer_auth: auth_token, args: args)
|
|
26
|
+
puts JSON.pretty_generate(response)
|
|
27
|
+
rescue WebFunction::Error => e
|
|
28
|
+
puts e
|
|
29
|
+
warn "error: [#{e.code}] #{e.message}"
|
|
30
|
+
warn ""
|
|
31
|
+
if e.details
|
|
32
|
+
warn JSON.pretty_generate(e.details).lines.map { |line| "| #{line}" }.join
|
|
33
|
+
end
|
|
34
|
+
exit 2
|
|
35
|
+
end
|
|
36
|
+
else
|
|
37
|
+
warn "Usage:\n wfn docs package_url endpoint_name\n wfn call --auth token endpoint_url key1=value1 [key2=value2 ...]"
|
|
38
|
+
exit 1
|
|
39
|
+
end
|
|
@@ -1,29 +1,107 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module WebFunction
|
|
4
|
+
# # Argument
|
|
5
|
+
#
|
|
6
|
+
# Arguments used by Web Function endpoints to define its input parameters.
|
|
7
|
+
#
|
|
8
|
+
# See the [arguments section][0] on the Web Function website for more details.
|
|
9
|
+
#
|
|
10
|
+
# [0]: https://webfunction.org/package#arguments
|
|
11
|
+
#
|
|
4
12
|
class Argument
|
|
5
13
|
def initialize(argument)
|
|
6
14
|
@argument = argument
|
|
7
15
|
end
|
|
8
16
|
|
|
17
|
+
# ## Name
|
|
18
|
+
#
|
|
19
|
+
# The name of the argument.
|
|
20
|
+
#
|
|
21
|
+
# @return [String]
|
|
22
|
+
#
|
|
9
23
|
def name
|
|
10
24
|
@argument["name"]
|
|
11
25
|
end
|
|
12
26
|
|
|
27
|
+
# ## Type
|
|
28
|
+
#
|
|
29
|
+
# The type of the argument. It must be one of:
|
|
30
|
+
# - object
|
|
31
|
+
# - array
|
|
32
|
+
# - string
|
|
33
|
+
# - number
|
|
34
|
+
# - boolean
|
|
35
|
+
#
|
|
36
|
+
# @return [String]
|
|
37
|
+
#
|
|
13
38
|
def type
|
|
14
39
|
@argument["type"]
|
|
15
40
|
end
|
|
16
41
|
|
|
42
|
+
# ## Hint
|
|
43
|
+
#
|
|
44
|
+
# The hint of the argument
|
|
45
|
+
#
|
|
46
|
+
# See the [hints section][1] on the Web Function website for the full list
|
|
47
|
+
# of possible hints.
|
|
48
|
+
#
|
|
49
|
+
# @return [String]
|
|
50
|
+
#
|
|
51
|
+
# [1]: https://webfunction.org/package#hints
|
|
52
|
+
#
|
|
53
|
+
def hint
|
|
54
|
+
@argument["hint"]
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# ## Group
|
|
58
|
+
#
|
|
59
|
+
# A name used to categorize or group similar arguments together. This
|
|
60
|
+
# should be used by documentation tools to organize related arguments.
|
|
61
|
+
#
|
|
62
|
+
# @return [String]
|
|
63
|
+
#
|
|
64
|
+
def group
|
|
65
|
+
@argument["group"]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# ## Choices
|
|
69
|
+
#
|
|
70
|
+
# An array specifying the exact, case-sensitive values that are permitted
|
|
71
|
+
# for this argument. Each value in the choices array must conform to the
|
|
72
|
+
# data type specified in the argument's type key.
|
|
73
|
+
#
|
|
74
|
+
# Note that if the argument type is array, choices may contain strings or
|
|
75
|
+
# numbers representing the allowed values that can be included in the array.
|
|
76
|
+
#
|
|
77
|
+
# @return [Array]
|
|
78
|
+
#
|
|
17
79
|
def choices
|
|
18
|
-
|
|
80
|
+
[*@argument["choices"]]
|
|
19
81
|
end
|
|
20
82
|
|
|
83
|
+
# ## Flags
|
|
84
|
+
#
|
|
85
|
+
# List of argument flags. See the [available flags section][2] on the Web
|
|
86
|
+
# Function website for a complete list of flags available at the
|
|
87
|
+
# argument level.
|
|
88
|
+
#
|
|
89
|
+
# @return [Array<String>]
|
|
90
|
+
#
|
|
91
|
+
# [2]: https://webfunction.org/package#available-flags
|
|
92
|
+
#
|
|
21
93
|
def flags
|
|
22
|
-
|
|
94
|
+
[*@argument["flags"]].map { |flag| flag.to_s }
|
|
23
95
|
end
|
|
24
96
|
|
|
97
|
+
# ## Docs
|
|
98
|
+
#
|
|
99
|
+
# Description of the argument. It must be formatted as markdown.
|
|
100
|
+
#
|
|
101
|
+
# @return [String]
|
|
102
|
+
#
|
|
25
103
|
def docs
|
|
26
|
-
@argument["docs"]
|
|
104
|
+
@argument["docs"].to_s
|
|
27
105
|
end
|
|
28
106
|
end
|
|
29
107
|
end
|
|
@@ -1,29 +1,100 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module WebFunction
|
|
4
|
+
# # Attribute
|
|
5
|
+
#
|
|
6
|
+
# An Attribute defines an output field that may be produced and returned by a
|
|
7
|
+
# Web Function endpoint.
|
|
8
|
+
#
|
|
9
|
+
# See the [attributes section][0] on the Web Function website for more
|
|
10
|
+
# details about attribute definitions, recognized keys, and usage.
|
|
11
|
+
#
|
|
12
|
+
# [0]: https://webfunction.org/package#attributes
|
|
13
|
+
#
|
|
4
14
|
class Attribute
|
|
5
15
|
def initialize(attribute)
|
|
6
16
|
@attribute = attribute
|
|
7
17
|
end
|
|
8
18
|
|
|
19
|
+
# ## Name
|
|
20
|
+
#
|
|
21
|
+
# The name of the attribute as it will appear in the endpoint's output
|
|
22
|
+
# object.
|
|
23
|
+
#
|
|
24
|
+
# @return [String]
|
|
25
|
+
#
|
|
9
26
|
def name
|
|
10
27
|
@attribute["name"]
|
|
11
28
|
end
|
|
12
29
|
|
|
30
|
+
# ## Type
|
|
31
|
+
#
|
|
32
|
+
# The type of value returned for this attribute. Must be one of:
|
|
33
|
+
# - object
|
|
34
|
+
# - array
|
|
35
|
+
# - string
|
|
36
|
+
# - number
|
|
37
|
+
# - boolean
|
|
38
|
+
#
|
|
39
|
+
# This is a required string.
|
|
40
|
+
#
|
|
41
|
+
# @return [String]
|
|
42
|
+
#
|
|
13
43
|
def type
|
|
14
44
|
@attribute["type"]
|
|
15
45
|
end
|
|
16
46
|
|
|
47
|
+
# ## Hint
|
|
48
|
+
#
|
|
49
|
+
# A string hinting about the semantics of this attribute. See the
|
|
50
|
+
# [hints section][1] for possible values and documentation tooling guidance.
|
|
51
|
+
#
|
|
52
|
+
# [1]: https://webfunction.org/package#hints
|
|
53
|
+
#
|
|
54
|
+
# @return [String, nil]
|
|
55
|
+
#
|
|
56
|
+
def hint
|
|
57
|
+
@attribute["hint"]
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# ## Values
|
|
61
|
+
#
|
|
62
|
+
# An array specifying the exact, case-sensitive values that may be returned
|
|
63
|
+
# for this attribute. Each value in the values array must conform to the
|
|
64
|
+
# data type specified in the "type" key.
|
|
65
|
+
#
|
|
66
|
+
# This is useful for attributes that can only take a select set of values
|
|
67
|
+
# (enums or constants).
|
|
68
|
+
#
|
|
69
|
+
# @return [Array]
|
|
70
|
+
#
|
|
17
71
|
def values
|
|
18
|
-
|
|
72
|
+
[*@attribute["values"]]
|
|
19
73
|
end
|
|
20
74
|
|
|
75
|
+
# ## Flags
|
|
76
|
+
#
|
|
77
|
+
# An array of attribute flags. Flags describe special characteristics or
|
|
78
|
+
# behaviors of attributes. See the [available flags section][2] for
|
|
79
|
+
# complete list and documentation.
|
|
80
|
+
#
|
|
81
|
+
# [2]: https://webfunction.org/package#available-flags
|
|
82
|
+
#
|
|
83
|
+
# @return [Array<String>]
|
|
84
|
+
#
|
|
21
85
|
def flags
|
|
22
|
-
|
|
86
|
+
[*@attribute["flags"]].map(&:to_s)
|
|
23
87
|
end
|
|
24
88
|
|
|
89
|
+
# ## Docs
|
|
90
|
+
#
|
|
91
|
+
# A markdown string describing this attribute and its purpose in the output
|
|
92
|
+
# object. Used by documentation tools, and highly recommended.
|
|
93
|
+
#
|
|
94
|
+
# @return [String]
|
|
95
|
+
#
|
|
25
96
|
def docs
|
|
26
|
-
@attribute["docs"]
|
|
97
|
+
@attribute["docs"].to_s
|
|
27
98
|
end
|
|
28
99
|
end
|
|
29
100
|
end
|
data/lib/web_function/client.rb
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module WebFunction
|
|
4
|
-
|
|
4
|
+
# # Client
|
|
5
|
+
#
|
|
6
|
+
# A Client is a wrapper around a Web Function package that provides a
|
|
7
|
+
# convenient interface for invoking endpoints.
|
|
8
|
+
#
|
|
9
|
+
# @example
|
|
10
|
+
# client = WebFunction::Client.from_package_endpoint("https://api.webfunction.com/package")
|
|
11
|
+
# client.list_items(a: "b") # => { "c" => "d" }
|
|
12
|
+
#
|
|
13
|
+
class Client < BasicObject
|
|
5
14
|
def initialize(package, bearer_auth: nil, pipeline: nil)
|
|
6
15
|
@package = package
|
|
7
16
|
@endpoints = package.endpoints.to_h { |e| [e.name.gsub("-", "_").to_sym, e] }
|
|
@@ -11,42 +20,53 @@ module WebFunction
|
|
|
11
20
|
|
|
12
21
|
attr_reader :package
|
|
13
22
|
|
|
23
|
+
# ## Instantiates a new Client from a package endpoint
|
|
24
|
+
#
|
|
25
|
+
# Creates a new Client from a package endpoint.
|
|
26
|
+
#
|
|
27
|
+
# @param url [String] The URL of the package endpoint
|
|
28
|
+
# @param bearer_auth [String] The bearer authentication token
|
|
29
|
+
# @param pipeline_url [String] The URL of the pipeline endpoint
|
|
30
|
+
# @param pipeline [Pipeline] The pipeline to use
|
|
31
|
+
#
|
|
32
|
+
# @return [Client] A new Client instance
|
|
33
|
+
#
|
|
14
34
|
def self.from_package_endpoint(url, bearer_auth: nil, pipeline_url: nil, pipeline: nil)
|
|
15
|
-
response = Endpoint.invoke(url, bearer_auth: bearer_auth)
|
|
16
|
-
package = Package.new(response)
|
|
35
|
+
response = ::WebFunction::Endpoint.invoke(url, bearer_auth: bearer_auth)
|
|
36
|
+
package = ::WebFunction::Package.new(response)
|
|
17
37
|
|
|
18
|
-
if
|
|
19
|
-
pipeline = WebFunction::Pipeline.new(
|
|
38
|
+
if pipeline_url.is_a?(::String)
|
|
39
|
+
pipeline = ::WebFunction::Pipeline.new(pipeline_url)
|
|
20
40
|
end
|
|
21
41
|
|
|
22
42
|
new(package, bearer_auth: bearer_auth, pipeline: pipeline)
|
|
23
43
|
end
|
|
24
44
|
|
|
25
|
-
def methods
|
|
45
|
+
def methods #:nodoc:
|
|
26
46
|
super + @endpoints.keys
|
|
27
47
|
end
|
|
28
48
|
|
|
29
|
-
def respond_to_missing?(method_name, include_private = false)
|
|
49
|
+
def respond_to_missing?(method_name, include_private = false) #:nodoc:
|
|
30
50
|
@endpoints[method_name] || super
|
|
31
51
|
end
|
|
32
52
|
|
|
33
|
-
def method_missing(method_name, *args)
|
|
53
|
+
def method_missing(method_name, *args) #:nodoc:
|
|
34
54
|
endpoint = @endpoints[method_name]
|
|
35
55
|
|
|
36
56
|
unless endpoint
|
|
37
57
|
super
|
|
38
58
|
end
|
|
39
59
|
|
|
40
|
-
url = URI.join(@package.base_url, endpoint.name).to_s
|
|
60
|
+
url = ::URI.join(@package.base_url, endpoint.name).to_s
|
|
41
61
|
args = args.first
|
|
42
62
|
|
|
43
63
|
if @pipeline
|
|
44
|
-
step = Endpoint.
|
|
64
|
+
step = ::WebFunction::Endpoint.step(url, bearer_auth: @bearer_auth, args: args)
|
|
45
65
|
promise = @pipeline.add_step(step)
|
|
46
66
|
return promise
|
|
47
67
|
end
|
|
48
68
|
|
|
49
|
-
Endpoint.invoke(url, bearer_auth: @bearer_auth, args: args)
|
|
69
|
+
::WebFunction::Endpoint.invoke(url, bearer_auth: @bearer_auth, args: args)
|
|
50
70
|
end
|
|
51
71
|
end
|
|
52
72
|
end
|
|
@@ -1,15 +1,39 @@
|
|
|
1
1
|
module WebFunction
|
|
2
|
+
# # DocumentedError
|
|
3
|
+
#
|
|
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,
|
|
7
|
+
# including a machine-readable error code and a human-readable description.
|
|
8
|
+
#
|
|
9
|
+
# See the [error definition documentation][0] on the Web Function website for more details,
|
|
10
|
+
# including recognized keys and usage recommendations.
|
|
11
|
+
#
|
|
12
|
+
# [0]: https://webfunction.org/package#error-definition
|
|
13
|
+
#
|
|
2
14
|
class DocumentedError
|
|
3
15
|
def initialize(error)
|
|
4
16
|
@error = error
|
|
5
17
|
end
|
|
6
18
|
|
|
19
|
+
# ## Code
|
|
20
|
+
#
|
|
21
|
+
# The code of the error.
|
|
22
|
+
#
|
|
23
|
+
# @return [String]
|
|
24
|
+
#
|
|
7
25
|
def code
|
|
8
26
|
@error["code"]
|
|
9
27
|
end
|
|
10
28
|
|
|
29
|
+
# ## Docs
|
|
30
|
+
#
|
|
31
|
+
# The documentation of the error.
|
|
32
|
+
#
|
|
33
|
+
# @return [String]
|
|
34
|
+
#
|
|
11
35
|
def docs
|
|
12
|
-
@error["docs"]
|
|
36
|
+
@error["docs"].to_s
|
|
13
37
|
end
|
|
14
38
|
end
|
|
15
|
-
end
|
|
39
|
+
end
|
|
@@ -1,67 +1,155 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module WebFunction
|
|
4
|
+
# # Endpoint
|
|
5
|
+
#
|
|
6
|
+
# Represents an endpoint as described in a Web Function package.
|
|
7
|
+
#
|
|
8
|
+
# An endpoint defines an operation that can be performed via a Web Function API.
|
|
9
|
+
# Endpoints declare their name, documentation, arguments (inputs), attributes (outputs), and
|
|
10
|
+
# the possible errors that may occur when invoking them.
|
|
11
|
+
#
|
|
12
|
+
# Endpoints are described as objects in each package under the `"endpoints"` key.
|
|
13
|
+
# For more information, see:
|
|
14
|
+
# - [Web Function package docs](https://webfunction.org/package)
|
|
15
|
+
# - [Web Function endpoint docs](https://webfunction.org/endpoint)
|
|
16
|
+
#
|
|
17
|
+
# This class provides methods for accessing endpoint metadata (name, docs, arguments, attributes, errors)
|
|
18
|
+
# and supports invocation via HTTP.
|
|
19
|
+
#
|
|
20
|
+
# Typical tasks include:
|
|
21
|
+
# - Querying endpoint name or documentation
|
|
22
|
+
# - Enumerating the arguments or attributes definitions
|
|
23
|
+
# - Invoking the endpoint through HTTP using required inputs
|
|
24
|
+
#
|
|
25
|
+
# See: https://webfunction.org/endpoint for more details on endpoint structure and contract.
|
|
26
|
+
#
|
|
4
27
|
class Endpoint
|
|
5
28
|
def initialize(endpoint)
|
|
6
29
|
@endpoint = endpoint
|
|
7
30
|
end
|
|
8
31
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
32
|
+
class << self
|
|
33
|
+
# ## HTTP client getter
|
|
34
|
+
#
|
|
35
|
+
# The HTTP client used to invoke the endpoint.
|
|
36
|
+
#
|
|
37
|
+
# @return [Proc]
|
|
38
|
+
#
|
|
39
|
+
def http_client
|
|
40
|
+
@http_client ||= proc do |url, headers, body|
|
|
41
|
+
response = Excon.post(url,
|
|
42
|
+
headers: headers,
|
|
43
|
+
body: body,
|
|
44
|
+
)
|
|
45
|
+
[response.status, response.body]
|
|
46
|
+
end
|
|
18
47
|
end
|
|
19
48
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
49
|
+
# ## HTTP client setter
|
|
50
|
+
#
|
|
51
|
+
# Sets the HTTP client used to invoke the endpoint.
|
|
52
|
+
#
|
|
53
|
+
# To provide a custom HTTP client instead of the default (which uses Excon),
|
|
54
|
+
# set this to any object responding to #call or a Proc/lambda.
|
|
55
|
+
#
|
|
56
|
+
# The contract is:
|
|
57
|
+
# client.call(url, headers, body)
|
|
58
|
+
#
|
|
59
|
+
# - url: [String] The full URL to post to (not just the hostname or path).
|
|
60
|
+
# - headers:[Hash<String,String>] HTTP headers, e.g. { "Content-Type" => "application/json" }
|
|
61
|
+
# - body: [String] The JSON body to post.
|
|
62
|
+
#
|
|
63
|
+
# The client must return a two-element Array: [status, body]:
|
|
64
|
+
# - status: [Integer] HTTP status code (e.g. 200, 400, 500)
|
|
65
|
+
# - body: [String] Raw response body as a string
|
|
66
|
+
#
|
|
67
|
+
# Example:
|
|
68
|
+
# WebFunction::Endpoint.http_client = ->(url, headers, args) {
|
|
69
|
+
# http_response = MyHTTP.post(url, headers: headers, body: JSON.generate(args))
|
|
70
|
+
# [http_response.status, http_response.body]
|
|
71
|
+
# }
|
|
72
|
+
#
|
|
73
|
+
# @param http_client [Proc,#call] The new HTTP client to use.
|
|
74
|
+
#
|
|
75
|
+
attr_writer :http_client
|
|
76
|
+
|
|
77
|
+
def step(url, bearer_auth: nil, args: {})
|
|
78
|
+
headers = {
|
|
79
|
+
"Content-Type": "application/json",
|
|
80
|
+
"Accept": "application/json",
|
|
81
|
+
"User-Agent": "webfunction/#{WebFunction::VERSION}",
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if args.nil?
|
|
85
|
+
args = {}
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
if bearer_auth
|
|
89
|
+
headers["Authorization"] = "Bearer #{bearer_auth}"
|
|
90
|
+
end
|
|
23
91
|
|
|
24
|
-
|
|
25
|
-
return {
|
|
92
|
+
{
|
|
26
93
|
url: url,
|
|
27
94
|
headers: headers,
|
|
28
95
|
body: args,
|
|
29
96
|
}
|
|
30
97
|
end
|
|
31
98
|
|
|
32
|
-
|
|
33
|
-
headers
|
|
34
|
-
|
|
35
|
-
|
|
99
|
+
def invoke(url, bearer_auth: nil, args: {})
|
|
100
|
+
headers = {
|
|
101
|
+
"Content-Type": "application/json",
|
|
102
|
+
"Accept": "application/json",
|
|
103
|
+
"User-Agent": "webfunction/#{WebFunction::VERSION}",
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if args.nil?
|
|
107
|
+
args = {}
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
if bearer_auth
|
|
111
|
+
headers["Authorization"] = "Bearer #{bearer_auth}"
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
status, body = http_client.call(url, headers, JSON.generate(args))
|
|
115
|
+
|
|
116
|
+
unless [200, 400].include?(status)
|
|
117
|
+
raise WebFunction::UnexpectedStatusCodeError.new("Unexpected status code (#{status})",
|
|
118
|
+
details: {
|
|
119
|
+
status_code: status,
|
|
120
|
+
raw_body: body,
|
|
121
|
+
},
|
|
122
|
+
)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
begin
|
|
126
|
+
result = JSON.parse(body)
|
|
127
|
+
rescue JSON::ParserError => e
|
|
128
|
+
raise WebFunction::JsonParseError.new(e.message,
|
|
129
|
+
details: {
|
|
130
|
+
status_code: status,
|
|
131
|
+
raw_body: body,
|
|
132
|
+
original_exception: e,
|
|
133
|
+
},
|
|
134
|
+
)
|
|
135
|
+
end
|
|
36
136
|
|
|
37
|
-
|
|
137
|
+
if status == 400
|
|
138
|
+
code = "BAD_REQUEST"
|
|
139
|
+
message = "Bad request"
|
|
140
|
+
details = { body: result }
|
|
38
141
|
|
|
39
|
-
|
|
40
|
-
case result
|
|
41
|
-
when Array
|
|
42
|
-
if result.length == 3 && result[0].is_a?(String) && result[1].is_a?(String)
|
|
142
|
+
if result.is_a?(Array) && result.length == 3 && result[0].is_a?(String) && result[1].is_a?(String)
|
|
43
143
|
code = result[0]
|
|
44
144
|
message = result[1]
|
|
45
145
|
details = result[2]
|
|
46
|
-
|
|
47
|
-
raise WebFunction::Error.new(message, code: code, details: details)
|
|
48
|
-
else
|
|
49
|
-
raise WebFunction::Error.new("Bad request", details: result)
|
|
50
146
|
end
|
|
51
|
-
|
|
52
|
-
raise WebFunction::
|
|
53
|
-
else
|
|
54
|
-
raise WebFunction::Error.new("Bad request", details: result)
|
|
147
|
+
|
|
148
|
+
raise WebFunction::BadRequestError.new(message, code: code, details: details)
|
|
55
149
|
end
|
|
56
|
-
end
|
|
57
150
|
|
|
58
|
-
|
|
59
|
-
raise WebFunction::Error.new("Unexpected status code [#{response.status}]")
|
|
151
|
+
result
|
|
60
152
|
end
|
|
61
|
-
|
|
62
|
-
result
|
|
63
|
-
rescue JSON::ParserError => e
|
|
64
|
-
raise WebFunction::Error.new("Response cannot be parsed", details: {})
|
|
65
153
|
end
|
|
66
154
|
|
|
67
155
|
def name
|
|
@@ -69,11 +157,15 @@ module WebFunction
|
|
|
69
157
|
end
|
|
70
158
|
|
|
71
159
|
def returns
|
|
72
|
-
|
|
160
|
+
[*@endpoint["returns"]].map { |type| type.to_s }
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def hints
|
|
164
|
+
[*@endpoint["hints"]].map { |hint| hint.to_s }
|
|
73
165
|
end
|
|
74
166
|
|
|
75
167
|
def flags
|
|
76
|
-
|
|
168
|
+
[*@endpoint["flags"]].map { |flag| flag.to_s }
|
|
77
169
|
end
|
|
78
170
|
|
|
79
171
|
def group
|
|
@@ -81,7 +173,7 @@ module WebFunction
|
|
|
81
173
|
end
|
|
82
174
|
|
|
83
175
|
def docs
|
|
84
|
-
@endpoint["docs"]
|
|
176
|
+
@endpoint["docs"].to_s
|
|
85
177
|
end
|
|
86
178
|
|
|
87
179
|
def arguments
|
|
@@ -89,7 +181,17 @@ module WebFunction
|
|
|
89
181
|
return []
|
|
90
182
|
end
|
|
91
183
|
|
|
92
|
-
@endpoint["arguments"].map
|
|
184
|
+
@endpoint["arguments"].map do |argument|
|
|
185
|
+
unless argument.is_a?(Hash)
|
|
186
|
+
next
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
unless argument["name"]
|
|
190
|
+
next
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
Argument.new(argument)
|
|
194
|
+
end
|
|
93
195
|
end
|
|
94
196
|
|
|
95
197
|
def attributes
|
|
@@ -97,7 +199,17 @@ module WebFunction
|
|
|
97
199
|
return []
|
|
98
200
|
end
|
|
99
201
|
|
|
100
|
-
@endpoint["attributes"].map
|
|
202
|
+
@endpoint["attributes"].map do |attribute|
|
|
203
|
+
unless attribute.is_a?(Hash)
|
|
204
|
+
next
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
unless attribute["name"]
|
|
208
|
+
next
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
Attribute.new(attribute)
|
|
212
|
+
end
|
|
101
213
|
end
|
|
102
214
|
|
|
103
215
|
def errors
|
|
@@ -105,7 +217,17 @@ module WebFunction
|
|
|
105
217
|
return []
|
|
106
218
|
end
|
|
107
219
|
|
|
108
|
-
@endpoint["errors"].map
|
|
220
|
+
@endpoint["errors"].map do |error|
|
|
221
|
+
unless error.is_a?(Hash)
|
|
222
|
+
next
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
unless error["code"]
|
|
226
|
+
next
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
DocumentedError.new(error)
|
|
230
|
+
end
|
|
109
231
|
end
|
|
110
232
|
end
|
|
111
233
|
end
|
data/lib/web_function/package.rb
CHANGED
|
@@ -15,11 +15,17 @@ module WebFunction
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def flags
|
|
18
|
-
@package["flags"]
|
|
18
|
+
unless @package["flags"].is_a?(Array)
|
|
19
|
+
return []
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
@package["flags"].each do |flag|
|
|
23
|
+
flag.to_s
|
|
24
|
+
end
|
|
19
25
|
end
|
|
20
26
|
|
|
21
27
|
def docs
|
|
22
|
-
@package["docs"]
|
|
28
|
+
@package["docs"].to_s
|
|
23
29
|
end
|
|
24
30
|
|
|
25
31
|
def endpoints
|
|
@@ -27,7 +33,17 @@ module WebFunction
|
|
|
27
33
|
return []
|
|
28
34
|
end
|
|
29
35
|
|
|
30
|
-
@package["endpoints"].map
|
|
36
|
+
@package["endpoints"].map do |endpoint|
|
|
37
|
+
unless endpoint.is_a?(Hash)
|
|
38
|
+
next
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
unless endpoint["name"]
|
|
42
|
+
next
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
Endpoint.new(endpoint)
|
|
46
|
+
end
|
|
31
47
|
end
|
|
32
48
|
|
|
33
49
|
def errors
|
|
@@ -35,7 +51,17 @@ module WebFunction
|
|
|
35
51
|
return []
|
|
36
52
|
end
|
|
37
53
|
|
|
38
|
-
@package["errors"].map
|
|
54
|
+
@package["errors"].map do |error|
|
|
55
|
+
unless error.is_a?(Hash)
|
|
56
|
+
next
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
unless error["code"]
|
|
60
|
+
next
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
DocumentedError.new(error)
|
|
64
|
+
end
|
|
39
65
|
end
|
|
40
66
|
end
|
|
41
67
|
end
|
data/lib/web_function/promise.rb
CHANGED
data/lib/web_function/version.rb
CHANGED
data/lib/web_function.rb
CHANGED
|
@@ -15,15 +15,25 @@ require_relative "web_function/pipeline"
|
|
|
15
15
|
require_relative "web_function/promise"
|
|
16
16
|
|
|
17
17
|
module WebFunction
|
|
18
|
-
UnresolvedPromise = Class.new(StandardError)
|
|
19
|
-
|
|
20
18
|
class Error < StandardError
|
|
21
19
|
attr_reader :code, :details
|
|
22
20
|
|
|
23
|
-
def initialize(message = nil, code:
|
|
21
|
+
def initialize(message = nil, code: self.class.name, details: nil)
|
|
24
22
|
super(message)
|
|
25
23
|
@code = code
|
|
26
24
|
@details = details
|
|
27
25
|
end
|
|
28
26
|
end
|
|
27
|
+
|
|
28
|
+
class UnresolvedPromiseError < Error
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
class UnexpectedStatusCodeError < Error
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
class JsonParseError < Error
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
class BadRequestError < Error
|
|
38
|
+
end
|
|
29
39
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: web_function
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Robin Clart
|
|
@@ -88,7 +88,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
88
88
|
- !ruby/object:Gem::Version
|
|
89
89
|
version: '0'
|
|
90
90
|
requirements: []
|
|
91
|
-
rubygems_version: 4.0.
|
|
91
|
+
rubygems_version: 4.0.11
|
|
92
92
|
specification_version: 4
|
|
93
93
|
summary: A Web Function Client for Ruby
|
|
94
94
|
test_files: []
|