workato-connector-sdk 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/VERSION +1 -0
  4. data/lib/workato/cli/edit_command.rb +3 -1
  5. data/lib/workato/cli/exec_command.rb +76 -10
  6. data/lib/workato/cli/generate_command.rb +2 -2
  7. data/lib/workato/cli/main.rb +17 -10
  8. data/lib/workato/cli/oauth2_command.rb +4 -4
  9. data/lib/workato/cli/push_command.rb +2 -2
  10. data/lib/workato/cli/schema_command.rb +2 -2
  11. data/lib/workato/connector/sdk/account_properties.rb +2 -2
  12. data/lib/workato/connector/sdk/action.rb +20 -70
  13. data/lib/workato/connector/sdk/block_invocation_refinements.rb +2 -10
  14. data/lib/workato/connector/sdk/connection.rb +36 -19
  15. data/lib/workato/connector/sdk/connector.rb +65 -77
  16. data/lib/workato/connector/sdk/core.rb +62 -0
  17. data/lib/workato/connector/sdk/dsl/aws.rb +3 -3
  18. data/lib/workato/connector/sdk/dsl/call.rb +1 -1
  19. data/lib/workato/connector/sdk/dsl/csv_package.rb +133 -0
  20. data/lib/workato/connector/sdk/dsl/execution_context.rb +1 -0
  21. data/lib/workato/connector/sdk/dsl/http.rb +1 -1
  22. data/lib/workato/connector/sdk/dsl/reinvoke_after.rb +84 -0
  23. data/lib/workato/connector/sdk/dsl/stream_package.rb +65 -0
  24. data/lib/workato/connector/sdk/dsl/time.rb +0 -14
  25. data/lib/workato/connector/sdk/dsl/workato_package.rb +146 -0
  26. data/lib/workato/connector/sdk/dsl.rb +63 -10
  27. data/lib/workato/connector/sdk/errors.rb +28 -11
  28. data/lib/workato/connector/sdk/operation.rb +9 -2
  29. data/lib/workato/connector/sdk/request.rb +63 -25
  30. data/lib/workato/connector/sdk/schema/field/convertors.rb +2 -2
  31. data/lib/workato/connector/sdk/schema/type/unicode_string.rb +1 -1
  32. data/lib/workato/connector/sdk/schema.rb +7 -5
  33. data/lib/workato/connector/sdk/settings.rb +10 -1
  34. data/lib/workato/connector/sdk/stream.rb +243 -0
  35. data/lib/workato/connector/sdk/streams.rb +71 -0
  36. data/lib/workato/connector/sdk/summarize.rb +2 -2
  37. data/lib/workato/connector/sdk/trigger.rb +14 -7
  38. data/lib/workato/connector/sdk/version.rb +1 -1
  39. data/lib/workato/connector/sdk.rb +19 -46
  40. data/lib/workato/extension/array.rb +2 -0
  41. data/lib/workato/extension/case_sensitive_headers.rb +0 -1
  42. data/lib/workato/extension/content_encoding_decoder.rb +2 -0
  43. data/lib/workato/extension/currency/countries.rb +79 -0
  44. data/lib/workato/extension/currency/countries.yml +18433 -0
  45. data/lib/workato/extension/currency/currencies.rb +55 -0
  46. data/lib/workato/extension/currency/currencies.yml +479 -0
  47. data/lib/workato/extension/currency.rb +73 -5
  48. data/lib/workato/extension/enumerable.rb +2 -2
  49. data/lib/workato/extension/metadata_fix_wrap_kw_args.rb +11 -0
  50. data/lib/workato/extension/string.rb +14 -111
  51. data/lib/workato/testing/vcr_encrypted_cassette_serializer.rb +2 -0
  52. data/lib/workato/types/binary.rb +55 -0
  53. metadata +46 -61
  54. data/lib/workato/connector/sdk/dsl/csv.rb +0 -125
  55. data/lib/workato/connector/sdk/dsl/workato_code_lib.rb +0 -167
@@ -0,0 +1,84 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Workato
5
+ module Connector
6
+ module Sdk
7
+ module Dsl
8
+ module ReinvokeAfter
9
+ extend T::Sig
10
+
11
+ sig do
12
+ params(
13
+ continue: T::Hash[T.untyped, T.untyped],
14
+ temp_output: T.nilable(T::Hash[T.untyped, T.untyped])
15
+ ).void
16
+ end
17
+ def checkpoint!(continue:, temp_output: nil)
18
+ # no-op
19
+ end
20
+
21
+ sig do
22
+ params(
23
+ seconds: T.any(Integer, Float),
24
+ continue: T::Hash[T.untyped, T.untyped],
25
+ temp_output: T.nilable(T::Hash[T.untyped, T.untyped])
26
+ ).void
27
+ end
28
+ def reinvoke_after(seconds:, continue:, temp_output: nil) # rubocop:disable Lint/UnusedMethodArgument
29
+ Kernel.throw REINVOKE_AFTER_SIGNAL, ReinvokeParams.new(
30
+ seconds: seconds,
31
+ continue: continue
32
+ )
33
+ end
34
+
35
+ private
36
+
37
+ MAX_REINVOKES = 5
38
+ private_constant :MAX_REINVOKES
39
+
40
+ REINVOKE_AFTER_SIGNAL = :reinvoke_after
41
+ private_constant :REINVOKE_AFTER_SIGNAL
42
+
43
+ class ReinvokeParams < T::Struct
44
+ prop :seconds, T.any(Float, Integer)
45
+ prop :continue, T::Hash[T.untyped, T.untyped]
46
+ end
47
+ private_constant :ReinvokeParams
48
+
49
+ sig { params(continue: T::Hash[T.any(Symbol, String), T.untyped], _blk: Proc).returns(T.untyped) }
50
+ def loop_reinvoke_after(continue, &_blk)
51
+ reinvokes_remaining = T.let(reinvoke_limit, Integer)
52
+
53
+ Kernel.loop do
54
+ reinvoke_after = Kernel.catch(REINVOKE_AFTER_SIGNAL) do
55
+ return yield(continue)
56
+ end
57
+
58
+ if reinvokes_remaining.zero?
59
+ Kernel.raise "Max number of reinvokes on SDK Gem reached. Current limit is #{reinvoke_limit}"
60
+ end
61
+
62
+ reinvokes_remaining -= 1
63
+
64
+ reinvoke_after = T.cast(reinvoke_after, ReinvokeParams)
65
+ reinvoke_sleep(reinvoke_after.seconds)
66
+ continue = reinvoke_after.continue
67
+ end
68
+ end
69
+
70
+ sig { params(seconds: T.any(Float, Integer)).void }
71
+ def reinvoke_sleep(seconds)
72
+ Kernel.sleep((ENV['WAIT_REINVOKE_AFTER'].presence || seconds).to_f)
73
+ end
74
+
75
+ sig { returns(Integer) }
76
+ def reinvoke_limit
77
+ @reinvoke_limit = T.let(@reinvoke_limit, T.nilable(Integer))
78
+ @reinvoke_limit ||= (ENV['MAX_REINVOKES'].presence || MAX_REINVOKES).to_i
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,65 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Workato
5
+ module Connector
6
+ module Sdk
7
+ module Dsl
8
+ class StreamPackage
9
+ extend T::Sig
10
+
11
+ sig { params(streams: Streams, connection: Connection).void }
12
+ def initialize(streams:, connection:)
13
+ @streams = streams
14
+ @connection = connection
15
+ end
16
+
17
+ sig do
18
+ params(
19
+ stream: T.any(Stream::Proxy, String, T::Hash[T.untyped, T.untyped]),
20
+ from: T.nilable(Integer),
21
+ frame_size: T.nilable(Integer),
22
+ blk: SorbetTypes::StreamInProc
23
+ ).returns(T.untyped)
24
+ end
25
+ def in(stream, from: nil, frame_size: nil, &blk)
26
+ if stream.is_a?(Hash) && stream[:__stream__] && stream[:chunks].nil?
27
+ stream = out(stream[:name], stream[:input] || {})
28
+ end
29
+
30
+ Stream::Reader.new(
31
+ stream: stream,
32
+ from: from,
33
+ frame_size: frame_size
34
+ ).each_chunk do |chunk, byte_from, byte_to, eof, next_from|
35
+ blk.call(chunk, byte_from, byte_to, eof, next_from)
36
+ end
37
+ end
38
+
39
+ sig { params(stream_name: String, input: SorbetTypes::StreamInputHash).returns(Stream::Proxy) }
40
+ def out(stream_name, input = {})
41
+ Stream::Proxy.new(input: input, name: stream_name, stream: streams[stream_name])
42
+ end
43
+
44
+ private
45
+
46
+ T::Sig::WithoutRuntime.sig { params(symbol: T.any(String, Symbol), _args: T.untyped).void }
47
+ def method_missing(symbol, *_args)
48
+ raise UndefinedStdLibMethodError.new(symbol.to_s, 'workato.stream')
49
+ end
50
+
51
+ T::Sig::WithoutRuntime.sig { params(_args: T.untyped).returns(T::Boolean) }
52
+ def respond_to_missing?(*_args)
53
+ false
54
+ end
55
+
56
+ sig { returns(Connection) }
57
+ attr_reader :connection
58
+
59
+ sig { returns(Streams) }
60
+ attr_reader :streams
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -18,17 +18,3 @@ module Workato
18
18
  end
19
19
  end
20
20
  end
21
-
22
- begin
23
- if ENV['TZ'].present? && ENV['TZ'] != 'UTC'
24
- warn "WARNING: TZ environment variable is set to '#{ENV['TZ']}'. Set TZ=UTC for consistency with Workato platform'"
25
- else
26
- ENV['TZ'] = 'UTC'
27
- end
28
- ::Time.zone = Workato::Connector::Sdk::DEFAULT_TIME_ZONE
29
- rescue TZInfo::DataSourceNotFound
30
- puts ''
31
- puts "tzinfo-data is not present. Please install gem 'tzinfo-data' by 'gem install tzinfo-data'"
32
- puts ''
33
- exit!
34
- end
@@ -0,0 +1,146 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ require 'jwt'
5
+ require_relative './csv_package'
6
+ require_relative './stream_package'
7
+
8
+ using Workato::Extension::HashWithIndifferentAccess
9
+
10
+ module Workato
11
+ module Connector
12
+ module Sdk
13
+ module Dsl
14
+ class WorkatoPackage
15
+ JWT_ALGORITHMS = %w[RS256 RS384 RS512].freeze
16
+ JWT_RSA_KEY_MIN_LENGTH = 2048
17
+
18
+ VERIFY_RCA_ALGORITHMS = %w[SHA SHA1 SHA224 SHA256 SHA384 SHA512].freeze
19
+
20
+ def initialize(streams:, connection:)
21
+ @streams = streams
22
+ @connection = connection
23
+ end
24
+
25
+ def jwt_encode_rs256(payload, key, header_fields = {})
26
+ jwt_encode(payload, key, 'RS256', header_fields)
27
+ end
28
+
29
+ def jwt_encode(payload, key, algorithm, header_fields = {})
30
+ algorithm = algorithm.to_s.upcase
31
+ unless JWT_ALGORITHMS.include?(algorithm)
32
+ raise "Unsupported signing method. Supports only #{JWT_ALGORITHMS.join(', ')}. Got: '#{algorithm}'"
33
+ end
34
+
35
+ rsa_private = OpenSSL::PKey::RSA.new(key)
36
+ if rsa_private.n.num_bits < JWT_RSA_KEY_MIN_LENGTH
37
+ raise "A RSA key of size #{JWT_RSA_KEY_MIN_LENGTH} bits or larger MUST be used with JWT."
38
+ end
39
+
40
+ header_fields = HashWithIndifferentAccess.wrap(header_fields).except(:typ, :alg)
41
+ ::JWT.encode(payload, rsa_private, algorithm, header_fields)
42
+ end
43
+
44
+ def verify_rsa(payload, certificate, signature, algorithm = 'SHA256')
45
+ algorithm = algorithm.to_s.upcase
46
+ unless VERIFY_RCA_ALGORITHMS.include?(algorithm)
47
+ raise "Unsupported signing method. Supports only #{VERIFY_RCA_ALGORITHMS.join(', ')}. Got: '#{algorithm}'"
48
+ end
49
+
50
+ cert = OpenSSL::X509::Certificate.new(certificate)
51
+ digest = OpenSSL::Digest.new(algorithm)
52
+ cert.public_key.verify(digest, signature, payload)
53
+ rescue OpenSSL::PKey::PKeyError
54
+ raise 'An error occurred during signature verification. Check arguments'
55
+ rescue OpenSSL::X509::CertificateError
56
+ raise 'Invalid certificate format'
57
+ end
58
+
59
+ def parse_yaml(yaml)
60
+ ::Psych.safe_load(yaml)
61
+ rescue ::Psych::DisallowedClass => e
62
+ raise e.message
63
+ end
64
+
65
+ def render_yaml(obj)
66
+ ::Psych.dump(obj)
67
+ end
68
+
69
+ def parse_json(source)
70
+ JSON.parse(source)
71
+ rescue JSON::ParserError => e
72
+ raise JSONResponseFormatError, e
73
+ end
74
+
75
+ def uuid
76
+ SecureRandom.uuid
77
+ end
78
+
79
+ RANDOM_SIZE = 32
80
+
81
+ def random_bytes(len)
82
+ unless (len.is_a? ::Integer) && (len <= RANDOM_SIZE)
83
+ raise "The requested length or random bytes sequence should be <= #{RANDOM_SIZE}"
84
+ end
85
+
86
+ Types::Binary.new(::OpenSSL::Random.random_bytes(len))
87
+ end
88
+
89
+ ALLOWED_KEY_SIZES = [128, 192, 256].freeze
90
+
91
+ def aes_cbc_encrypt(string, key, init_vector = nil)
92
+ key_size = key.bytesize * 8
93
+ unless ALLOWED_KEY_SIZES.include?(key_size)
94
+ raise 'Incorrect key size for AES'
95
+ end
96
+
97
+ cipher = ::OpenSSL::Cipher.new("AES-#{key_size}-CBC")
98
+ cipher.encrypt
99
+ cipher.key = key
100
+ cipher.iv = init_vector if init_vector.present?
101
+ Types::Binary.new(cipher.update(string) + cipher.final)
102
+ end
103
+
104
+ def aes_cbc_decrypt(string, key, init_vector = nil)
105
+ key_size = key.bytesize * 8
106
+ unless ALLOWED_KEY_SIZES.include?(key_size)
107
+ raise 'Incorrect key size for AES'
108
+ end
109
+
110
+ cipher = ::OpenSSL::Cipher.new("AES-#{key_size}-CBC")
111
+ cipher.decrypt
112
+ cipher.key = key
113
+ cipher.iv = init_vector if init_vector.present?
114
+ Types::Binary.new(cipher.update(string) + cipher.final)
115
+ end
116
+
117
+ def pbkdf2_hmac_sha1(string, salt, iterations = 1000, key_len = 16)
118
+ Types::Binary.new(::OpenSSL::PKCS5.pbkdf2_hmac_sha1(string, salt, iterations, key_len))
119
+ end
120
+
121
+ def csv
122
+ @csv ||= CsvPackage.new
123
+ end
124
+
125
+ def stream
126
+ @stream ||= StreamPackage.new(streams: streams, connection: connection)
127
+ end
128
+
129
+ private
130
+
131
+ def method_missing(symbol, *_args)
132
+ raise UndefinedStdLibMethodError.new(symbol.to_s, 'workato')
133
+ end
134
+
135
+ def respond_to_missing?(*)
136
+ false
137
+ end
138
+
139
+ attr_reader :streams
140
+
141
+ attr_reader :connection
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
@@ -5,10 +5,11 @@ require_relative './block_invocation_refinements'
5
5
 
6
6
  require_relative './dsl/http'
7
7
  require_relative './dsl/call'
8
+ require_relative './dsl/reinvoke_after'
8
9
  require_relative './dsl/error'
9
10
  require_relative './dsl/account_property'
10
11
  require_relative './dsl/lookup_table'
11
- require_relative './dsl/workato_code_lib'
12
+ require_relative './dsl/workato_package'
12
13
  require_relative './dsl/workato_schema'
13
14
  require_relative './dsl/time'
14
15
  require_relative './dsl/aws'
@@ -19,12 +20,29 @@ module Workato
19
20
  module Sdk
20
21
  module Dsl
21
22
  module Global
23
+ extend T::Sig
24
+ extend T::Helpers
25
+
26
+ abstract!
27
+
28
+ sig { abstract.returns(Streams) }
29
+ def streams; end
30
+
31
+ sig { abstract.returns(Connection) }
32
+ def connection; end
33
+
22
34
  include Time
23
35
  include AccountProperty
24
36
  include LookupTable
25
- include WorkatoCodeLib
26
37
  include WorkatoSchema
27
- include AWS
38
+
39
+ delegate :parse_json,
40
+ :uuid,
41
+ to: :workato
42
+
43
+ def workato
44
+ @workato ||= WorkatoPackage.new(streams: streams, connection: connection)
45
+ end
28
46
 
29
47
  def sleep(seconds)
30
48
  ::Kernel.sleep(seconds.presence || 0)
@@ -33,6 +51,39 @@ module Workato
33
51
  def puts(*args)
34
52
  T.unsafe(::Kernel).puts(*args)
35
53
  end
54
+
55
+ def encrypt(text, key)
56
+ ::Kernel.require('ruby_rncryptor')
57
+
58
+ enc_text = ::RubyRNCryptor.encrypt(text, key)
59
+ ::Base64.strict_encode64(enc_text)
60
+ end
61
+
62
+ def decrypt(text, key)
63
+ ::Kernel.require('ruby_rncryptor')
64
+
65
+ text = ::Base64.decode64(text)
66
+ dec_text = ::RubyRNCryptor.decrypt(text, key)
67
+ Workato::Types::Binary.new(dec_text)
68
+ rescue Exception => e # rubocop:disable Lint/RescueException
69
+ message = e.message.to_s
70
+ case message
71
+ when /Password may be incorrect/
72
+ ::Kernel.raise 'invalid/corrupt input or key'
73
+ when /RubyRNCryptor only decrypts version/
74
+ ::Kernel.raise 'invalid/corrupt input'
75
+ else
76
+ ::Kernel.raise
77
+ end
78
+ end
79
+
80
+ def blank; end
81
+
82
+ def clear; end
83
+
84
+ def null; end
85
+
86
+ def skip; end
36
87
  end
37
88
 
38
89
  class WithDsl
@@ -42,21 +93,23 @@ module Workato
42
93
 
43
94
  using BlockInvocationRefinements
44
95
 
45
- sig { params(connection: Connection, args: T.untyped, block: T.untyped).returns(T.untyped) }
46
- def execute(connection, *args, &block)
96
+ sig { params(connection: Connection, streams: Streams).void }
97
+ def initialize(connection = Connection.new, streams = ProhibitedStreams.new)
47
98
  @connection = connection
48
- T.unsafe(self).instance_exec(*args, &block)
99
+ @streams = streams
49
100
  end
50
101
 
51
- sig { params(connection: Connection, args: T.untyped, block: T.untyped).returns(T.untyped) }
52
- def self.execute(connection, *args, &block)
53
- T.unsafe(WithDsl.new).execute(connection, *args, &block)
102
+ def execute(...)
103
+ T.unsafe(self).instance_exec(...)
54
104
  end
55
105
 
56
106
  private
57
107
 
58
- sig { returns(Connection) }
108
+ sig { override.returns(Connection) }
59
109
  attr_reader :connection
110
+
111
+ sig { override.returns(Streams) }
112
+ attr_reader :streams
60
113
  end
61
114
  end
62
115
  end
@@ -4,7 +4,13 @@
4
4
  module Workato
5
5
  module Connector
6
6
  module Sdk
7
- InvalidDefinitionError = Class.new(StandardError)
7
+ Error = Class.new(StandardError)
8
+
9
+ DetectOnUnauthorizedRequestError = Class.new(Error)
10
+
11
+ RuntimeError = Class.new(Error)
12
+
13
+ InvalidDefinitionError = Class.new(Error)
8
14
 
9
15
  class UnexpectedMethodDefinitionError < InvalidDefinitionError
10
16
  attr_reader :name
@@ -28,8 +34,6 @@ module Workato
28
34
 
29
35
  InvalidSchemaError = Class.new(InvalidDefinitionError)
30
36
 
31
- CustomRequestError = Class.new(StandardError)
32
-
33
37
  InvalidMultiAuthDefinition = Class.new(InvalidDefinitionError)
34
38
 
35
39
  class UnresolvedMultiAuthOptionError < InvalidMultiAuthDefinition
@@ -41,9 +45,7 @@ module Workato
41
45
  end
42
46
  end
43
47
 
44
- RuntimeError = Class.new(StandardError)
45
-
46
- class UnresolvedObjectDefinitionError < StandardError
48
+ class UnresolvedObjectDefinitionError < InvalidDefinitionError
47
49
  attr_reader :name
48
50
 
49
51
  def initialize(name)
@@ -52,7 +54,7 @@ module Workato
52
54
  end
53
55
  end
54
56
 
55
- class CircleReferenceObjectDefinitionError < StandardError
57
+ class CircleReferenceObjectDefinitionError < InvalidDefinitionError
56
58
  attr_reader :name
57
59
 
58
60
  def initialize(name, backtrace = [])
@@ -62,7 +64,11 @@ module Workato
62
64
  end
63
65
  end
64
66
 
65
- class RequestError < StandardError
67
+ RequestError = Class.new(RuntimeError)
68
+
69
+ RequestTimeoutError = Class.new(RequestError)
70
+
71
+ class RequestFailedError < RequestError
66
72
  attr_reader :method
67
73
  attr_reader :code
68
74
  attr_reader :response
@@ -81,7 +87,7 @@ module Workato
81
87
  end
82
88
  end
83
89
 
84
- class MissingRequiredInput < StandardError
90
+ class MissingRequiredInput < RuntimeError
85
91
  def initialize(label, toggle_label)
86
92
  message = if toggle_label && label != toggle_label
87
93
  "Either '#{label}' or '#{toggle_label}' must be present"
@@ -92,9 +98,9 @@ module Workato
92
98
  end
93
99
  end
94
100
 
95
- RequestTLSCertificateFormatError = Class.new(StandardError)
101
+ RequestTLSCertificateFormatError = Class.new(RequestError)
96
102
 
97
- RequestPayloadFormatError = Class.new(StandardError)
103
+ RequestPayloadFormatError = Class.new(RequestError)
98
104
 
99
105
  JSONRequestFormatError = Class.new(RequestPayloadFormatError)
100
106
 
@@ -109,6 +115,17 @@ module Workato
109
115
  MultipartFormRequestFormatError = Class.new(RequestPayloadFormatError)
110
116
 
111
117
  RAWResponseFormatError = Class.new(RequestPayloadFormatError)
118
+
119
+ class UndefinedStdLibMethodError < RuntimeError
120
+ attr_reader :name
121
+ attr_reader :package
122
+
123
+ def initialize(name, package)
124
+ @name = name
125
+ @package = package
126
+ super("Undefined method '#{name}' for \"#{package}\" namespace")
127
+ end
128
+ end
112
129
  end
113
130
  end
114
131
  end
@@ -44,6 +44,7 @@ module Workato
44
44
  extend T::Sig
45
45
 
46
46
  include Dsl::Global
47
+ include Dsl::AWS
47
48
  include Dsl::HTTP
48
49
  include Dsl::Call
49
50
  include Dsl::Error
@@ -51,18 +52,24 @@ module Workato
51
52
 
52
53
  using BlockInvocationRefinements
53
54
 
55
+ sig { override.returns(Streams) }
56
+ attr_reader :streams
57
+
54
58
  sig do
55
59
  params(
56
60
  operation: SorbetTypes::SourceHash,
57
61
  methods: SorbetTypes::SourceHash,
58
62
  connection: Connection,
63
+ streams: Streams,
59
64
  object_definitions: T.nilable(ObjectDefinitions)
60
65
  ).void
61
66
  end
62
- def initialize(operation: {}, methods: {}, connection: Connection.new, object_definitions: nil)
67
+ def initialize(operation: {}, methods: {}, connection: Connection.new, streams: ProhibitedStreams.new,
68
+ object_definitions: nil)
63
69
  @operation = T.let(HashWithIndifferentAccess.wrap(operation), HashWithIndifferentAccess)
64
70
  @_methods = T.let(HashWithIndifferentAccess.wrap(methods), HashWithIndifferentAccess)
65
71
  @connection = T.let(connection, Connection)
72
+ @streams = T.let(streams, Streams)
66
73
  @object_definitions = T.let(object_definitions, T.nilable(ObjectDefinitions))
67
74
  end
68
75
 
@@ -262,7 +269,7 @@ module Workato
262
269
  sig { returns(HashWithIndifferentAccess) }
263
270
  attr_reader :operation
264
271
 
265
- sig { returns(Connection) }
272
+ sig { override.returns(Connection) }
266
273
  attr_reader :connection
267
274
  end
268
275
  end