workato-connector-sdk 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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