workato-connector-sdk 1.0.1 → 1.1.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/README.md +17 -11
- data/lib/workato/cli/edit_command.rb +4 -3
- data/lib/workato/cli/exec_command.rb +27 -35
- data/lib/workato/cli/generate_command.rb +1 -0
- data/lib/workato/cli/generators/connector_generator.rb +1 -0
- data/lib/workato/cli/generators/master_key_generator.rb +1 -0
- data/lib/workato/cli/main.rb +44 -11
- data/lib/workato/cli/oauth2_command.rb +6 -5
- data/lib/workato/cli/push_command.rb +8 -5
- data/lib/workato/cli/schema_command.rb +6 -7
- data/lib/workato/connector/sdk/account_properties.rb +1 -0
- data/lib/workato/connector/sdk/action.rb +78 -20
- data/lib/workato/connector/sdk/block_invocation_refinements.rb +1 -0
- data/lib/workato/connector/sdk/connection.rb +204 -44
- data/lib/workato/connector/sdk/connector.rb +200 -65
- data/lib/workato/connector/sdk/dsl/account_property.rb +1 -0
- data/lib/workato/connector/sdk/dsl/aws.rb +23 -27
- data/lib/workato/connector/sdk/dsl/call.rb +6 -2
- data/lib/workato/connector/sdk/dsl/error.rb +1 -0
- data/lib/workato/connector/sdk/dsl/http.rb +2 -7
- data/lib/workato/connector/sdk/dsl/lookup_table.rb +1 -0
- data/lib/workato/connector/sdk/dsl/time.rb +6 -0
- data/lib/workato/connector/sdk/dsl/workato_code_lib.rb +38 -0
- data/lib/workato/connector/sdk/dsl/workato_schema.rb +1 -0
- data/lib/workato/connector/sdk/dsl.rb +19 -4
- data/lib/workato/connector/sdk/errors.rb +62 -4
- data/lib/workato/connector/sdk/lookup_tables.rb +1 -0
- data/lib/workato/connector/sdk/object_definitions.rb +22 -17
- data/lib/workato/connector/sdk/operation.rb +127 -88
- data/lib/workato/connector/sdk/request.rb +95 -31
- data/lib/workato/connector/sdk/schema/field/array.rb +1 -0
- data/lib/workato/connector/sdk/schema/field/convertors.rb +1 -0
- data/lib/workato/connector/sdk/schema/field/date.rb +1 -0
- data/lib/workato/connector/sdk/schema/field/date_time.rb +1 -0
- data/lib/workato/connector/sdk/schema/field/integer.rb +1 -0
- data/lib/workato/connector/sdk/schema/field/number.rb +1 -0
- data/lib/workato/connector/sdk/schema/field/object.rb +1 -0
- data/lib/workato/connector/sdk/schema/field/string.rb +1 -0
- data/lib/workato/connector/sdk/schema/type/time.rb +1 -0
- data/lib/workato/connector/sdk/schema/type/unicode_string.rb +1 -0
- data/lib/workato/connector/sdk/schema.rb +1 -0
- data/lib/workato/connector/sdk/settings.rb +9 -4
- data/lib/workato/connector/sdk/summarize.rb +3 -2
- data/lib/workato/connector/sdk/trigger.rb +106 -10
- data/lib/workato/connector/sdk/version.rb +2 -1
- data/lib/workato/connector/sdk/workato_schemas.rb +1 -0
- data/lib/workato/connector/sdk/xml.rb +1 -0
- data/lib/workato/connector/sdk.rb +8 -0
- data/lib/workato/extension/array.rb +1 -0
- data/lib/workato/extension/case_sensitive_headers.rb +1 -0
- data/lib/workato/extension/currency.rb +2 -1
- data/lib/workato/extension/date.rb +1 -0
- data/lib/workato/extension/enumerable.rb +1 -0
- data/lib/workato/extension/extra_chain_cert.rb +1 -0
- data/lib/workato/extension/hash.rb +1 -0
- data/lib/workato/extension/integer.rb +1 -0
- data/lib/workato/extension/nil_class.rb +1 -0
- data/lib/workato/extension/object.rb +1 -0
- data/lib/workato/extension/phone.rb +2 -1
- data/lib/workato/extension/string.rb +6 -2
- data/lib/workato/extension/symbol.rb +1 -0
- data/lib/workato/extension/time.rb +1 -0
- data/lib/workato/testing/vcr_encrypted_cassette_serializer.rb +5 -0
- data/lib/workato/testing/vcr_multipart_body_matcher.rb +1 -0
- data/lib/workato/utilities/encoding.rb +57 -0
- data/lib/workato/web/app.rb +1 -0
- data/lib/workato-connector-sdk.rb +1 -0
- metadata +88 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 053e48199f2b1406ef47a84fb43d7b7d0cc74d74ce0f1f1b650c01fc422bc683
|
4
|
+
data.tar.gz: e2155ca61c45230234b105ff0f4ab033205c86b49b35838d88e8a8e473a957b3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4d34393bda1fc5eef5e138c7e742a2a05a7c1ced8fb5a4a8969a1770473c4534cf015c7096cf17a18eb69c669301ca8761ff51a88b3ee8a04ad4550467a23588
|
7
|
+
data.tar.gz: b293f65e21f45ef2bab573d687cd12cd77981a7375bec619ce45561ead9e96f895f633e65910dad7226213daacb38b95453c890b96e7b7a957b5085e5055ff94
|
data/README.md
CHANGED
@@ -248,8 +248,9 @@ Usage:
|
|
248
248
|
workato edit <PATH>
|
249
249
|
|
250
250
|
Options:
|
251
|
-
-k, [--key=KEY] # Path to file with encrypt/decrypt key.
|
252
|
-
|
251
|
+
-k, [--key=KEY] # Path to file with encrypt/decrypt key.
|
252
|
+
# NOTE: key from WORKATO_CONNECTOR_MASTER_KEY has higher priority
|
253
|
+
[--verbose], [--no-verbose]
|
253
254
|
|
254
255
|
Edit encrypted file, e.g. settings.yaml.enc
|
255
256
|
```
|
@@ -261,6 +262,7 @@ Edit encrypted file, e.g. settings.yaml.enc
|
|
261
262
|
### 3.3 workato exec
|
262
263
|
```
|
263
264
|
workato help exec
|
265
|
+
|
264
266
|
Usage:
|
265
267
|
workato exec <PATH>
|
266
268
|
|
@@ -268,7 +270,8 @@ Options:
|
|
268
270
|
-c, [--connector=CONNECTOR] # Path to connector source code
|
269
271
|
-s, [--settings=SETTINGS] # Path to plain or encrypted file with connection configs, passwords, tokens, secrets etc
|
270
272
|
-n, [--connection=CONNECTION] # Connection name if settings file contains multiple settings
|
271
|
-
-k, [--key=KEY] # Path to file with encrypt/decrypt key.
|
273
|
+
-k, [--key=KEY] # Path to file with encrypt/decrypt key.
|
274
|
+
# NOTE: key from WORKATO_CONNECTOR_MASTER_KEY has higher priority
|
272
275
|
-i, [--input=INPUT] # Path to file with input JSON
|
273
276
|
[--closure=CLOSURE] # Path to file with next poll closure JSON
|
274
277
|
[--continue=CONTINUE] # Path to file with next multistep action continue closure JSON
|
@@ -286,7 +289,7 @@ Options:
|
|
286
289
|
[--redirect-url=REDIRECT_URL] # OAuth2 callback url
|
287
290
|
[--refresh-token=REFRESH_TOKEN] # OAuth2 refresh token
|
288
291
|
[--debug], [--no-debug]
|
289
|
-
[--verbose], [--no-verbose]
|
292
|
+
[--verbose], [--no-verbose]
|
290
293
|
|
291
294
|
Description:
|
292
295
|
The 'workato exec' executes connector's lambda block at <PATH>. Lambda's parameters can be provided if needed, see options part.
|
@@ -394,13 +397,14 @@ Options:
|
|
394
397
|
-c, [--connector=CONNECTOR] # Path to connector source code
|
395
398
|
-s, [--settings=SETTINGS] # Path to plain or encrypted file with connection configs, passwords, tokens, secrets etc
|
396
399
|
-n, [--connection=CONNECTION] # Connection name if settings file contains multiple settings
|
397
|
-
-k, [--key=KEY] # Path to file with encrypt/decrypt key.
|
400
|
+
-k, [--key=KEY] # Path to file with encrypt/decrypt key.
|
401
|
+
# NOTE: key from WORKATO_CONNECTOR_MASTER_KEY has higher priority
|
398
402
|
[--port=PORT] # Listen requests on specific port
|
399
403
|
# Default: 45555
|
400
404
|
[--ip=IP] # Listen requests on specific interface
|
401
405
|
# Default: 127.0.0.1
|
402
406
|
[--https], [--no-https] # Start HTTPS server using self-signed certificate
|
403
|
-
[--verbose], [--no-verbose]
|
407
|
+
[--verbose], [--no-verbose]
|
404
408
|
|
405
409
|
Implements OAuth Authorization Code flow
|
406
410
|
```
|
@@ -420,11 +424,13 @@ Options:
|
|
420
424
|
-l, [--logo=LOGO] # Path to connector logo: png or jpeg file
|
421
425
|
-n, [--notes=NOTES] # Release notes
|
422
426
|
-c, [--connector=CONNECTOR] # Path to connector source code
|
423
|
-
[--api-email=API_EMAIL] # Email for accessing Workato API
|
424
|
-
|
425
|
-
[--
|
426
|
-
#
|
427
|
-
|
427
|
+
[--api-email=API_EMAIL] # Email for accessing Workato API.
|
428
|
+
# If present overrides value from WORKATO_API_EMAIL environment variable.
|
429
|
+
[--api-token=API_TOKEN] # Token for accessing Workato API.
|
430
|
+
# If present overrides value from WORKATO_API_TOKEN environment variable.
|
431
|
+
[--environment=ENVIRONMENT] # Data center specific URL to push connector code.
|
432
|
+
# If present overrides value from WORKATO_BASE_URL environment variable.
|
433
|
+
# Examples: 'https://app.workato.com', 'https://app.eu.workato.com'
|
428
434
|
[--folder=FOLDER] # Folder ID if you what to push to folder other than Home
|
429
435
|
[--verbose], [--no-verbose]
|
430
436
|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# typed: true
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require 'active_support/encrypted_configuration'
|
@@ -33,9 +34,9 @@ module Workato
|
|
33
34
|
|
34
35
|
private
|
35
36
|
|
36
|
-
attr_reader :key_path
|
37
|
-
|
38
|
-
|
37
|
+
attr_reader :key_path
|
38
|
+
attr_reader :encrypted_file_path
|
39
|
+
attr_reader :encrypted_config
|
39
40
|
|
40
41
|
def ensure_encryption_key_present
|
41
42
|
return if encrypted_config.key.present?
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# typed: false
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require 'thor'
|
@@ -24,8 +25,8 @@ module Workato
|
|
24
25
|
|
25
26
|
private
|
26
27
|
|
27
|
-
attr_reader :path
|
28
|
-
|
28
|
+
attr_reader :path
|
29
|
+
attr_reader :options
|
29
30
|
|
30
31
|
# rubocop:disable Style/GuardClause
|
31
32
|
def load_from_default_files
|
@@ -46,11 +47,9 @@ module Workato
|
|
46
47
|
|
47
48
|
def params
|
48
49
|
@params ||= {
|
49
|
-
connector: connector,
|
50
50
|
settings: settings,
|
51
51
|
input: from_json(options[:input]),
|
52
|
-
|
53
|
-
webhook_subscribe_output: from_json(options[:webhook_subscribe_output]).presence,
|
52
|
+
webhook_subscribe_output: from_json(options[:webhook_subscribe_output]),
|
54
53
|
args: from_json(options[:args]).presence || [],
|
55
54
|
extended_input_schema: from_json(options[:extended_input_schema]).presence || [],
|
56
55
|
extended_output_schema: from_json(options[:extended_output_schema]).presence || [],
|
@@ -69,7 +68,7 @@ module Workato
|
|
69
68
|
end
|
70
69
|
|
71
70
|
def connector
|
72
|
-
Workato::Connector::Sdk::Connector.from_file(
|
71
|
+
@connector ||= Workato::Connector::Sdk::Connector.from_file(
|
73
72
|
options[:connector] || Workato::Connector::Sdk::DEFAULT_CONNECTOR_PATH,
|
74
73
|
settings
|
75
74
|
)
|
@@ -85,16 +84,26 @@ module Workato
|
|
85
84
|
)
|
86
85
|
@settings = settings_store.read
|
87
86
|
|
88
|
-
Workato::Connector::Sdk::
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
break
|
87
|
+
Workato::Connector::Sdk::Connection.on_settings_update = lambda do |message, &refresher|
|
88
|
+
begin
|
89
|
+
$stdout.pause if verbose?
|
90
|
+
say('')
|
91
|
+
say(message)
|
92
|
+
|
93
|
+
new_settings = refresher.call
|
94
|
+
break unless new_settings
|
95
|
+
|
96
|
+
loop do
|
97
|
+
answer = ask('Updated settings file with new connection attributes? (Yes or No)').to_s.downcase
|
98
|
+
break new_settings if %w[n no].include?(answer)
|
99
|
+
next unless %w[y yes].include?(answer)
|
100
|
+
|
101
|
+
settings_store.update(new_settings)
|
102
|
+
break new_settings
|
103
|
+
end
|
104
|
+
ensure
|
105
|
+
$stdout.resume if verbose?
|
96
106
|
end
|
97
|
-
$stdout.resume if verbose?
|
98
107
|
end
|
99
108
|
|
100
109
|
@settings
|
@@ -103,9 +112,9 @@ module Workato
|
|
103
112
|
def from_json(path, parse_json_times: false)
|
104
113
|
old_parse_json_times = ActiveSupport.parse_json_times
|
105
114
|
::ActiveSupport.parse_json_times = parse_json_times
|
106
|
-
|
115
|
+
path ? ::ActiveSupport::JSON.decode(File.read(path)) : {}
|
116
|
+
ensure
|
107
117
|
::ActiveSupport.parse_json_times = old_parse_json_times
|
108
|
-
result
|
109
118
|
end
|
110
119
|
|
111
120
|
def inspect_params(params)
|
@@ -121,30 +130,13 @@ module Workato
|
|
121
130
|
end
|
122
131
|
|
123
132
|
def execute_path
|
124
|
-
|
125
|
-
method = methods.pop
|
126
|
-
object = methods.inject(params[:connector]) { |obj, m| obj.public_send(m) }
|
127
|
-
output = invoke_method(object, method)
|
128
|
-
if output.respond_to?(:invoke)
|
129
|
-
invoke_method(output, :invoke)
|
130
|
-
else
|
131
|
-
output
|
132
|
-
end
|
133
|
+
connector.invoke(path, params)
|
133
134
|
rescue Exception => e # rubocop:disable Lint/RescueException
|
134
135
|
raise DebugExceptionError, e if options[:debug]
|
135
136
|
|
136
137
|
raise
|
137
138
|
end
|
138
139
|
|
139
|
-
def invoke_method(object, method)
|
140
|
-
parameters = object.method(method).parameters.reject { |p| p[0] == :block }.map(&:second)
|
141
|
-
args = params.values_at(*parameters)
|
142
|
-
if parameters.last == :args
|
143
|
-
args = args.take(args.length - 1) + Array.wrap(args.last).flatten(1)
|
144
|
-
end
|
145
|
-
object.public_send(method, *args)
|
146
|
-
end
|
147
|
-
|
148
140
|
def show_output(output)
|
149
141
|
if options[:output].present?
|
150
142
|
File.open(options[:output], 'w') do |f|
|
data/lib/workato/cli/main.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# typed: true
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require 'thor'
|
@@ -40,8 +41,8 @@ module Workato
|
|
40
41
|
desc: 'Connection name if settings file contains multiple settings'
|
41
42
|
method_option :key, type: :string, aliases: '-k',
|
42
43
|
lazy_default: Workato::Connector::Sdk::DEFAULT_MASTER_KEY_PATH,
|
43
|
-
desc:
|
44
|
-
|
44
|
+
desc: "Path to file with encrypt/decrypt key.\n"\
|
45
|
+
"NOTE: key from #{Workato::Connector::Sdk::DEFAULT_MASTER_KEY_ENV} has higher priority"
|
45
46
|
method_option :input, type: :string, aliases: '-i', desc: 'Path to file with input JSON'
|
46
47
|
method_option :closure, type: :string, desc: 'Path to file with next poll closure JSON'
|
47
48
|
method_option :continue, type: :string, desc: 'Path to file with next multistep action continue closure JSON'
|
@@ -74,7 +75,7 @@ module Workato
|
|
74
75
|
|
75
76
|
method_option :key, type: :string, aliases: '-k',
|
76
77
|
lazy_default: Workato::Connector::Sdk::DEFAULT_MASTER_KEY_PATH,
|
77
|
-
desc:
|
78
|
+
desc: "Path to file with encrypt/decrypt key.\n"\
|
78
79
|
"NOTE: key from #{Workato::Connector::Sdk::DEFAULT_MASTER_KEY_ENV} has higher priority"
|
79
80
|
|
80
81
|
def edit(path)
|
@@ -126,17 +127,20 @@ module Workato
|
|
126
127
|
lazy_default: Workato::Connector::Sdk::DEFAULT_CONNECTOR_PATH
|
127
128
|
method_option :api_email,
|
128
129
|
type: :string,
|
129
|
-
desc:
|
130
|
-
"
|
130
|
+
desc: "Email for accessing Workato API.\n"\
|
131
|
+
"If present overrides value from #{Workato::Connector::Sdk::WORKATO_API_EMAIL_ENV} "\
|
132
|
+
'environment variable.'
|
131
133
|
method_option :api_token,
|
132
134
|
type: :string,
|
133
|
-
desc:
|
134
|
-
"
|
135
|
+
desc: "Token for accessing Workato API.\n" \
|
136
|
+
"If present overrides value from #{Workato::Connector::Sdk::WORKATO_API_TOKEN_ENV} "\
|
137
|
+
'environment variable.'
|
135
138
|
method_option :environment,
|
136
139
|
type: :string,
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
+
desc: "Data center specific URL to push connector code.\n"\
|
141
|
+
"If present overrides value from #{Workato::Connector::Sdk::WORKATO_BASE_URL_ENV} "\
|
142
|
+
"environment variable.\n"\
|
143
|
+
"Examples: 'https://app.workato.com', 'https://app.eu.workato.com'"
|
140
144
|
method_option :folder,
|
141
145
|
type: :string,
|
142
146
|
desc: 'Folder ID if you what to push to folder other than Home'
|
@@ -167,7 +171,7 @@ module Workato
|
|
167
171
|
type: :string,
|
168
172
|
aliases: '-k',
|
169
173
|
lazy_default: Workato::Connector::Sdk::DEFAULT_MASTER_KEY_PATH,
|
170
|
-
desc:
|
174
|
+
desc: "Path to file with encrypt/decrypt key.\n"\
|
171
175
|
"NOTE: key from #{Workato::Connector::Sdk::DEFAULT_MASTER_KEY_ENV} has higher priority"
|
172
176
|
method_option :port,
|
173
177
|
type: :string,
|
@@ -186,6 +190,35 @@ module Workato
|
|
186
190
|
options: options
|
187
191
|
).call
|
188
192
|
end
|
193
|
+
|
194
|
+
class << self
|
195
|
+
def print_options(shell, options, group_name = nil)
|
196
|
+
return if options.empty?
|
197
|
+
|
198
|
+
list = []
|
199
|
+
padding = options.map { |o| o.aliases.size }.max.to_i * 4
|
200
|
+
|
201
|
+
options.each do |option|
|
202
|
+
next if option.hide
|
203
|
+
|
204
|
+
description = []
|
205
|
+
description_lines = option.description ? option.description.split("\n") : []
|
206
|
+
first_line = description_lines.shift
|
207
|
+
description << [option.usage(padding), first_line ? "# #{first_line}" : '']
|
208
|
+
description_lines.each do |line|
|
209
|
+
description << ['', "# #{line}"]
|
210
|
+
end
|
211
|
+
|
212
|
+
list.concat(description)
|
213
|
+
list << ['', "# Default: #{option.default}"] if option.show_default?
|
214
|
+
list << ['', "# Possible values: #{option.enum.join(', ')}"] if option.enum
|
215
|
+
end
|
216
|
+
|
217
|
+
shell.say(group_name ? "#{group_name} options:" : 'Options:')
|
218
|
+
shell.print_table(list, indent: 2)
|
219
|
+
shell.say ''
|
220
|
+
end
|
221
|
+
end
|
189
222
|
end
|
190
223
|
end
|
191
224
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# typed: false
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require 'securerandom'
|
@@ -55,11 +56,11 @@ module Workato
|
|
55
56
|
|
56
57
|
private
|
57
58
|
|
58
|
-
attr_reader :https
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
59
|
+
attr_reader :https
|
60
|
+
attr_reader :base_url
|
61
|
+
attr_reader :redirect_url
|
62
|
+
attr_reader :port
|
63
|
+
attr_reader :options
|
63
64
|
|
64
65
|
def verbose?
|
65
66
|
!!options[:verbose]
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# typed: true
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require 'uri'
|
@@ -31,7 +32,9 @@ module Workato
|
|
31
32
|
|
32
33
|
def initialize(options:)
|
33
34
|
@options = options
|
34
|
-
@api_base_url = ENVIRONMENTS.fetch(options[:environment])
|
35
|
+
@api_base_url = ENVIRONMENTS.fetch(options[:environment]) do
|
36
|
+
options[:environment].presence || Workato::Connector::Sdk::WORKATO_BASE_URL
|
37
|
+
end
|
35
38
|
@api_email = options[:api_email] || ENV[Workato::Connector::Sdk::WORKATO_API_EMAIL_ENV]
|
36
39
|
@api_token = options[:api_token] || ENV[Workato::Connector::Sdk::WORKATO_API_TOKEN_ENV]
|
37
40
|
@folder_id = options[:folder]
|
@@ -55,10 +58,10 @@ module Workato
|
|
55
58
|
|
56
59
|
private
|
57
60
|
|
58
|
-
attr_reader :options
|
59
|
-
|
60
|
-
|
61
|
-
|
61
|
+
attr_reader :options
|
62
|
+
attr_reader :api_token
|
63
|
+
attr_reader :api_email
|
64
|
+
attr_reader :api_base_url
|
62
65
|
|
63
66
|
def verbose?
|
64
67
|
@options[:verbose]
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# typed: false
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module Workato
|
@@ -8,7 +9,6 @@ module Workato
|
|
8
9
|
SAMPLE_TO_SCHEMA_SUPPORT_TYPES = %w[csv json].freeze
|
9
10
|
CSV_SEPARATORS = %w[comma space tab colon semicolon pipe].freeze
|
10
11
|
|
11
|
-
WORKATO_BASE_URL = ENV['WORKATO_BASE_URL'] || 'https://app.workato.com'
|
12
12
|
API_GENERATE_SCHEMA_PATH = '/api/sdk/generate_schema'
|
13
13
|
|
14
14
|
def initialize(options:)
|
@@ -31,9 +31,9 @@ module Workato
|
|
31
31
|
|
32
32
|
private
|
33
33
|
|
34
|
-
attr_reader :options
|
35
|
-
|
36
|
-
|
34
|
+
attr_reader :options
|
35
|
+
attr_reader :api_token
|
36
|
+
attr_reader :api_email
|
37
37
|
|
38
38
|
def verbose?
|
39
39
|
@options[:verbose]
|
@@ -52,7 +52,7 @@ module Workato
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def sample_to_schema(sample)
|
55
|
-
url = "#{WORKATO_BASE_URL}#{API_GENERATE_SCHEMA_PATH}/#{sample.delete(:type)}"
|
55
|
+
url = "#{Workato::Connector::Sdk::WORKATO_BASE_URL}#{API_GENERATE_SCHEMA_PATH}/#{sample.delete(:type)}"
|
56
56
|
response = RestClient.post(
|
57
57
|
url,
|
58
58
|
sample.to_json,
|
@@ -74,8 +74,7 @@ module Workato
|
|
74
74
|
}
|
75
75
|
end
|
76
76
|
|
77
|
-
private_constant :API_GENERATE_SCHEMA_PATH
|
78
|
-
:WORKATO_BASE_URL
|
77
|
+
private_constant :API_GENERATE_SCHEMA_PATH
|
79
78
|
end
|
80
79
|
end
|
81
80
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# typed: strict
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require_relative './operation'
|
@@ -7,27 +8,52 @@ module Workato
|
|
7
8
|
module Connector
|
8
9
|
module Sdk
|
9
10
|
class Action < Operation
|
11
|
+
extend T::Sig
|
10
12
|
using BlockInvocationRefinements
|
11
13
|
|
12
|
-
RETRY_DEFAULT_CODES = [429, 500, 502, 503, 504, 507].freeze
|
13
|
-
RETRY_DEFAULT_METHODS = %i[get head].freeze
|
14
|
-
RETRY_DELAY = 5
|
14
|
+
RETRY_DEFAULT_CODES = T.let([429, 500, 502, 503, 504, 507].freeze, T::Array[Integer])
|
15
|
+
RETRY_DEFAULT_METHODS = T.let(%i[get head].freeze, T::Array[Symbol])
|
16
|
+
RETRY_DELAY = T.let(5, Integer) # seconds
|
15
17
|
MAX_RETRIES = 3
|
16
18
|
|
17
19
|
MAX_REINVOKES = 5
|
18
20
|
|
19
|
-
|
21
|
+
sig do
|
22
|
+
params(
|
23
|
+
action: SorbetTypes::SourceHash,
|
24
|
+
methods: SorbetTypes::SourceHash,
|
25
|
+
connection: Connection,
|
26
|
+
object_definitions: T.nilable(ObjectDefinitions)
|
27
|
+
).void
|
28
|
+
end
|
29
|
+
def initialize(action:, methods: {}, connection: Connection.new, object_definitions: nil)
|
20
30
|
super(
|
21
31
|
operation: action,
|
22
32
|
connection: connection,
|
23
33
|
methods: methods,
|
24
|
-
settings: settings,
|
25
34
|
object_definitions: object_definitions
|
26
35
|
)
|
27
36
|
|
37
|
+
@retries_left = T.let(0, Integer)
|
38
|
+
@retry_codes = T.let([], T::Array[Integer])
|
39
|
+
@retry_methods = T.let([], T::Array[String])
|
40
|
+
@retry_matchers = T.let([], T::Array[T.any(Symbol, String, Regexp)])
|
41
|
+
|
28
42
|
initialize_retry
|
29
43
|
end
|
30
44
|
|
45
|
+
sig do
|
46
|
+
params(
|
47
|
+
settings: T.nilable(SorbetTypes::SettingsHash),
|
48
|
+
input: SorbetTypes::OperationInputHash,
|
49
|
+
extended_input_schema: SorbetTypes::OperationSchema,
|
50
|
+
extended_output_schema: SorbetTypes::OperationSchema,
|
51
|
+
continue: T::Hash[T.any(Symbol, String), T.untyped],
|
52
|
+
block: T.nilable(SorbetTypes::OperationExecuteProc)
|
53
|
+
).returns(
|
54
|
+
T.untyped
|
55
|
+
)
|
56
|
+
end
|
31
57
|
def execute(settings = nil, input = {}, extended_input_schema = [], extended_output_schema = [], continue = {},
|
32
58
|
&block)
|
33
59
|
raise InvalidDefinitionError, "'execute' block is required for action" unless block || action[:execute]
|
@@ -39,7 +65,7 @@ module Workato
|
|
39
65
|
|
40
66
|
reinvoke_sleep if @reinvoke_after
|
41
67
|
|
42
|
-
|
68
|
+
reinvoke_reset
|
43
69
|
|
44
70
|
result = super(
|
45
71
|
settings,
|
@@ -52,15 +78,17 @@ module Workato
|
|
52
78
|
|
53
79
|
break result unless @reinvoke_after
|
54
80
|
|
55
|
-
continue = @reinvoke_after
|
81
|
+
continue = @reinvoke_after.continue
|
56
82
|
end
|
57
83
|
rescue RequestError => e
|
58
84
|
raise e unless retry?(e)
|
59
85
|
|
60
86
|
@retries_left -= 1
|
61
|
-
sleep(RETRY_DELAY)
|
87
|
+
sleep(RETRY_DELAY)
|
88
|
+
retry
|
62
89
|
end
|
63
90
|
|
91
|
+
sig { params(input: SorbetTypes::OperationInputHash).returns(T::Hash[T.any(String, Symbol), T.untyped]) }
|
64
92
|
def invoke(input = {})
|
65
93
|
extended_schema = extended_schema(nil, input)
|
66
94
|
config_schema = Schema.new(schema: config_fields_schema)
|
@@ -72,63 +100,93 @@ module Workato
|
|
72
100
|
apply_output_schema(output, output_schema)
|
73
101
|
end
|
74
102
|
|
103
|
+
sig do
|
104
|
+
params(
|
105
|
+
continue: T::Hash[T.untyped, T.untyped],
|
106
|
+
temp_output: T.nilable(T::Hash[T.untyped, T.untyped])
|
107
|
+
).void
|
108
|
+
end
|
75
109
|
def checkpoint!(continue:, temp_output: nil)
|
76
110
|
# no-op
|
77
111
|
end
|
78
112
|
|
79
|
-
|
113
|
+
sig do
|
114
|
+
params(
|
115
|
+
seconds: Integer,
|
116
|
+
continue: T::Hash[T.untyped, T.untyped],
|
117
|
+
temp_output: T.nilable(T::Hash[T.untyped, T.untyped])
|
118
|
+
).void
|
119
|
+
end
|
120
|
+
def reinvoke_after(seconds:, continue:, temp_output: nil) # rubocop:disable Lint/UnusedMethodArgument
|
121
|
+
@reinvokes_remaining = T.let(@reinvokes_remaining, T.nilable(Integer))
|
80
122
|
@reinvokes_remaining = (@reinvokes_remaining ? @reinvokes_remaining - 1 : reinvoke_limit)
|
81
|
-
@reinvoke_after =
|
123
|
+
@reinvoke_after = ReinvokeAfter.new(
|
82
124
|
seconds: seconds,
|
83
|
-
continue: continue
|
84
|
-
|
85
|
-
}
|
125
|
+
continue: continue
|
126
|
+
)
|
86
127
|
end
|
87
128
|
|
88
129
|
private
|
89
130
|
|
131
|
+
sig { returns(T::Array[T.any(Symbol, String, Regexp, Integer)]) }
|
90
132
|
def retry_on_response
|
91
133
|
Array(action[:retry_on_response])
|
92
134
|
end
|
93
135
|
|
136
|
+
sig { returns(T::Array[T.any(Symbol, String, Regexp, Integer)]) }
|
94
137
|
def retry_on_request
|
95
138
|
Array(action[:retry_on_request])
|
96
139
|
end
|
97
140
|
|
141
|
+
sig { returns(T.nilable(Integer)) }
|
98
142
|
def max_retries
|
99
143
|
action[:max_retries]
|
100
144
|
end
|
101
145
|
|
146
|
+
sig { void }
|
102
147
|
def initialize_retry
|
103
|
-
@retries_left = 0
|
104
148
|
return if retry_on_response.blank?
|
105
149
|
|
106
|
-
@retry_codes = []
|
107
|
-
@retry_matchers = []
|
108
150
|
retry_on_response.each { |m| m.is_a?(::Integer) ? @retry_codes << m : @retry_matchers << m }
|
109
151
|
@retry_codes = RETRY_DEFAULT_CODES if @retry_codes.empty?
|
110
152
|
@retry_methods = (retry_on_request.presence || RETRY_DEFAULT_METHODS).map(&:to_s).map(&:downcase)
|
111
153
|
@retries_left = [[max_retries.is_a?(::Integer) && max_retries || MAX_RETRIES, MAX_RETRIES].min, 0].max
|
112
154
|
end
|
113
155
|
|
156
|
+
sig { params(exception: RequestError).returns(T::Boolean) }
|
114
157
|
def retry?(exception)
|
115
|
-
return unless @retries_left.positive?
|
116
|
-
return unless @retry_codes.include?(exception.code.to_i)
|
117
|
-
return unless @retry_matchers.empty? || @retry_matchers.any? do |m|
|
158
|
+
return false unless @retries_left.positive?
|
159
|
+
return false unless @retry_codes.include?(exception.code.to_i)
|
160
|
+
return false unless @retry_matchers.empty? || @retry_matchers.any? do |m|
|
118
161
|
m === exception.message || m === exception.response
|
119
162
|
end
|
120
163
|
|
121
164
|
@retry_methods.include?(exception.method.to_s.downcase)
|
122
165
|
end
|
123
166
|
|
167
|
+
sig { void }
|
124
168
|
def reinvoke_sleep
|
125
|
-
sleep((ENV['WAIT_REINVOKE_AFTER'].presence || @reinvoke_after
|
169
|
+
sleep((ENV['WAIT_REINVOKE_AFTER'].presence || T.must(@reinvoke_after).seconds).to_f)
|
126
170
|
end
|
127
171
|
|
172
|
+
sig { returns(Integer) }
|
128
173
|
def reinvoke_limit
|
174
|
+
@reinvoke_limit = T.let(@reinvoke_limit, T.nilable(Integer))
|
129
175
|
@reinvoke_limit ||= (ENV['MAX_REINVOKES'].presence || MAX_REINVOKES).to_i
|
130
176
|
end
|
131
177
|
|
178
|
+
sig { void }
|
179
|
+
def reinvoke_reset
|
180
|
+
@reinvoke_after = T.let(nil, T.nilable(ReinvokeAfter))
|
181
|
+
end
|
182
|
+
|
183
|
+
class ReinvokeAfter < T::Struct
|
184
|
+
prop :seconds, T.any(Float, Integer)
|
185
|
+
prop :continue, T::Hash[T.untyped, T.untyped]
|
186
|
+
end
|
187
|
+
|
188
|
+
private_constant :ReinvokeAfter
|
189
|
+
|
132
190
|
alias action operation
|
133
191
|
end
|
134
192
|
end
|