workato-connector-sdk 1.0.1 → 1.0.2

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.
Files changed (67) hide show
  1. checksums.yaml +5 -5
  2. data/lib/workato/cli/edit_command.rb +4 -3
  3. data/lib/workato/cli/exec_command.rb +24 -35
  4. data/lib/workato/cli/generate_command.rb +1 -0
  5. data/lib/workato/cli/generators/connector_generator.rb +1 -0
  6. data/lib/workato/cli/generators/master_key_generator.rb +1 -0
  7. data/lib/workato/cli/main.rb +1 -0
  8. data/lib/workato/cli/oauth2_command.rb +6 -5
  9. data/lib/workato/cli/push_command.rb +5 -4
  10. data/lib/workato/cli/schema_command.rb +4 -3
  11. data/lib/workato/connector/sdk/account_properties.rb +1 -0
  12. data/lib/workato/connector/sdk/action.rb +78 -20
  13. data/lib/workato/connector/sdk/block_invocation_refinements.rb +1 -0
  14. data/lib/workato/connector/sdk/connection.rb +202 -44
  15. data/lib/workato/connector/sdk/connector.rb +200 -65
  16. data/lib/workato/connector/sdk/dsl/account_property.rb +1 -0
  17. data/lib/workato/connector/sdk/dsl/aws.rb +23 -27
  18. data/lib/workato/connector/sdk/dsl/call.rb +1 -0
  19. data/lib/workato/connector/sdk/dsl/error.rb +1 -0
  20. data/lib/workato/connector/sdk/dsl/http.rb +2 -7
  21. data/lib/workato/connector/sdk/dsl/lookup_table.rb +1 -0
  22. data/lib/workato/connector/sdk/dsl/time.rb +6 -0
  23. data/lib/workato/connector/sdk/dsl/workato_code_lib.rb +38 -0
  24. data/lib/workato/connector/sdk/dsl/workato_schema.rb +1 -0
  25. data/lib/workato/connector/sdk/dsl.rb +19 -4
  26. data/lib/workato/connector/sdk/errors.rb +4 -3
  27. data/lib/workato/connector/sdk/lookup_tables.rb +1 -0
  28. data/lib/workato/connector/sdk/object_definitions.rb +7 -8
  29. data/lib/workato/connector/sdk/operation.rb +127 -88
  30. data/lib/workato/connector/sdk/request.rb +45 -17
  31. data/lib/workato/connector/sdk/schema/field/array.rb +1 -0
  32. data/lib/workato/connector/sdk/schema/field/convertors.rb +1 -0
  33. data/lib/workato/connector/sdk/schema/field/date.rb +1 -0
  34. data/lib/workato/connector/sdk/schema/field/date_time.rb +1 -0
  35. data/lib/workato/connector/sdk/schema/field/integer.rb +1 -0
  36. data/lib/workato/connector/sdk/schema/field/number.rb +1 -0
  37. data/lib/workato/connector/sdk/schema/field/object.rb +1 -0
  38. data/lib/workato/connector/sdk/schema/field/string.rb +1 -0
  39. data/lib/workato/connector/sdk/schema/type/time.rb +1 -0
  40. data/lib/workato/connector/sdk/schema/type/unicode_string.rb +1 -0
  41. data/lib/workato/connector/sdk/schema.rb +1 -0
  42. data/lib/workato/connector/sdk/settings.rb +9 -4
  43. data/lib/workato/connector/sdk/summarize.rb +3 -2
  44. data/lib/workato/connector/sdk/trigger.rb +81 -7
  45. data/lib/workato/connector/sdk/version.rb +2 -1
  46. data/lib/workato/connector/sdk/workato_schemas.rb +1 -0
  47. data/lib/workato/connector/sdk/xml.rb +1 -0
  48. data/lib/workato/connector/sdk.rb +4 -0
  49. data/lib/workato/extension/array.rb +1 -0
  50. data/lib/workato/extension/case_sensitive_headers.rb +1 -0
  51. data/lib/workato/extension/currency.rb +1 -0
  52. data/lib/workato/extension/date.rb +1 -0
  53. data/lib/workato/extension/enumerable.rb +1 -0
  54. data/lib/workato/extension/extra_chain_cert.rb +1 -0
  55. data/lib/workato/extension/hash.rb +1 -0
  56. data/lib/workato/extension/integer.rb +1 -0
  57. data/lib/workato/extension/nil_class.rb +1 -0
  58. data/lib/workato/extension/object.rb +1 -0
  59. data/lib/workato/extension/phone.rb +1 -0
  60. data/lib/workato/extension/string.rb +2 -1
  61. data/lib/workato/extension/symbol.rb +1 -0
  62. data/lib/workato/extension/time.rb +1 -0
  63. data/lib/workato/testing/vcr_encrypted_cassette_serializer.rb +5 -0
  64. data/lib/workato/testing/vcr_multipart_body_matcher.rb +1 -0
  65. data/lib/workato/web/app.rb +1 -0
  66. data/lib/workato-connector-sdk.rb +1 -0
  67. metadata +64 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: 70241ed06aeae85f14f775ff2366ec4edbc54322aa034f0931dd987e9fd1fb2c
4
- data.tar.gz: 1a99f10c8c3c4dfe036e591cddb81504980586b0fb48cd319f7cfd5e510a1512
2
+ SHA1:
3
+ metadata.gz: f52b011085690e264b4e2082fb2f13c1375e74fe
4
+ data.tar.gz: 190c0bc7e6264ab9524acdda484e07154dd0b2b8
5
5
  SHA512:
6
- metadata.gz: b74c573b4e5c00509b955a14477a132ce01cfa6824382f21e50646bc10ce5ee44f3f2bf9bbf06ad7e565ddedfd0cce8c5017ae31e28e3b470164600abbb29d6d
7
- data.tar.gz: 1f1139718e2f18faa63087e3782c42a0bb0b3bae237086044873283bad8128f9ce42b26b3738d0a3a8ff22e529180a6d8df821f7c7eee9da68b85d3b97098340
6
+ metadata.gz: 29480d50f931dec0b0f18bf8f7c97f0a6029dd2656ba367ce0a3015a2a32e961bca9981083e01455d9c65cba2244dea5491b34d02e18a9cb8c4ac1a02f9a1d85
7
+ data.tar.gz: 1681f2fc8fc0eec6949361ae49ae26fdea3372eab98fb745e9d4a55d192b0e74a34d446655d2b5b08ede89d09cf748d4610ef86b08bab3210165de961004bbb6
@@ -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
- :encrypted_file_path,
38
- :encrypted_config
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
- :options
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
- output: from_json(options[:input]),
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,23 @@ module Workato
85
84
  )
86
85
  @settings = settings_store.read
87
86
 
88
- Workato::Connector::Sdk::Operation.on_settings_updated = lambda do |message, new_settings|
89
- $stdout.pause if verbose?
90
- say('')
91
- say(message)
92
- loop do
93
- answer = ask('Updated settings file with new connection attributes? (Yes or No)').to_s.downcase
94
- break if %w[n no].include?(answer)
95
- break settings_store.update(new_settings) if %w[y yes].include?(answer)
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
+ new_settings = refresher.call
93
+ loop do
94
+ answer = ask('Updated settings file with new connection attributes? (Yes or No)').to_s.downcase
95
+ break new_settings if %w[n no].include?(answer)
96
+ next unless %w[y yes].include?(answer)
97
+
98
+ settings_store.update(new_settings)
99
+ break new_settings
100
+ end
101
+ ensure
102
+ $stdout.resume if verbose?
96
103
  end
97
- $stdout.resume if verbose?
98
104
  end
99
105
 
100
106
  @settings
@@ -103,9 +109,9 @@ module Workato
103
109
  def from_json(path, parse_json_times: false)
104
110
  old_parse_json_times = ActiveSupport.parse_json_times
105
111
  ::ActiveSupport.parse_json_times = parse_json_times
106
- result = path ? ::ActiveSupport::JSON.decode(File.read(path)) : {}
112
+ path ? ::ActiveSupport::JSON.decode(File.read(path)) : {}
113
+ ensure
107
114
  ::ActiveSupport.parse_json_times = old_parse_json_times
108
- result
109
115
  end
110
116
 
111
117
  def inspect_params(params)
@@ -121,30 +127,13 @@ module Workato
121
127
  end
122
128
 
123
129
  def execute_path
124
- methods = path.split('.')
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
130
+ connector.invoke(path, params)
133
131
  rescue Exception => e # rubocop:disable Lint/RescueException
134
132
  raise DebugExceptionError, e if options[:debug]
135
133
 
136
134
  raise
137
135
  end
138
136
 
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
137
  def show_output(output)
149
138
  if options[:output].present?
150
139
  File.open(options[:output], 'w') do |f|
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Workato
@@ -1,3 +1,4 @@
1
+ # typed: false
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Workato
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Workato
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require 'thor'
@@ -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
- :base_url,
60
- :redirect_url,
61
- :port,
62
- :options
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'
@@ -55,10 +56,10 @@ module Workato
55
56
 
56
57
  private
57
58
 
58
- attr_reader :options,
59
- :api_token,
60
- :api_email,
61
- :api_base_url
59
+ attr_reader :options
60
+ attr_reader :api_token
61
+ attr_reader :api_email
62
+ attr_reader :api_base_url
62
63
 
63
64
  def verbose?
64
65
  @options[:verbose]
@@ -1,3 +1,4 @@
1
+ # typed: false
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Workato
@@ -31,9 +32,9 @@ module Workato
31
32
 
32
33
  private
33
34
 
34
- attr_reader :options,
35
- :api_token,
36
- :api_email
35
+ attr_reader :options
36
+ attr_reader :api_token
37
+ attr_reader :api_email
37
38
 
38
39
  def verbose?
39
40
  @options[:verbose]
@@ -1,3 +1,4 @@
1
+ # typed: false
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require 'csv'
@@ -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.seconds
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
- def initialize(action:, connection: {}, methods: {}, settings: {}, object_definitions: nil)
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
- @reinvoke_after = nil
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[:continue]
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) && retry
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
- def reinvoke_after(seconds:, continue:, temp_output: nil)
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
- temp_output: temp_output
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[:seconds]).to_f)
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
@@ -1,3 +1,4 @@
1
+ # typed: false
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Workato