workato-connector-sdk 1.2.0 → 1.3.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.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/VERSION +1 -0
- data/lib/workato/cli/edit_command.rb +3 -1
- data/lib/workato/cli/exec_command.rb +76 -10
- data/lib/workato/cli/generate_command.rb +2 -2
- data/lib/workato/cli/main.rb +17 -10
- data/lib/workato/cli/oauth2_command.rb +4 -4
- data/lib/workato/cli/push_command.rb +2 -2
- data/lib/workato/cli/schema_command.rb +2 -2
- data/lib/workato/connector/sdk/account_properties.rb +2 -2
- data/lib/workato/connector/sdk/action.rb +20 -70
- data/lib/workato/connector/sdk/block_invocation_refinements.rb +2 -10
- data/lib/workato/connector/sdk/connection.rb +36 -19
- data/lib/workato/connector/sdk/connector.rb +65 -77
- data/lib/workato/connector/sdk/core.rb +62 -0
- data/lib/workato/connector/sdk/dsl/aws.rb +3 -3
- data/lib/workato/connector/sdk/dsl/call.rb +1 -1
- data/lib/workato/connector/sdk/dsl/csv_package.rb +133 -0
- data/lib/workato/connector/sdk/dsl/execution_context.rb +1 -0
- data/lib/workato/connector/sdk/dsl/http.rb +1 -1
- data/lib/workato/connector/sdk/dsl/reinvoke_after.rb +84 -0
- data/lib/workato/connector/sdk/dsl/stream_package.rb +65 -0
- data/lib/workato/connector/sdk/dsl/time.rb +0 -14
- data/lib/workato/connector/sdk/dsl/workato_package.rb +146 -0
- data/lib/workato/connector/sdk/dsl.rb +63 -10
- data/lib/workato/connector/sdk/errors.rb +28 -11
- data/lib/workato/connector/sdk/operation.rb +9 -2
- data/lib/workato/connector/sdk/request.rb +63 -25
- data/lib/workato/connector/sdk/schema/field/convertors.rb +2 -2
- data/lib/workato/connector/sdk/schema/type/unicode_string.rb +1 -1
- data/lib/workato/connector/sdk/schema.rb +7 -5
- data/lib/workato/connector/sdk/settings.rb +10 -1
- data/lib/workato/connector/sdk/stream.rb +243 -0
- data/lib/workato/connector/sdk/streams.rb +71 -0
- data/lib/workato/connector/sdk/summarize.rb +2 -2
- data/lib/workato/connector/sdk/trigger.rb +14 -7
- data/lib/workato/connector/sdk/version.rb +1 -1
- data/lib/workato/connector/sdk.rb +19 -46
- data/lib/workato/extension/array.rb +2 -0
- data/lib/workato/extension/case_sensitive_headers.rb +0 -1
- data/lib/workato/extension/content_encoding_decoder.rb +2 -0
- data/lib/workato/extension/currency/countries.rb +79 -0
- data/lib/workato/extension/currency/countries.yml +18433 -0
- data/lib/workato/extension/currency/currencies.rb +55 -0
- data/lib/workato/extension/currency/currencies.yml +479 -0
- data/lib/workato/extension/currency.rb +73 -5
- data/lib/workato/extension/enumerable.rb +2 -2
- data/lib/workato/extension/metadata_fix_wrap_kw_args.rb +11 -0
- data/lib/workato/extension/string.rb +14 -111
- data/lib/workato/testing/vcr_encrypted_cassette_serializer.rb +2 -0
- data/lib/workato/types/binary.rb +55 -0
- metadata +46 -61
- data/lib/workato/connector/sdk/dsl/csv.rb +0 -125
- data/lib/workato/connector/sdk/dsl/workato_code_lib.rb +0 -167
@@ -7,6 +7,7 @@ require 'json'
|
|
7
7
|
require 'gyoku'
|
8
8
|
require 'net/http'
|
9
9
|
require 'net/http/digest_auth'
|
10
|
+
require 'active_support/json'
|
10
11
|
|
11
12
|
require 'workato/utilities/encoding'
|
12
13
|
require 'workato/utilities/xml'
|
@@ -37,18 +38,20 @@ module Workato
|
|
37
38
|
@callstack_before_request = Array.wrap(Kernel.caller)
|
38
39
|
end
|
39
40
|
|
40
|
-
def method_missing(
|
41
|
-
execute!.send(
|
41
|
+
def method_missing(...)
|
42
|
+
execute!.send(...)
|
42
43
|
end
|
43
44
|
|
44
45
|
def execute!
|
45
46
|
__getobj__ || __setobj__(response)
|
47
|
+
rescue RestClient::Exceptions::Timeout => e
|
48
|
+
Kernel.raise RequestTimeoutError, e
|
46
49
|
rescue RestClient::Exception => e
|
47
50
|
if after_error_response_matches?(e)
|
48
51
|
return apply_after_error_response(e)
|
49
52
|
end
|
50
53
|
|
51
|
-
Kernel.raise
|
54
|
+
Kernel.raise RequestFailedError.new(
|
52
55
|
response: e.response,
|
53
56
|
message: e.message,
|
54
57
|
method: current_verb,
|
@@ -250,8 +253,8 @@ module Workato
|
|
250
253
|
::Kernel.puts(*args)
|
251
254
|
end
|
252
255
|
|
253
|
-
def try(
|
254
|
-
execute!.try(
|
256
|
+
def try(...)
|
257
|
+
execute!.try(...)
|
255
258
|
end
|
256
259
|
|
257
260
|
private
|
@@ -275,9 +278,9 @@ module Workato
|
|
275
278
|
request = RestClientRequest.new(rest_request_params)
|
276
279
|
response = execute_request(request)
|
277
280
|
end
|
278
|
-
|
281
|
+
detect_auth_error!(response.body)
|
279
282
|
parsed_response = @parse_response.call(response)
|
280
|
-
|
283
|
+
detect_auth_error!(parsed_response)
|
281
284
|
apply_after_response(response.code, parsed_response, response.headers)
|
282
285
|
end
|
283
286
|
end
|
@@ -322,7 +325,7 @@ module Workato
|
|
322
325
|
|
323
326
|
def build_url
|
324
327
|
uri = if @base_uri
|
325
|
-
|
328
|
+
merge_uris(@base_uri, @uri)
|
326
329
|
else
|
327
330
|
URI.parse(@uri)
|
328
331
|
end
|
@@ -347,9 +350,13 @@ module Workato
|
|
347
350
|
uri.to_s
|
348
351
|
end
|
349
352
|
|
353
|
+
def merge_uris(uri1, uri2)
|
354
|
+
(uri1.is_a?(::String) ? URI.parse(uri1) : uri1).merge(uri2)
|
355
|
+
end
|
356
|
+
|
350
357
|
def build_headers
|
351
358
|
headers = @headers
|
352
|
-
if @content_type_header.present? && headers.keys.none? { |key| /^content[
|
359
|
+
if @content_type_header.present? && headers.keys.none? { |key| /^content[-_]type$/i =~ key }
|
353
360
|
headers[:content_type] = @content_type_header
|
354
361
|
end
|
355
362
|
if @accept_header && headers.keys.none? { |key| /^accept$/i =~ key }
|
@@ -358,13 +365,13 @@ module Workato
|
|
358
365
|
headers.compact
|
359
366
|
end
|
360
367
|
|
361
|
-
def
|
368
|
+
def detect_auth_error!(response)
|
362
369
|
return unless authorized?
|
363
370
|
|
364
371
|
error_patterns = connection.authorization.detect_on
|
365
372
|
return unless error_patterns.any? { |pattern| pattern === response rescue false }
|
366
373
|
|
367
|
-
Kernel.raise(
|
374
|
+
Kernel.raise(DetectOnUnauthorizedRequestError, response.to_s)
|
368
375
|
end
|
369
376
|
|
370
377
|
def after_error_response_matches?(exception)
|
@@ -399,8 +406,8 @@ module Workato
|
|
399
406
|
within_action_context(code, parsed_response, encoded_headers, &@after_response)
|
400
407
|
end
|
401
408
|
|
402
|
-
def within_action_context(
|
403
|
-
(@action || self).instance_exec(
|
409
|
+
def within_action_context(...)
|
410
|
+
(@action || self).instance_exec(...)
|
404
411
|
end
|
405
412
|
|
406
413
|
sig { returns(T::Boolean) }
|
@@ -418,14 +425,14 @@ module Workato
|
|
418
425
|
begin
|
419
426
|
settings = connection.settings
|
420
427
|
if connection.authorization.oauth2?
|
421
|
-
|
428
|
+
apply_oauth2(settings, settings[:access_token], @auth_type, &apply)
|
422
429
|
else
|
423
|
-
|
430
|
+
apply_custom_auth(settings, @auth_type, &apply)
|
424
431
|
end
|
425
432
|
yield
|
426
|
-
rescue RestClient::Exception,
|
433
|
+
rescue RestClient::Exception, DetectOnUnauthorizedRequestError => e
|
427
434
|
Kernel.raise e unless first
|
428
|
-
Kernel.raise e unless refresh_authorization!(e.try(:http_code), e.try(:http_body), e.message)
|
435
|
+
Kernel.raise e unless refresh_authorization!(settings, e.try(:http_code), e.try(:http_body), e.message)
|
429
436
|
|
430
437
|
first = false
|
431
438
|
retry
|
@@ -434,16 +441,49 @@ module Workato
|
|
434
441
|
|
435
442
|
sig do
|
436
443
|
params(
|
444
|
+
settings: HashWithIndifferentAccess,
|
445
|
+
access_token: T.untyped,
|
446
|
+
auth_type: T.untyped,
|
447
|
+
apply_proc: T.proc.params(
|
448
|
+
settings: HashWithIndifferentAccess,
|
449
|
+
access_token: T.untyped,
|
450
|
+
auth_type: T.untyped
|
451
|
+
).void
|
452
|
+
).void
|
453
|
+
end
|
454
|
+
def apply_oauth2(settings, access_token, auth_type, &apply_proc)
|
455
|
+
instance_exec(settings, access_token, auth_type, &apply_proc)
|
456
|
+
end
|
457
|
+
|
458
|
+
sig do
|
459
|
+
params(
|
460
|
+
settings: HashWithIndifferentAccess,
|
461
|
+
auth_type: T.untyped,
|
462
|
+
apply_proc: T.proc.params(
|
463
|
+
settings: HashWithIndifferentAccess,
|
464
|
+
auth_type: T.untyped
|
465
|
+
).void
|
466
|
+
).void
|
467
|
+
end
|
468
|
+
def apply_custom_auth(settings, auth_type, &apply_proc)
|
469
|
+
instance_exec(settings, auth_type, &apply_proc)
|
470
|
+
end
|
471
|
+
|
472
|
+
sig do
|
473
|
+
params(
|
474
|
+
settings_before: HashWithIndifferentAccess,
|
437
475
|
http_code: T.nilable(Integer),
|
438
476
|
http_body: T.nilable(String),
|
439
477
|
exception: T.nilable(String)
|
440
478
|
).returns(T::Boolean)
|
441
479
|
end
|
442
|
-
def refresh_authorization!(http_code, http_body, exception)
|
480
|
+
def refresh_authorization!(settings_before, http_code, http_body, exception)
|
443
481
|
return false unless connection.authorization.refresh?(http_code, http_body, exception)
|
444
482
|
|
445
|
-
connection.update_settings!("Refresh token triggered on response \"#{exception}\"") do
|
446
|
-
connection.
|
483
|
+
connection.update_settings!("Refresh token triggered on response \"#{exception}\"", settings_before) do
|
484
|
+
next connection.settings unless connection.settings == settings_before
|
485
|
+
|
486
|
+
connection.authorization.refresh!(settings_before)
|
447
487
|
end
|
448
488
|
end
|
449
489
|
|
@@ -454,11 +494,9 @@ module Workato
|
|
454
494
|
|
455
495
|
def lambda_with_error_wrap(error_type, &block)
|
456
496
|
Kernel.lambda do |payload|
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
Kernel.raise error_type.new(e)
|
461
|
-
end
|
497
|
+
block.call(payload)
|
498
|
+
rescue StandardError => e
|
499
|
+
Kernel.raise error_type.new(e)
|
462
500
|
end
|
463
501
|
end
|
464
502
|
|
@@ -26,7 +26,7 @@ module Workato
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def integer_conversion(value)
|
29
|
-
value.try(:is_number?) && value.to_i || value
|
29
|
+
(value.try(:is_number?) && value.to_i) || value
|
30
30
|
end
|
31
31
|
|
32
32
|
def boolean_conversion(value)
|
@@ -34,7 +34,7 @@ module Workato
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def float_conversion(value)
|
37
|
-
value.try(:is_number?) && value.to_f || value
|
37
|
+
(value.try(:is_number?) && value.to_f) || value
|
38
38
|
end
|
39
39
|
|
40
40
|
def item_array_wrap(items)
|
@@ -101,14 +101,14 @@ module Workato
|
|
101
101
|
return Type::Time.from_date_time(value)
|
102
102
|
when ::Date
|
103
103
|
return value.to_date
|
104
|
-
when ::Numeric, ::TrueClass, ::FalseClass, Workato::
|
105
|
-
::Array, ::Hash
|
104
|
+
when ::Numeric, ::TrueClass, ::FalseClass, Workato::Types::Binary, Type::UnicodeString,
|
105
|
+
::Array, ::Hash, Stream::Proxy
|
106
106
|
return value
|
107
107
|
when Extension::Array::ArrayWhere
|
108
108
|
return value.to_a
|
109
109
|
when ::String
|
110
110
|
if value.encoding == Encoding::ASCII_8BIT
|
111
|
-
return Workato::
|
111
|
+
return Workato::Types::Binary.new(value)
|
112
112
|
end
|
113
113
|
|
114
114
|
return Type::UnicodeString.new(value)
|
@@ -119,7 +119,7 @@ module Workato
|
|
119
119
|
|
120
120
|
if value.respond_to?(:read) && value.respond_to?(:rewind)
|
121
121
|
value.rewind
|
122
|
-
return Workato::
|
122
|
+
return Workato::Types::Binary.new(value.read.force_encoding(Encoding::ASCII_8BIT))
|
123
123
|
end
|
124
124
|
end
|
125
125
|
|
@@ -178,7 +178,9 @@ module Workato
|
|
178
178
|
|
179
179
|
def clean_values(field)
|
180
180
|
field.transform_values! do |value|
|
181
|
-
value
|
181
|
+
next value if value.is_a?(FalseClass)
|
182
|
+
|
183
|
+
value.presence && ((value.is_a?(::Symbol) && value.to_s) || value)
|
182
184
|
end
|
183
185
|
field.compact!
|
184
186
|
field
|
@@ -123,7 +123,7 @@ module Workato
|
|
123
123
|
end
|
124
124
|
|
125
125
|
def encrypted_configuration
|
126
|
-
@encrypted_configuration ||=
|
126
|
+
@encrypted_configuration ||= FixedEncryptedConfiguration.new(
|
127
127
|
config_path: path,
|
128
128
|
key_path: key_path || DEFAULT_MASTER_KEY_PATH,
|
129
129
|
env_key: DEFAULT_MASTER_KEY_ENV,
|
@@ -135,6 +135,15 @@ module Workato
|
|
135
135
|
YAML.dump(settings.to_hash)
|
136
136
|
end
|
137
137
|
end
|
138
|
+
|
139
|
+
class FixedEncryptedConfiguration < ActiveSupport::EncryptedConfiguration
|
140
|
+
private
|
141
|
+
|
142
|
+
def handle_missing_key
|
143
|
+
# Original methods incorectly passes constructor params
|
144
|
+
raise MissingKeyError.new(key_path: key_path, env_key: env_key) if raise_if_missing_key
|
145
|
+
end
|
146
|
+
end
|
138
147
|
end
|
139
148
|
end
|
140
149
|
end
|
@@ -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)
|
@@ -34,15 +34,18 @@ module Workato
|
|
34
34
|
trigger: SorbetTypes::SourceHash,
|
35
35
|
methods: SorbetTypes::SourceHash,
|
36
36
|
connection: Connection,
|
37
|
-
object_definitions: T.nilable(ObjectDefinitions)
|
37
|
+
object_definitions: T.nilable(ObjectDefinitions),
|
38
|
+
streams: Streams
|
38
39
|
).void
|
39
40
|
end
|
40
|
-
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)
|
41
43
|
super(
|
42
44
|
operation: trigger,
|
43
45
|
connection: connection,
|
44
46
|
methods: methods,
|
45
|
-
object_definitions: object_definitions
|
47
|
+
object_definitions: object_definitions,
|
48
|
+
streams: streams
|
46
49
|
)
|
47
50
|
end
|
48
51
|
|
@@ -118,7 +121,7 @@ module Workato
|
|
118
121
|
headers: T::Hash[T.any(String, Symbol), T.untyped],
|
119
122
|
params: T::Hash[T.any(String, Symbol), T.untyped],
|
120
123
|
settings: T.nilable(SorbetTypes::SettingsHash),
|
121
|
-
webhook_subscribe_output: SorbetTypes::WebhookSubscribeOutputHash
|
124
|
+
webhook_subscribe_output: T.nilable(SorbetTypes::WebhookSubscribeOutputHash)
|
122
125
|
).returns(
|
123
126
|
SorbetTypes::WebhookNotificationOutputHash
|
124
127
|
)
|
@@ -134,8 +137,7 @@ module Workato
|
|
134
137
|
webhook_subscribe_output = {}
|
135
138
|
)
|
136
139
|
connection.merge_settings!(settings) if settings
|
137
|
-
output =
|
138
|
-
connection,
|
140
|
+
output = global_dsl_context.execute(
|
139
141
|
HashWithIndifferentAccess.wrap(input),
|
140
142
|
payload,
|
141
143
|
Array.wrap(extended_input_schema).map { |i| HashWithIndifferentAccess.wrap(i) },
|
@@ -190,7 +192,7 @@ module Workato
|
|
190
192
|
payload: T::Hash[T.any(String, Symbol), T.untyped],
|
191
193
|
headers: T::Hash[T.any(String, Symbol), T.untyped],
|
192
194
|
params: T::Hash[T.any(String, Symbol), T.untyped],
|
193
|
-
webhook_subscribe_output: SorbetTypes::WebhookSubscribeOutputHash
|
195
|
+
webhook_subscribe_output: T.nilable(SorbetTypes::WebhookSubscribeOutputHash)
|
194
196
|
).returns(
|
195
197
|
T.any(SorbetTypes::WebhookNotificationOutputHash, SorbetTypes::PollOutputHash)
|
196
198
|
)
|
@@ -232,6 +234,11 @@ module Workato
|
|
232
234
|
def webhook_notification?
|
233
235
|
trigger[:webhook_notification].present?
|
234
236
|
end
|
237
|
+
|
238
|
+
sig { returns(Dsl::WithDsl) }
|
239
|
+
def global_dsl_context
|
240
|
+
Dsl::WithDsl.new(connection, streams)
|
241
|
+
end
|
235
242
|
end
|
236
243
|
end
|
237
244
|
end
|