workato-connector-sdk 1.1.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -2
  3. data/VERSION +1 -0
  4. data/lib/workato/cli/edit_command.rb +3 -1
  5. data/lib/workato/cli/exec_command.rb +103 -17
  6. data/lib/workato/cli/generate_command.rb +2 -2
  7. data/lib/workato/cli/main.rb +17 -10
  8. data/lib/workato/cli/multi_auth_selected_fallback.rb +33 -0
  9. data/lib/workato/cli/oauth2_command.rb +50 -12
  10. data/lib/workato/cli/push_command.rb +2 -2
  11. data/lib/workato/cli/schema_command.rb +2 -2
  12. data/lib/workato/connector/sdk/account_properties.rb +2 -2
  13. data/lib/workato/connector/sdk/action.rb +20 -70
  14. data/lib/workato/connector/sdk/block_invocation_refinements.rb +2 -10
  15. data/lib/workato/connector/sdk/connection.rb +115 -30
  16. data/lib/workato/connector/sdk/connector.rb +71 -81
  17. data/lib/workato/connector/sdk/core.rb +62 -0
  18. data/lib/workato/connector/sdk/dsl/aws.rb +8 -5
  19. data/lib/workato/connector/sdk/dsl/call.rb +1 -1
  20. data/lib/workato/connector/sdk/dsl/csv_package.rb +133 -0
  21. data/lib/workato/connector/sdk/dsl/execution_context.rb +45 -0
  22. data/lib/workato/connector/sdk/dsl/http.rb +1 -1
  23. data/lib/workato/connector/sdk/dsl/reinvoke_after.rb +84 -0
  24. data/lib/workato/connector/sdk/dsl/stream_package.rb +65 -0
  25. data/lib/workato/connector/sdk/dsl/time.rb +0 -14
  26. data/lib/workato/connector/sdk/dsl/workato_package.rb +146 -0
  27. data/lib/workato/connector/sdk/dsl.rb +64 -10
  28. data/lib/workato/connector/sdk/errors.rb +37 -9
  29. data/lib/workato/connector/sdk/lookup_tables.rb +3 -1
  30. data/lib/workato/connector/sdk/operation.rb +33 -10
  31. data/lib/workato/connector/sdk/request.rb +149 -69
  32. data/lib/workato/connector/sdk/schema/field/convertors.rb +2 -2
  33. data/lib/workato/connector/sdk/schema/type/unicode_string.rb +1 -1
  34. data/lib/workato/connector/sdk/schema.rb +12 -8
  35. data/lib/workato/connector/sdk/settings.rb +14 -3
  36. data/lib/workato/connector/sdk/stream.rb +243 -0
  37. data/lib/workato/connector/sdk/streams.rb +71 -0
  38. data/lib/workato/connector/sdk/summarize.rb +2 -2
  39. data/lib/workato/connector/sdk/trigger.rb +23 -15
  40. data/lib/workato/connector/sdk/version.rb +1 -1
  41. data/lib/workato/connector/sdk.rb +21 -47
  42. data/lib/workato/extension/array.rb +2 -0
  43. data/lib/workato/extension/case_sensitive_headers.rb +0 -26
  44. data/lib/workato/extension/content_encoding_decoder.rb +69 -0
  45. data/lib/workato/extension/currency/countries.rb +79 -0
  46. data/lib/workato/extension/currency/countries.yml +18433 -0
  47. data/lib/workato/extension/currency/currencies.rb +55 -0
  48. data/lib/workato/extension/currency/currencies.yml +479 -0
  49. data/lib/workato/extension/currency.rb +73 -5
  50. data/lib/workato/extension/enumerable.rb +2 -2
  51. data/lib/workato/extension/extra_chain_cert.rb +0 -14
  52. data/lib/workato/extension/hash_with_indifferent_access.rb +19 -0
  53. data/lib/workato/extension/metadata_fix_wrap_kw_args.rb +11 -0
  54. data/lib/workato/extension/string.rb +16 -112
  55. data/lib/workato/testing/vcr_encrypted_cassette_serializer.rb +2 -0
  56. data/lib/workato/types/binary.rb +55 -0
  57. data/lib/workato/{connector/sdk → utilities}/xml.rb +4 -4
  58. metadata +61 -64
  59. data/lib/workato/connector/sdk/dsl/workato_code_lib.rb +0 -160
@@ -0,0 +1,243 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ using Workato::Extension::HashWithIndifferentAccess
5
+
6
+ module Workato
7
+ module Connector
8
+ module Sdk
9
+ module SorbetTypes
10
+ StreamProc = T.type_alias do
11
+ T.proc.params(
12
+ input: SorbetTypes::StreamInputHash,
13
+ from: Integer,
14
+ to: Integer,
15
+ frame_size: Integer
16
+ ).returns(SorbetTypes::StreamOutput)
17
+ end
18
+
19
+ StreamInProc = T.type_alias do
20
+ T.proc.params(
21
+ data: T.untyped,
22
+ from: Integer,
23
+ to: T.nilable(Integer),
24
+ eof: T::Boolean,
25
+ next_from: T.nilable(Integer)
26
+ ).void
27
+ end
28
+
29
+ StreamInputHash = T.type_alias { T::Hash[T.any(Symbol, String), T.untyped] }
30
+
31
+ StreamOutput = T.type_alias { [T.untyped, T::Boolean] }
32
+ end
33
+
34
+ class Stream < Operation
35
+ extend T::Sig
36
+
37
+ DEFAULT_FRAME_SIZE = T.let(10.megabytes, Integer)
38
+
39
+ using BlockInvocationRefinements
40
+ include Dsl::ReinvokeAfter
41
+
42
+ sig do
43
+ params(
44
+ stream: SorbetTypes::StreamProc,
45
+ methods: SorbetTypes::SourceHash,
46
+ connection: Connection
47
+ ).void
48
+ end
49
+ def initialize(stream:, methods: {}, connection: Connection.new)
50
+ super(methods: methods, connection: connection)
51
+ @stream_proc = stream
52
+ end
53
+
54
+ sig do
55
+ params(
56
+ input: SorbetTypes::StreamInputHash,
57
+ from: Integer,
58
+ to: Integer,
59
+ frame_size: Integer
60
+ ).returns(SorbetTypes::StreamOutput)
61
+ end
62
+ def chunk(input = {}, from = 0, to = from + DEFAULT_FRAME_SIZE, frame_size = DEFAULT_FRAME_SIZE)
63
+ raise "'frame_size' must be a positive integer number" unless frame_size.positive?
64
+
65
+ stream_proc = @stream_proc
66
+ execute(nil, { input: input, from: from, to: to, size: frame_size }) do |_, input| # rubocop:disable Lint/ShadowingOuterLocalVariable
67
+ T.unsafe(self).instance_exec(input['input'], input['from'], input['to'], input['size'], &stream_proc)
68
+ end
69
+ end
70
+
71
+ sig { params(input: SorbetTypes::StreamInputHash, frame_size: Integer).returns(T.untyped) }
72
+ def invoke(input = {}, frame_size = DEFAULT_FRAME_SIZE)
73
+ proxy = Proxy.new(name: '', input: input, stream: self)
74
+ reader = Reader.new(stream: proxy, frame_size: frame_size)
75
+ data = T.let(nil, T.untyped)
76
+ reader.each_chunk do |chunk|
77
+ data = data.nil? ? chunk : data + chunk
78
+ end
79
+ data
80
+ end
81
+
82
+ class Reader
83
+ extend T::Sig
84
+
85
+ ProxyReadProc = T.type_alias do
86
+ T.proc.params(
87
+ data: T.untyped,
88
+ from: Integer,
89
+ eof: T::Boolean,
90
+ next_from: T.nilable(Integer)
91
+ ).void
92
+ end
93
+
94
+ sig do
95
+ params(
96
+ stream: T.any(Proxy, T::Hash[T.untyped, T.untyped], String),
97
+ from: T.nilable(Integer),
98
+ frame_size: T.nilable(Integer)
99
+ ).void
100
+ end
101
+ def initialize(stream:, from: nil, frame_size: nil)
102
+ @stream = T.let(
103
+ stream.is_a?(Hash) && stream[:__stream__] ? from_mock(stream) : stream,
104
+ T.any(Proxy, Mock, T::Hash[T.untyped, T.untyped], String)
105
+ )
106
+ @from = T.let(from || 0, Integer)
107
+ @frame_size = T.let(frame_size || DEFAULT_FRAME_SIZE, Integer)
108
+ end
109
+
110
+ sig { params(_blk: SorbetTypes::StreamInProc).void }
111
+ def each_chunk(&_blk)
112
+ case @stream
113
+ when Proxy, Mock
114
+ @stream.read(from: @from, frame_size: @frame_size) do |chunk, from, eof, next_from|
115
+ yield(chunk, from, calculate_byte_to(chunk, from), eof, next_from)
116
+ end
117
+ when Hash
118
+ chunk = @stream[:data][@from..]
119
+ yield(chunk, @from, calculate_byte_to(chunk, @from), @stream[:eof], nil)
120
+ else
121
+ chunk = @stream[@from..]
122
+ yield(@stream[@from..], @from, calculate_byte_to(chunk, @from), true, nil)
123
+ end
124
+ end
125
+
126
+ private
127
+
128
+ sig { params(chunk: T.untyped, from: Integer).returns(T.nilable(Integer)) }
129
+ def calculate_byte_to(chunk, from)
130
+ (chunk_size = chunk.try(:bytesize) || 0).zero? ? nil : from + chunk_size - 1
131
+ end
132
+
133
+ sig { params(hash: T::Hash[T.untyped, T.untyped]).returns(T.any(Proxy, Mock)) }
134
+ def from_mock(hash)
135
+ case hash[:chunks]
136
+ when Proc
137
+ Proxy.new(
138
+ name: hash[:name],
139
+ input: HashWithIndifferentAccess.wrap(hash[:input] || {}),
140
+ stream: Stream.new(
141
+ stream: hash[:chunks],
142
+ connection: Connection.new(
143
+ connection: hash[:connection] || {},
144
+ settings: hash[:settings] || {}
145
+ )
146
+ )
147
+ )
148
+ when Hash
149
+ Mock.new(chunks: hash[:chunks])
150
+ else
151
+ raise 'Mock streams with Proc or Hash. Read spec/examples/stream/connector_spec.rb for examples'
152
+ end
153
+ end
154
+ end
155
+
156
+ class Proxy
157
+ extend T::Sig
158
+
159
+ sig { params(name: String, input: SorbetTypes::StreamInputHash, stream: Stream).void }
160
+ def initialize(name:, input:, stream:)
161
+ @name = name
162
+ @input = input
163
+ @stream = stream
164
+ end
165
+
166
+ sig { params(_options: T.untyped).returns(T::Hash[String, T.untyped]) }
167
+ def as_json(_options = nil)
168
+ {
169
+ __stream__: true,
170
+ name: name,
171
+ input: input
172
+ }
173
+ end
174
+
175
+ sig { params(from: Integer, frame_size: Integer, _blk: Reader::ProxyReadProc).void }
176
+ def read(from:, frame_size:, &_blk)
177
+ next_from = from
178
+ loop do
179
+ res = read_chunk(next_from, frame_size)
180
+ yield(res.data, res.from, res.eof, res.next_from)
181
+ break if res.eof
182
+
183
+ next_from = T.must(res.next_from)
184
+ end
185
+ end
186
+
187
+ private
188
+
189
+ sig { returns(String) }
190
+ attr_reader :name
191
+
192
+ sig { returns(SorbetTypes::StreamInputHash) }
193
+ attr_reader :input
194
+
195
+ class Chunk < T::Struct
196
+ const :data, T.untyped
197
+ const :from, Integer
198
+ const :eof, T::Boolean
199
+ const :next_from, T.nilable(Integer)
200
+ end
201
+ private_constant :Chunk
202
+
203
+ sig { params(from: Integer, frame_size: Integer).returns(Chunk) }
204
+ def read_chunk(from, frame_size)
205
+ data, eof = @stream.chunk(input, from, from + frame_size - 1, frame_size)
206
+ next_from = from + (data&.length || 0)
207
+ next_from = nil if eof
208
+ Chunk.new(data: data, from: from, eof: eof, next_from: next_from)
209
+ end
210
+ end
211
+
212
+ class Mock
213
+ extend T::Sig
214
+
215
+ sig { params(chunks: T.untyped).void }
216
+ def initialize(chunks:)
217
+ @chunks = chunks
218
+ end
219
+
220
+ sig { params(from: Integer, frame_size: Integer, _blk: Reader::ProxyReadProc).void }
221
+ def read(from:, frame_size:, &_blk)
222
+ last_from = chunks.keys.last
223
+ chunks.each do |chunk_from, data|
224
+ next if chunk_from < from
225
+
226
+ eof = chunk_from == last_from
227
+ next_from = eof ? nil : chunk_from + frame_size
228
+
229
+ yield(data, chunk_from, eof, next_from)
230
+ end
231
+ end
232
+
233
+ private
234
+
235
+ sig { returns(T.untyped) }
236
+ attr_reader :chunks
237
+ end
238
+
239
+ private_constant :Mock
240
+ end
241
+ end
242
+ end
243
+ end
@@ -0,0 +1,71 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ using Workato::Extension::HashWithIndifferentAccess
5
+
6
+ module Workato
7
+ module Connector
8
+ module Sdk
9
+ class Streams
10
+ extend T::Sig
11
+
12
+ sig do
13
+ params(
14
+ streams: SorbetTypes::SourceHash,
15
+ methods: SorbetTypes::SourceHash,
16
+ connection: Connection
17
+ ).void
18
+ end
19
+ def initialize(streams: {}, methods: {}, connection: Connection.new)
20
+ @methods_source = methods
21
+ @connection = connection
22
+ @streams = T.let({}, T::Hash[T.any(Symbol, String), Stream])
23
+ @streams_source = streams
24
+ define_action_methods(streams)
25
+ end
26
+
27
+ sig { params(stream: T.any(String, Symbol)).returns(Stream) }
28
+ def [](stream)
29
+ @streams[stream] ||= Stream.new(
30
+ stream: @streams_source.fetch(stream),
31
+ methods: methods_source,
32
+ connection: connection
33
+ )
34
+ end
35
+
36
+ private
37
+
38
+ sig { params(streams_source: SorbetTypes::SourceHash).void }
39
+ def define_action_methods(streams_source)
40
+ streams_source.each do |stream, _stream_proc|
41
+ define_singleton_method(stream) do |input = {}, from = 0, to = nil, frame_size = Stream::DEFAULT_FRAME_SIZE|
42
+ to ||= from + frame_size
43
+ self[stream].chunk(input, from, to, frame_size)
44
+ end
45
+
46
+ define_singleton_method("#{stream}!") do |input = {}, frame_size = Stream::DEFAULT_FRAME_SIZE|
47
+ self[stream].invoke(input, frame_size)
48
+ end
49
+ end
50
+ end
51
+
52
+ sig { returns(SorbetTypes::SourceHash) }
53
+ attr_reader :methods_source
54
+
55
+ sig { returns(Connection) }
56
+ attr_reader :connection
57
+ end
58
+
59
+ class ProhibitedStreams < Streams
60
+ extend T::Sig
61
+
62
+ sig { void }
63
+ def initialize
64
+ @streams = Hash.new do
65
+ raise 'Streams are not available in this context. Access streams in actions or triggers'
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -34,8 +34,8 @@ module Workato
34
34
  attr_reader :paths
35
35
 
36
36
  def above_summarization_limit?(candidate)
37
- candidate.is_a?(::Array) && candidate.length > ARRAY_SUMMARIZATION_LIMIT ||
38
- candidate.is_a?(::String) && candidate.length > STRING_SUMMARIZATION_LIMIT
37
+ (candidate.is_a?(::Array) && candidate.length > ARRAY_SUMMARIZATION_LIMIT) ||
38
+ (candidate.is_a?(::String) && candidate.length > STRING_SUMMARIZATION_LIMIT)
39
39
  end
40
40
 
41
41
  def apply_summarization_limit(summarized, steps)
@@ -3,6 +3,8 @@
3
3
 
4
4
  require 'securerandom'
5
5
 
6
+ using Workato::Extension::HashWithIndifferentAccess
7
+
6
8
  module Workato
7
9
  module Connector
8
10
  module Sdk
@@ -32,15 +34,18 @@ module Workato
32
34
  trigger: SorbetTypes::SourceHash,
33
35
  methods: SorbetTypes::SourceHash,
34
36
  connection: Connection,
35
- object_definitions: T.nilable(ObjectDefinitions)
37
+ object_definitions: T.nilable(ObjectDefinitions),
38
+ streams: Streams
36
39
  ).void
37
40
  end
38
- def initialize(trigger:, methods: {}, connection: Connection.new, object_definitions: nil)
41
+ def initialize(trigger:, methods: {}, connection: Connection.new, object_definitions: nil,
42
+ streams: ProhibitedStreams.new)
39
43
  super(
40
44
  operation: trigger,
41
45
  connection: connection,
42
46
  methods: methods,
43
- object_definitions: object_definitions
47
+ object_definitions: object_definitions,
48
+ streams: streams
44
49
  )
45
50
  end
46
51
 
@@ -66,7 +71,6 @@ module Workato
66
71
  ) do |connection, payload, eis, eos|
67
72
  instance_exec(connection, payload[:input], payload[:closure], eis, eos, &poll_proc)
68
73
  end
69
- output.with_indifferent_access
70
74
  output[:events] = Array.wrap(output[:events])
71
75
  .reverse!
72
76
  .map! { |event| ::Hash.try_convert(event) || event }
@@ -117,7 +121,7 @@ module Workato
117
121
  headers: T::Hash[T.any(String, Symbol), T.untyped],
118
122
  params: T::Hash[T.any(String, Symbol), T.untyped],
119
123
  settings: T.nilable(SorbetTypes::SettingsHash),
120
- webhook_subscribe_output: SorbetTypes::WebhookSubscribeOutputHash
124
+ webhook_subscribe_output: T.nilable(SorbetTypes::WebhookSubscribeOutputHash)
121
125
  ).returns(
122
126
  SorbetTypes::WebhookNotificationOutputHash
123
127
  )
@@ -133,16 +137,15 @@ module Workato
133
137
  webhook_subscribe_output = {}
134
138
  )
135
139
  connection.merge_settings!(settings) if settings
136
- output = Dsl::WithDsl.execute(
137
- connection,
138
- input.with_indifferent_access,
140
+ output = global_dsl_context.execute(
141
+ HashWithIndifferentAccess.wrap(input),
139
142
  payload,
140
- Array.wrap(extended_input_schema).map(&:with_indifferent_access),
141
- Array.wrap(extended_output_schema).map(&:with_indifferent_access),
142
- headers.with_indifferent_access,
143
- params.with_indifferent_access,
143
+ Array.wrap(extended_input_schema).map { |i| HashWithIndifferentAccess.wrap(i) },
144
+ Array.wrap(extended_output_schema).map { |i| HashWithIndifferentAccess.wrap(i) },
145
+ HashWithIndifferentAccess.wrap(headers),
146
+ HashWithIndifferentAccess.wrap(params),
144
147
  connection.settings,
145
- webhook_subscribe_output.with_indifferent_access,
148
+ HashWithIndifferentAccess.wrap(webhook_subscribe_output),
146
149
  &trigger[:webhook_notification]
147
150
  )
148
151
  if output.is_a?(::Array)
@@ -162,7 +165,7 @@ module Workato
162
165
  SorbetTypes::WebhookSubscribeOutputHash
163
166
  )
164
167
  end
165
- def webhook_subscribe(webhook_url = '', settings = nil, input = {}, recipe_id = SecureRandom.uuid)
168
+ def webhook_subscribe(webhook_url = '', settings = nil, input = {}, recipe_id = recipe_id!)
166
169
  webhook_subscribe_proc = trigger[:webhook_subscribe]
167
170
  execute(settings, { input: input, webhook_url: webhook_url, recipe_id: recipe_id }) do |connection, payload|
168
171
  instance_exec(
@@ -189,7 +192,7 @@ module Workato
189
192
  payload: T::Hash[T.any(String, Symbol), T.untyped],
190
193
  headers: T::Hash[T.any(String, Symbol), T.untyped],
191
194
  params: T::Hash[T.any(String, Symbol), T.untyped],
192
- webhook_subscribe_output: SorbetTypes::WebhookSubscribeOutputHash
195
+ webhook_subscribe_output: T.nilable(SorbetTypes::WebhookSubscribeOutputHash)
193
196
  ).returns(
194
197
  T.any(SorbetTypes::WebhookNotificationOutputHash, SorbetTypes::PollOutputHash)
195
198
  )
@@ -231,6 +234,11 @@ module Workato
231
234
  def webhook_notification?
232
235
  trigger[:webhook_notification].present?
233
236
  end
237
+
238
+ sig { returns(Dsl::WithDsl) }
239
+ def global_dsl_context
240
+ Dsl::WithDsl.new(connection, streams)
241
+ end
234
242
  end
235
243
  end
236
244
  end
@@ -4,7 +4,7 @@
4
4
  module Workato
5
5
  module Connector
6
6
  module Sdk
7
- VERSION = '1.1.0'
7
+ VERSION = T.let(File.read(File.expand_path('../../../../VERSION', __dir__)).strip, String)
8
8
  end
9
9
  end
10
10
  end
@@ -2,48 +2,22 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'sorbet-runtime'
5
- ::Method.prepend(T::CompatibilityPatches::MethodExtensions)
6
-
7
- module Workato
8
- module Connector
9
- module Sdk
10
- DEFAULT_MASTER_KEY_ENV = 'WORKATO_CONNECTOR_MASTER_KEY'
11
- DEFAULT_MASTER_KEY_PATH = 'master.key'
12
-
13
- DEFAULT_CONNECTOR_PATH = 'connector.rb'
14
-
15
- DEFAULT_SETTINGS_PATH = 'settings.yaml'
16
- DEFAULT_ENCRYPTED_SETTINGS_PATH = 'settings.yaml.enc'
17
-
18
- DEFAULT_ACCOUNT_PROPERTIES_PATH = 'account_properties.yaml'
19
- DEFAULT_ENCRYPTED_ACCOUNT_PROPERTIES_PATH = 'account_properties.yaml.enc'
20
-
21
- DEFAULT_LOOKUP_TABLES_PATH = 'lookup_tables.yaml'
22
-
23
- DEFAULT_TIME_ZONE = 'Pacific Time (US & Canada)'
24
-
25
- DEFAULT_SCHEMAS_PATH = 'workato_schemas.json'
26
-
27
- WORKATO_API_EMAIL_ENV = 'WORKATO_API_EMAIL'
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)
33
- end
34
- end
35
- end
36
5
 
37
6
  # Global libs and monkey patches
38
7
  require 'active_support/all'
39
8
  require 'active_support/json'
9
+
10
+ require_relative '../types/binary'
11
+
40
12
  require_relative '../extension/array'
41
13
  require_relative '../extension/case_sensitive_headers'
14
+ require_relative '../extension/content_encoding_decoder'
42
15
  require_relative '../extension/currency'
43
16
  require_relative '../extension/date'
44
17
  require_relative '../extension/enumerable'
45
18
  require_relative '../extension/extra_chain_cert'
46
19
  require_relative '../extension/hash'
20
+ require_relative '../extension/hash_with_indifferent_access'
47
21
  require_relative '../extension/integer'
48
22
  require_relative '../extension/nil_class'
49
23
  require_relative '../extension/object'
@@ -52,19 +26,19 @@ require_relative '../extension/string'
52
26
  require_relative '../extension/symbol'
53
27
  require_relative '../extension/time'
54
28
 
55
- require_relative './sdk/account_properties'
56
- require_relative './sdk/action'
57
- require_relative './sdk/connection'
58
- require_relative './sdk/connector'
59
- require_relative './sdk/dsl'
60
- require_relative './sdk/errors'
61
- require_relative './sdk/lookup_tables'
62
- require_relative './sdk/object_definitions'
63
- require_relative './sdk/operation'
64
- require_relative './sdk/request'
65
- require_relative './sdk/settings'
66
- require_relative './sdk/summarize'
67
- require_relative './sdk/trigger'
68
- require_relative './sdk/version'
69
- require_relative './sdk/workato_schemas'
70
- require_relative './sdk/xml'
29
+ require_relative './sdk/core'
30
+
31
+ begin
32
+ tz = ENV.fetch('TZ', nil)
33
+ if tz.present? && tz != 'UTC'
34
+ warn "WARNING: TZ environment variable is set to '#{tz}'. Set TZ=UTC for consistency with Workato platform'"
35
+ else
36
+ ENV['TZ'] = 'UTC'
37
+ end
38
+ Time.zone = Workato::Connector::Sdk::DEFAULT_TIME_ZONE
39
+ rescue TZInfo::DataSourceNotFound
40
+ puts ''
41
+ puts "tzinfo-data is not present. Please install gem 'tzinfo-data' by 'gem install tzinfo-data'"
42
+ puts ''
43
+ exit!
44
+ end
@@ -1,6 +1,8 @@
1
1
  # typed: false
2
2
  # frozen_string_literal: true
3
3
 
4
+ require 'delegate'
5
+
4
6
  module Workato
5
7
  module Extension
6
8
  module Array
@@ -1,7 +1,6 @@
1
1
  # typed: false
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'rest-client'
5
4
  require 'net/http'
6
5
 
7
6
  module Workato
@@ -22,31 +21,6 @@ module Workato
22
21
 
23
22
  ::Net::HTTPHeader.prepend Net::HTTPHeader
24
23
  ::Net::HTTPGenericRequest.prepend Net::HTTPHeader
25
-
26
- module RestClient
27
- module Request
28
- attr_accessor :case_sensitive_headers
29
-
30
- def processed_headers
31
- return @processed_headers if case_sensitive_headers.blank?
32
- return case_sensitive_headers if @processed_headers.blank?
33
-
34
- @processed_headers.merge(case_sensitive_headers)
35
- end
36
-
37
- def execute(&block)
38
- # With 2.0.0+, net/http accepts URI objects in requests and handles wrapping
39
- # IPv6 addresses in [] for use in the Host request header.
40
- net_http_request = net_http_request_class(method).new(uri, processed_headers)
41
- net_http_request.case_sensitive_headers = case_sensitive_headers
42
- transmit(uri, net_http_request, payload, &block)
43
- ensure
44
- payload&.close
45
- end
46
- end
47
- end
48
-
49
- ::RestClient::Request.prepend RestClient::Request
50
24
  end
51
25
  end
52
26
  end
@@ -0,0 +1,69 @@
1
+ # typed: false
2
+ # frozen_string_literal: true
3
+
4
+ require 'rest-client'
5
+
6
+ module Workato
7
+ module Extension
8
+ module ContentEncodingDecoder
9
+ module RestClient
10
+ module Response
11
+ def create(body, net_http_res, request, start_time)
12
+ body = decode_content_encoding(net_http_res, body)
13
+ super(body, net_http_res, request, start_time)
14
+ end
15
+
16
+ private
17
+
18
+ def decode_content_encoding(response, body)
19
+ content_encoding = response['content-encoding']
20
+
21
+ case content_encoding&.downcase
22
+ when 'deflate', 'gzip', 'x-gzip'
23
+ response.delete 'content-encoding'
24
+ return body if body.blank?
25
+
26
+ deflate_string(body).force_encoding(Encoding.default_external)
27
+ when 'none', 'identity'
28
+ response.delete 'content-encoding'
29
+ body
30
+ else
31
+ body
32
+ end
33
+ end
34
+
35
+ def deflate_string(body)
36
+ # Decodes all deflate, gzip or x-gzip
37
+ zstream = Zlib::Inflate.new(Zlib::MAX_WBITS + 32)
38
+
39
+ zstream.inflate(body) + zstream.finish
40
+ rescue Zlib::DataError
41
+ # No luck with Zlib decompression. Let's try with raw deflate,
42
+ # like some broken web servers do. This part isn't compatible with Net::HTTP content-decoding
43
+ zstream.close
44
+
45
+ zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
46
+ zstream.inflate(body) + zstream.finish
47
+ ensure
48
+ zstream.close
49
+ end
50
+ end
51
+ end
52
+
53
+ ::RestClient::Response.singleton_class.prepend(RestClient::Response)
54
+
55
+ ::RestClient::Request.prepend(
56
+ Module.new do
57
+ def default_headers
58
+ # Should pass this header to be compatible with rest-client 2.0.2 version
59
+ # and rely on decode_content_encoding patch
60
+ # since net/http does not decompress response body if Content-Range is specified
61
+ # (see https://github.com/ruby/ruby/blob/27f6ad737b13062339df0a0c80449cf0dbc92ba5/lib/net/http/response.rb#L254)
62
+ # while the previous version of rest-client does.
63
+ super.tap { |headers| headers[:accept_encoding] = 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3' }
64
+ end
65
+ end
66
+ )
67
+ end
68
+ end
69
+ end