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.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +17 -11
  3. data/lib/workato/cli/edit_command.rb +4 -3
  4. data/lib/workato/cli/exec_command.rb +27 -35
  5. data/lib/workato/cli/generate_command.rb +1 -0
  6. data/lib/workato/cli/generators/connector_generator.rb +1 -0
  7. data/lib/workato/cli/generators/master_key_generator.rb +1 -0
  8. data/lib/workato/cli/main.rb +44 -11
  9. data/lib/workato/cli/oauth2_command.rb +6 -5
  10. data/lib/workato/cli/push_command.rb +8 -5
  11. data/lib/workato/cli/schema_command.rb +6 -7
  12. data/lib/workato/connector/sdk/account_properties.rb +1 -0
  13. data/lib/workato/connector/sdk/action.rb +78 -20
  14. data/lib/workato/connector/sdk/block_invocation_refinements.rb +1 -0
  15. data/lib/workato/connector/sdk/connection.rb +204 -44
  16. data/lib/workato/connector/sdk/connector.rb +200 -65
  17. data/lib/workato/connector/sdk/dsl/account_property.rb +1 -0
  18. data/lib/workato/connector/sdk/dsl/aws.rb +23 -27
  19. data/lib/workato/connector/sdk/dsl/call.rb +6 -2
  20. data/lib/workato/connector/sdk/dsl/error.rb +1 -0
  21. data/lib/workato/connector/sdk/dsl/http.rb +2 -7
  22. data/lib/workato/connector/sdk/dsl/lookup_table.rb +1 -0
  23. data/lib/workato/connector/sdk/dsl/time.rb +6 -0
  24. data/lib/workato/connector/sdk/dsl/workato_code_lib.rb +38 -0
  25. data/lib/workato/connector/sdk/dsl/workato_schema.rb +1 -0
  26. data/lib/workato/connector/sdk/dsl.rb +19 -4
  27. data/lib/workato/connector/sdk/errors.rb +62 -4
  28. data/lib/workato/connector/sdk/lookup_tables.rb +1 -0
  29. data/lib/workato/connector/sdk/object_definitions.rb +22 -17
  30. data/lib/workato/connector/sdk/operation.rb +127 -88
  31. data/lib/workato/connector/sdk/request.rb +95 -31
  32. data/lib/workato/connector/sdk/schema/field/array.rb +1 -0
  33. data/lib/workato/connector/sdk/schema/field/convertors.rb +1 -0
  34. data/lib/workato/connector/sdk/schema/field/date.rb +1 -0
  35. data/lib/workato/connector/sdk/schema/field/date_time.rb +1 -0
  36. data/lib/workato/connector/sdk/schema/field/integer.rb +1 -0
  37. data/lib/workato/connector/sdk/schema/field/number.rb +1 -0
  38. data/lib/workato/connector/sdk/schema/field/object.rb +1 -0
  39. data/lib/workato/connector/sdk/schema/field/string.rb +1 -0
  40. data/lib/workato/connector/sdk/schema/type/time.rb +1 -0
  41. data/lib/workato/connector/sdk/schema/type/unicode_string.rb +1 -0
  42. data/lib/workato/connector/sdk/schema.rb +1 -0
  43. data/lib/workato/connector/sdk/settings.rb +9 -4
  44. data/lib/workato/connector/sdk/summarize.rb +3 -2
  45. data/lib/workato/connector/sdk/trigger.rb +106 -10
  46. data/lib/workato/connector/sdk/version.rb +2 -1
  47. data/lib/workato/connector/sdk/workato_schemas.rb +1 -0
  48. data/lib/workato/connector/sdk/xml.rb +1 -0
  49. data/lib/workato/connector/sdk.rb +8 -0
  50. data/lib/workato/extension/array.rb +1 -0
  51. data/lib/workato/extension/case_sensitive_headers.rb +1 -0
  52. data/lib/workato/extension/currency.rb +2 -1
  53. data/lib/workato/extension/date.rb +1 -0
  54. data/lib/workato/extension/enumerable.rb +1 -0
  55. data/lib/workato/extension/extra_chain_cert.rb +1 -0
  56. data/lib/workato/extension/hash.rb +1 -0
  57. data/lib/workato/extension/integer.rb +1 -0
  58. data/lib/workato/extension/nil_class.rb +1 -0
  59. data/lib/workato/extension/object.rb +1 -0
  60. data/lib/workato/extension/phone.rb +2 -1
  61. data/lib/workato/extension/string.rb +6 -2
  62. data/lib/workato/extension/symbol.rb +1 -0
  63. data/lib/workato/extension/time.rb +1 -0
  64. data/lib/workato/testing/vcr_encrypted_cassette_serializer.rb +5 -0
  65. data/lib/workato/testing/vcr_multipart_body_matcher.rb +1 -0
  66. data/lib/workato/utilities/encoding.rb +57 -0
  67. data/lib/workato/web/app.rb +1 -0
  68. data/lib/workato-connector-sdk.rb +1 -0
  69. metadata +88 -17
@@ -1,3 +1,4 @@
1
+ # typed: false
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require 'delegate'
@@ -8,24 +9,25 @@ require 'net/http'
8
9
  require 'net/http/digest_auth'
9
10
 
10
11
  require_relative './block_invocation_refinements'
12
+ require_relative './../../utilities/encoding'
11
13
 
12
14
  module Workato
13
15
  module Connector
14
16
  module Sdk
15
17
  class Request < SimpleDelegator
18
+ extend T::Sig
19
+
16
20
  using BlockInvocationRefinements
17
21
 
18
- def initialize(uri, method: 'GET', settings: {}, connection: nil, action: nil)
22
+ def initialize(uri, method: 'GET', connection: nil, action: nil)
19
23
  super(nil)
20
24
  @uri = uri
21
25
  @method = method
22
- @settings = settings
23
- @authorization = connection&.authorization
24
- @base_uri = connection&.base_uri(settings)
26
+ @connection = connection
27
+ @base_uri = connection&.base_uri(connection&.settings || {})
25
28
  @action = action
26
29
  @headers = {}
27
30
  @case_sensitive_headers = {}
28
- @params = {}.with_indifferent_access
29
31
  @render_request = ->(payload) { payload }
30
32
  @parse_response = ->(payload) { payload }
31
33
  @after_response = ->(_response_code, parsed_response, _response_headers) { parsed_response }
@@ -56,7 +58,7 @@ module Workato
56
58
  detect_error!(response.body)
57
59
  parsed_response = @parse_response.call(response)
58
60
  detect_error!(parsed_response)
59
- within_action_context(response.code, parsed_response, response.headers, &@after_response)
61
+ apply_after_response(response.code, parsed_response, response.headers)
60
62
  end
61
63
  )
62
64
  rescue RestClient::Exception => e
@@ -79,7 +81,12 @@ module Workato
79
81
  end
80
82
 
81
83
  def params(params)
82
- @params.merge!(params)
84
+ if params.is_a?(Hash)
85
+ @params ||= HashWithIndifferentAccess.new
86
+ @params.merge!(params)
87
+ else
88
+ @params = params
89
+ end
83
90
  self
84
91
  end
85
92
 
@@ -140,13 +147,17 @@ module Workato
140
147
 
141
148
  def request_format_json
142
149
  @content_type_header = :json
143
- @render_request = ->(payload) { ActiveSupport::JSON.encode(payload) if payload }
150
+ @render_request = lambda_with_error_wrap(JSONRequestFormatError) do |payload|
151
+ ActiveSupport::JSON.encode(payload) if payload
152
+ end
144
153
  self
145
154
  end
146
155
 
147
156
  def response_format_json
148
157
  @accept_header = :json
149
- @parse_response = ->(payload) { ActiveSupport::JSON.decode(payload.presence || '{}') }
158
+ @parse_response = lambda_with_error_wrap(JSONResponseFormatError) do |payload|
159
+ ActiveSupport::JSON.decode(payload.presence || '{}')
160
+ end
150
161
  self
151
162
  end
152
163
 
@@ -156,17 +167,19 @@ module Workato
156
167
 
157
168
  def request_format_xml(root_element_name, namespaces = {})
158
169
  @content_type_header = :xml
159
- @render_request = Kernel.lambda { |payload|
170
+ @render_request = lambda_with_error_wrap(XMLRequestFormatError) do |payload|
160
171
  next unless payload
161
172
 
162
173
  Gyoku.xml({ root_element_name => payload.merge(namespaces).deep_symbolize_keys }, key_converter: :none)
163
- }
174
+ end
164
175
  self
165
176
  end
166
177
 
167
178
  def response_format_xml(strip_response_namespaces: false)
168
179
  @accept_header = :xml
169
- @parse_response = ->(payload) { Xml.parse_xml_to_hash(payload, strip_namespaces: strip_response_namespaces) }
180
+ @parse_response = lambda_with_error_wrap(XMLResponseFormatError) do |payload|
181
+ Xml.parse_xml_to_hash(payload, strip_namespaces: strip_response_namespaces)
182
+ end
170
183
  self
171
184
  end
172
185
 
@@ -177,7 +190,7 @@ module Workato
177
190
  end
178
191
 
179
192
  def response_format_raw
180
- @parse_response = Kernel.lambda do |payload|
193
+ @parse_response = lambda_with_error_wrap(RAWResponseFormatError) do |payload|
181
194
  payload.body.force_encoding(::Encoding::BINARY)
182
195
  payload.body.valid_encoding? ? payload.body : payload.body.force_encoding(::Encoding::BINARY)
183
196
  end
@@ -187,7 +200,7 @@ module Workato
187
200
  def request_format_multipart_form
188
201
  @content_type_header = nil
189
202
 
190
- @render_request = Kernel.lambda do |payload|
203
+ @render_request = lambda_with_error_wrap(MultipartFormRequestFormatError) do |payload|
191
204
  payload&.each_with_object({}) do |(name, (value, content_type, original_filename)), rendered|
192
205
  rendered[name] = if content_type.present?
193
206
  Part.new(name, content_type, original_filename || ::File.basename(name), value.to_s)
@@ -202,7 +215,7 @@ module Workato
202
215
 
203
216
  def request_format_www_form_urlencoded
204
217
  @content_type_header = 'application/x-www-form-urlencoded'
205
- @render_request = Kernel.lambda { |payload| payload.to_param }
218
+ @render_request = lambda_with_error_wrap(WWWFormURLEncodedRequestFormatError, &:to_param)
206
219
  self
207
220
  end
208
221
 
@@ -226,6 +239,8 @@ module Workato
226
239
  OpenSSL::X509::Certificate.new(intermediate)
227
240
  end
228
241
  self
242
+ rescue OpenSSL::OpenSSLError => e
243
+ Kernel.raise(RequestTLSCertificateFormatError, e)
229
244
  end
230
245
 
231
246
  def tls_server_certs(certificates:, strict: true)
@@ -235,6 +250,16 @@ module Workato
235
250
  @ssl_cert_store.add_cert(OpenSSL::X509::Certificate.new(certificate))
236
251
  end
237
252
  self
253
+ rescue OpenSSL::OpenSSLError => e
254
+ Kernel.raise(RequestTLSCertificateFormatError, e)
255
+ end
256
+
257
+ def puts(*args)
258
+ ::Kernel.puts(*args)
259
+ end
260
+
261
+ def try(*args, &block)
262
+ execute!.try(*args, &block)
238
263
  end
239
264
 
240
265
  private
@@ -289,14 +314,14 @@ module Workato
289
314
  URI.parse(@uri)
290
315
  end
291
316
 
292
- return uri.to_s unless @params.any? || @user || @password
317
+ return uri.to_s unless @params || @user || @password
293
318
 
294
319
  unless @digest_auth
295
320
  uri.user = URI.encode_www_form_component(@user) if @user
296
321
  uri.password = URI.encode_www_form_component(@password) if @password
297
322
  end
298
323
 
299
- return uri.to_s unless @params.any?
324
+ return uri.to_s unless @params
300
325
 
301
326
  query = uri.query.to_s.split('&').select(&:present?).join('&').presence
302
327
  params = @params.to_param.presence
@@ -321,9 +346,9 @@ module Workato
321
346
  end
322
347
 
323
348
  def detect_error!(response)
324
- return unless @authorization
349
+ return unless authorized?
325
350
 
326
- error_patterns = @authorization.detect_on
351
+ error_patterns = connection.authorization.detect_on
327
352
  return unless error_patterns.any? { |pattern| pattern === response rescue false }
328
353
 
329
354
  Kernel.raise(CustomRequestError, response.to_s)
@@ -354,39 +379,76 @@ module Workato
354
379
  )
355
380
  end
356
381
 
382
+ def apply_after_response(code, parsed_response, headers)
383
+ encoded_headers = (headers || {}).each_with_object(HashWithIndifferentAccess.new) do |(k, v), h|
384
+ h[k] = Workato::Utilities::Encoding.force_best_encoding!(v.to_s)
385
+ end
386
+ within_action_context(code, parsed_response, encoded_headers, &@after_response)
387
+ end
388
+
357
389
  def within_action_context(*args, &block)
358
390
  (@action || self).instance_exec(*args, &block)
359
391
  end
360
392
 
393
+ sig { returns(T::Boolean) }
394
+ def authorized?
395
+ !!@connection&.authorization?
396
+ end
397
+
361
398
  def authorized
362
- return yield unless @authorization
399
+ return yield unless authorized?
363
400
 
364
- apply = @authorization.source[:apply] || @authorization.source[:credentials]
401
+ apply = connection.authorization.source[:apply] || connection.authorization.source[:credentials]
365
402
  return yield unless apply
366
403
 
367
404
  first = true
368
405
  begin
369
- settings = @settings.with_indifferent_access
370
- if /oauth2/i =~ @authorization.type
406
+ settings = connection.settings
407
+ if /oauth2/i =~ connection.authorization.type
371
408
  instance_exec(settings, settings[:access_token], @auth_type, &apply)
372
409
  else
373
410
  instance_exec(settings, @auth_type, &apply)
374
411
  end
375
412
  yield
376
- rescue StandardError => e
413
+ rescue RestClient::Exception, CustomRequestError => e
377
414
  Kernel.raise e unless first
378
- Kernel.raise e unless @action&.refresh_authorization!(
379
- e.try(:http_code),
380
- e.try(:http_body),
381
- e.message,
382
- @settings
383
- )
415
+ Kernel.raise e unless refresh_authorization!(e.try(:http_code), e.try(:http_body), e.message)
384
416
 
385
417
  first = false
386
418
  retry
387
419
  end
388
420
  end
389
421
 
422
+ sig do
423
+ params(
424
+ http_code: T.nilable(Integer),
425
+ http_body: T.nilable(String),
426
+ exception: T.nilable(String)
427
+ ).returns(T::Boolean)
428
+ end
429
+ def refresh_authorization!(http_code, http_body, exception)
430
+ return false unless connection.authorization.refresh?(http_code, http_body, exception)
431
+
432
+ connection.update_settings!("Refresh token triggered on response \"#{exception}\"") do
433
+ connection.authorization.refresh!(connection.settings)
434
+ end
435
+ end
436
+
437
+ sig { returns(Connection) }
438
+ def connection
439
+ T.must(@connection)
440
+ end
441
+
442
+ def lambda_with_error_wrap(error_type, &block)
443
+ Kernel.lambda do |payload|
444
+ begin
445
+ block.call(payload)
446
+ rescue StandardError => e
447
+ Kernel.raise error_type.new(e)
448
+ end
449
+ end
450
+ end
451
+
390
452
  class Part < StringIO
391
453
  def initialize(path, content_type, original_filename, *args)
392
454
  super(*args)
@@ -395,7 +457,9 @@ module Workato
395
457
  @original_filename = original_filename
396
458
  end
397
459
 
398
- attr_reader :path, :content_type, :original_filename
460
+ attr_reader :path
461
+ attr_reader :content_type
462
+ attr_reader :original_filename
399
463
  end
400
464
  end
401
465
  end
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require_relative './convertors'
@@ -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
  require_relative './convertors'
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require_relative './convertors'
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require_relative './convertors'
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require_relative './convertors'
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require_relative './convertors'
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require_relative './convertors'
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require 'time'
@@ -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: false
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require 'active_support/encrypted_configuration'
@@ -5,6 +6,10 @@ require 'active_support/encrypted_configuration'
5
6
  module Workato
6
7
  module Connector
7
8
  module Sdk
9
+ module SorbetTypes
10
+ SettingsHash = T.type_alias { T.any(HashWithIndifferentAccess, T::Hash[T.any(Symbol, String), T.untyped]) }
11
+ end
12
+
8
13
  class Settings
9
14
  class << self
10
15
  def from_file(path = DEFAULT_SETTINGS_PATH, name = nil)
@@ -68,10 +73,10 @@ module Workato
68
73
 
69
74
  private
70
75
 
71
- attr_reader :key_path,
72
- :name,
73
- :path,
74
- :encrypted
76
+ attr_reader :key_path
77
+ attr_reader :name
78
+ attr_reader :path
79
+ attr_reader :encrypted
75
80
 
76
81
  def read_plain_file
77
82
  all_settings = File.open(path) do |f|
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Workato
@@ -29,8 +30,8 @@ module Workato
29
30
 
30
31
  private
31
32
 
32
- attr_reader :data,
33
- :paths
33
+ attr_reader :data
34
+ attr_reader :paths
34
35
 
35
36
  def above_summarization_limit?(candidate)
36
37
  candidate.is_a?(::Array) && candidate.length > ARRAY_SUMMARIZATION_LIMIT ||
@@ -1,3 +1,4 @@
1
+ # typed: strict
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require 'securerandom'
@@ -5,19 +6,55 @@ require 'securerandom'
5
6
  module Workato
6
7
  module Connector
7
8
  module Sdk
9
+ module SorbetTypes
10
+ WebhookSubscribeOutputHash = T.type_alias { T::Hash[T.any(String, Symbol), T.untyped] }
11
+
12
+ WebhookNotificationPayload = T.type_alias { T.untyped }
13
+
14
+ TriggerEventHash = T.type_alias { T::Hash[T.untyped, T.untyped] }
15
+
16
+ WebhookNotificationOutputHash = T.type_alias { T.any(T::Array[TriggerEventHash], TriggerEventHash) }
17
+
18
+ PollOutputHash = T.type_alias do
19
+ {
20
+ 'events' => T::Array[TriggerEventHash],
21
+ 'can_poll_more' => T.nilable(T::Boolean),
22
+ 'next_poll' => T.untyped
23
+ }
24
+ end
25
+ end
26
+
8
27
  class Trigger < Operation
9
28
  using BlockInvocationRefinements
10
29
 
11
- def initialize(trigger:, connection: {}, methods: {}, settings: {}, object_definitions: nil)
30
+ sig do
31
+ params(
32
+ trigger: SorbetTypes::SourceHash,
33
+ methods: SorbetTypes::SourceHash,
34
+ connection: Connection,
35
+ object_definitions: T.nilable(ObjectDefinitions)
36
+ ).void
37
+ end
38
+ def initialize(trigger:, methods: {}, connection: Connection.new, object_definitions: nil)
12
39
  super(
13
40
  operation: trigger,
14
41
  connection: connection,
15
42
  methods: methods,
16
- settings: settings,
17
43
  object_definitions: object_definitions
18
44
  )
19
45
  end
20
46
 
47
+ sig do
48
+ params(
49
+ settings: T.nilable(SorbetTypes::SettingsHash),
50
+ input: SorbetTypes::OperationInputHash,
51
+ closure: T.untyped,
52
+ extended_input_schema: SorbetTypes::OperationSchema,
53
+ extended_output_schema: SorbetTypes::OperationSchema
54
+ ).returns(
55
+ SorbetTypes::PollOutputHash
56
+ )
57
+ end
21
58
  def poll_page(settings = nil, input = {}, closure = nil, extended_input_schema = [],
22
59
  extended_output_schema = [])
23
60
  poll_proc = trigger[:poll]
@@ -29,13 +66,27 @@ module Workato
29
66
  ) do |connection, payload, eis, eos|
30
67
  instance_exec(connection, payload[:input], payload[:closure], eis, eos, &poll_proc)
31
68
  end
32
- output[:events] = ::Array.wrap(output[:events]).reverse!.uniq(&trigger[:dedup])
69
+ output.with_indifferent_access
70
+ output[:events] = Array.wrap(output[:events])
71
+ .reverse!
72
+ .map! { |event| ::Hash.try_convert(event) || event }
33
73
  output[:next_poll] = output[:next_poll].presence || closure
34
74
  output
35
75
  end
36
76
 
77
+ sig do
78
+ params(
79
+ settings: T.nilable(SorbetTypes::SettingsHash),
80
+ input: SorbetTypes::OperationInputHash,
81
+ closure: T.untyped,
82
+ extended_input_schema: SorbetTypes::OperationSchema,
83
+ extended_output_schema: SorbetTypes::OperationSchema
84
+ ).returns(
85
+ SorbetTypes::PollOutputHash
86
+ )
87
+ end
37
88
  def poll(settings = nil, input = {}, closure = nil, extended_input_schema = [], extended_output_schema = [])
38
- events = []
89
+ events = T.let([], T::Array[SorbetTypes::TriggerEventHash])
39
90
 
40
91
  loop do
41
92
  output = poll_page(settings, input, closure, extended_input_schema, extended_output_schema)
@@ -46,16 +97,31 @@ module Workato
46
97
  end
47
98
 
48
99
  {
49
- events: events.uniq(&trigger[:dedup]),
100
+ events: events,
50
101
  can_poll_more: false,
51
102
  next_poll: closure
52
103
  }.with_indifferent_access
53
104
  end
54
105
 
106
+ sig { params(input: SorbetTypes::TriggerEventHash).returns(T.untyped) }
55
107
  def dedup(input = {})
56
108
  trigger[:dedup].call(input)
57
109
  end
58
110
 
111
+ sig do
112
+ params(
113
+ input: SorbetTypes::OperationInputHash,
114
+ payload: SorbetTypes::WebhookNotificationPayload,
115
+ extended_input_schema: SorbetTypes::OperationSchema,
116
+ extended_output_schema: SorbetTypes::OperationSchema,
117
+ headers: T::Hash[T.any(String, Symbol), T.untyped],
118
+ params: T::Hash[T.any(String, Symbol), T.untyped],
119
+ settings: T.nilable(SorbetTypes::SettingsHash),
120
+ webhook_subscribe_output: SorbetTypes::WebhookSubscribeOutputHash
121
+ ).returns(
122
+ SorbetTypes::WebhookNotificationOutputHash
123
+ )
124
+ end
59
125
  def webhook_notification(
60
126
  input = {},
61
127
  payload = {},
@@ -66,19 +132,36 @@ module Workato
66
132
  settings = nil,
67
133
  webhook_subscribe_output = {}
68
134
  )
69
- Dsl::WithDsl.execute(
135
+ connection.merge_settings!(settings) if settings
136
+ output = Dsl::WithDsl.execute(
137
+ connection,
70
138
  input.with_indifferent_access,
71
- payload.with_indifferent_access,
72
- extended_input_schema.map(&:with_indifferent_access),
73
- extended_output_schema.map(&:with_indifferent_access),
139
+ payload,
140
+ Array.wrap(extended_input_schema).map(&:with_indifferent_access),
141
+ Array.wrap(extended_output_schema).map(&:with_indifferent_access),
74
142
  headers.with_indifferent_access,
75
143
  params.with_indifferent_access,
76
- (settings || @settings).with_indifferent_access,
144
+ connection.settings,
77
145
  webhook_subscribe_output.with_indifferent_access,
78
146
  &trigger[:webhook_notification]
79
147
  )
148
+ if output.is_a?(::Array)
149
+ output.map! { |event| ::Hash.try_convert(event) || event }
150
+ else
151
+ ::Hash.try_convert(output) || output
152
+ end
80
153
  end
81
154
 
155
+ sig do
156
+ params(
157
+ webhook_url: String,
158
+ settings: T.nilable(SorbetTypes::SettingsHash),
159
+ input: SorbetTypes::OperationInputHash,
160
+ recipe_id: String
161
+ ).returns(
162
+ SorbetTypes::WebhookSubscribeOutputHash
163
+ )
164
+ end
82
165
  def webhook_subscribe(webhook_url = '', settings = nil, input = {}, recipe_id = SecureRandom.uuid)
83
166
  webhook_subscribe_proc = trigger[:webhook_subscribe]
84
167
  execute(settings, { input: input, webhook_url: webhook_url, recipe_id: recipe_id }) do |connection, payload|
@@ -92,6 +175,7 @@ module Workato
92
175
  end
93
176
  end
94
177
 
178
+ sig { params(webhook_subscribe_output: SorbetTypes::WebhookSubscribeOutputHash).returns(T.untyped) }
95
179
  def webhook_unsubscribe(webhook_subscribe_output = {})
96
180
  webhook_unsubscribe_proc = trigger[:webhook_unsubscribe]
97
181
  execute(nil, webhook_subscribe_output) do |_connection, input|
@@ -99,6 +183,17 @@ module Workato
99
183
  end
100
184
  end
101
185
 
186
+ sig do
187
+ params(
188
+ input: SorbetTypes::OperationInputHash,
189
+ payload: T::Hash[T.any(String, Symbol), T.untyped],
190
+ headers: T::Hash[T.any(String, Symbol), T.untyped],
191
+ params: T::Hash[T.any(String, Symbol), T.untyped],
192
+ webhook_subscribe_output: SorbetTypes::WebhookSubscribeOutputHash
193
+ ).returns(
194
+ T.any(SorbetTypes::WebhookNotificationOutputHash, SorbetTypes::PollOutputHash)
195
+ )
196
+ end
102
197
  def invoke(input = {}, payload = {}, headers = {}, params = {}, webhook_subscribe_output = {})
103
198
  extended_schema = extended_schema(nil, input)
104
199
  config_schema = Schema.new(schema: config_fields_schema)
@@ -132,6 +227,7 @@ module Workato
132
227
 
133
228
  alias trigger operation
134
229
 
230
+ sig { returns(T::Boolean) }
135
231
  def webhook_notification?
136
232
  trigger[:webhook_notification].present?
137
233
  end
@@ -1,9 +1,10 @@
1
+ # typed: strict
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Workato
4
5
  module Connector
5
6
  module Sdk
6
- VERSION = '1.0.1'
7
+ VERSION = '1.1.0'
7
8
  end
8
9
  end
9
10
  end
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require 'json'
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require 'nokogiri'
@@ -1,5 +1,9 @@
1
+ # typed: strict
1
2
  # frozen_string_literal: true
2
3
 
4
+ require 'sorbet-runtime'
5
+ ::Method.prepend(T::CompatibilityPatches::MethodExtensions)
6
+
3
7
  module Workato
4
8
  module Connector
5
9
  module Sdk
@@ -22,6 +26,10 @@ module Workato
22
26
 
23
27
  WORKATO_API_EMAIL_ENV = 'WORKATO_API_EMAIL'
24
28
  WORKATO_API_TOKEN_ENV = 'WORKATO_API_TOKEN'
29
+
30
+ WORKATO_BASE_URL_ENV = 'WORKATO_BASE_URL'
31
+ DEFAULT_WORKATO_BASE_URL = 'https://app.workato.com'
32
+ WORKATO_BASE_URL = T.let(ENV.fetch(WORKATO_BASE_URL_ENV, DEFAULT_WORKATO_BASE_URL), String)
25
33
  end
26
34
  end
27
35
  end
@@ -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: false
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require 'rest-client'
@@ -1,10 +1,11 @@
1
+ # typed: false
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Workato
4
5
  module Extension
5
6
  module Currency
6
7
  def to_currency(options = {})
7
- ActiveSupport::NumberHelper::NumberToCurrencyConverter(self, options)
8
+ ActiveSupport::NumberHelper::NumberToCurrencyConverter.convert(self, options)
8
9
  end
9
10
  end
10
11
  end
@@ -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: false
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Enumerable