workato-connector-sdk 1.2.0 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +8 -0
  3. data/README.md +2 -6
  4. data/VERSION +1 -0
  5. data/lib/workato/cli/edit_command.rb +3 -1
  6. data/lib/workato/cli/exec_command.rb +76 -10
  7. data/lib/workato/cli/generate_command.rb +3 -2
  8. data/lib/workato/cli/main.rb +18 -10
  9. data/lib/workato/cli/oauth2_command.rb +4 -4
  10. data/lib/workato/cli/push_command.rb +23 -7
  11. data/lib/workato/cli/schema_command.rb +20 -6
  12. data/lib/workato/connector/sdk/account_properties.rb +3 -3
  13. data/lib/workato/connector/sdk/action.rb +20 -70
  14. data/lib/workato/connector/sdk/block_invocation_refinements.rb +4 -11
  15. data/lib/workato/connector/sdk/connection.rb +44 -21
  16. data/lib/workato/connector/sdk/connector.rb +73 -76
  17. data/lib/workato/connector/sdk/core.rb +62 -0
  18. data/lib/workato/connector/sdk/dsl/aws.rb +13 -3
  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/error.rb +2 -0
  22. data/lib/workato/connector/sdk/dsl/execution_context.rb +3 -0
  23. data/lib/workato/connector/sdk/dsl/http.rb +7 -2
  24. data/lib/workato/connector/sdk/dsl/reinvoke_after.rb +84 -0
  25. data/lib/workato/connector/sdk/dsl/stream_package.rb +59 -0
  26. data/lib/workato/connector/sdk/dsl/time.rb +0 -14
  27. data/lib/workato/connector/sdk/dsl/workato_package.rb +152 -0
  28. data/lib/workato/connector/sdk/dsl.rb +65 -10
  29. data/lib/workato/connector/sdk/errors.rb +28 -11
  30. data/lib/workato/connector/sdk/object_definitions.rb +59 -18
  31. data/lib/workato/connector/sdk/operation.rb +10 -3
  32. data/lib/workato/connector/sdk/request.rb +67 -26
  33. data/lib/workato/connector/sdk/schema/field/convertors.rb +2 -2
  34. data/lib/workato/connector/sdk/schema.rb +10 -7
  35. data/lib/workato/connector/sdk/settings.rb +13 -2
  36. data/lib/workato/connector/sdk/stream.rb +262 -0
  37. data/lib/workato/connector/sdk/streams.rb +72 -0
  38. data/lib/workato/connector/sdk/summarize.rb +4 -2
  39. data/lib/workato/connector/sdk/trigger.rb +14 -7
  40. data/lib/workato/connector/sdk/version.rb +1 -1
  41. data/lib/workato/connector/sdk.rb +20 -46
  42. data/lib/workato/extension/array.rb +2 -0
  43. data/lib/workato/extension/case_sensitive_headers.rb +0 -1
  44. data/lib/workato/extension/content_encoding_decoder.rb +2 -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/metadata_fix_wrap_kw_args.rb +11 -0
  52. data/lib/workato/extension/string.rb +23 -111
  53. data/lib/workato/testing/vcr_encrypted_cassette_serializer.rb +2 -0
  54. data/lib/workato/testing/vcr_multipart_body_matcher.rb +1 -0
  55. data/lib/workato/types/binary.rb +99 -0
  56. data/lib/workato/types/unicode_string.rb +62 -0
  57. metadata +34 -62
  58. data/lib/workato/connector/sdk/dsl/csv.rb +0 -125
  59. data/lib/workato/connector/sdk/dsl/workato_code_lib.rb +0 -167
  60. data/lib/workato/connector/sdk/schema/type/unicode_string.rb +0 -23
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b49034b5762b2b44d0987d72eb74327e379284347b793714149d85d354a5bb57
4
- data.tar.gz: 1be17d19381fe42689ef4a157a56eca0fb8c61a9c0e90e981e5a373305ed771f
3
+ metadata.gz: 2a456929ee155b6a048f547defcb4f3ccfcdd2172c1e0539ca601d8268bc0060
4
+ data.tar.gz: 588a1bae54828aa7fb750aaa53ca57336c14693478ac096b810b441008186fde
5
5
  SHA512:
6
- metadata.gz: 5bcc365d25ec713df12b75d9d6d5fb8a6a73266b94cf012829e4a2c98af955f1fcfa7b0d0f7e69861a4ee6cb54af24ed8952bbb590553e93a37fcf2933c69459
7
- data.tar.gz: 1da6193b9a1b04e3d3e2c6fb34fcd0eeec7666908c61df5c7ec386381ba8f33207b50b8ffc1e9d581fecb599fc423f84f9f79867120322356aa4d645b9b7da5e
6
+ metadata.gz: 5ab021777798644396d5d910c6d3c6f6ebf7ef23956ca7c3b5e79ec2d01d9f59776ea7afa4cbf8c9d501d18c4fc8142e1d4794e15bb3ade22692a3a95c94e4f4
7
+ data.tar.gz: e101977c93f1d878cd27c7170e143fbaf7f1221b52d80c489c5ca37915783662bd8571041bae0d4ad75094851ad74f00e6434c331da902d580e9e13098eb21a5
data/.yardopts ADDED
@@ -0,0 +1,8 @@
1
+ --title "Workato Connector SDK Ruby"
2
+ --main README.md
3
+ --no-private
4
+ --plugin sorbet
5
+ --exclude lib/workato/cli/
6
+ --exclude lib/workato/utilities/
7
+ --exclude lib/workato/web/
8
+ --exclude lib/workato/extension/
data/README.md CHANGED
@@ -13,7 +13,7 @@ This guide below showcases how you can do the following things:
13
13
 
14
14
  ## Prerequisites
15
15
  1. Install [RVM ("Ruby Version Manager")](http://rvm.io/) or a Ruby manager of your choice. You can find more at [here](https://www.ruby-lang.org/en/documentation/installation/)
16
- 2. Choose between Ruby versions `2.4.10` `2.5.X` or `2.7.X`. Our preferred version is `2.7.X`.
16
+ 2. Choose between Ruby versions `2.7.X`, `3.0.X`, `3.1.X`. Our preferred version is `2.7.6`.
17
17
  3. Verify you're running a valid ruby version. Do this by running either `ruby -v` or the commands within your version manager. i.e., `rvm current` if you have installed RVM.
18
18
  4. For Windows you need tzinfo-data gem installed as well. `gem install tzinfo-data`
19
19
  5. SDK depends on `charlock_holmes` gem. Check [gem's documentation](https://github.com/brianmario/charlock_holmes#installing) if you have troubles when install this dependency. Additional [details for Windows](https://github.com/brianmario/charlock_holmes/issues/84#issuecomment-652877605)
@@ -339,7 +339,6 @@ Options:
339
339
  [--col-sep=COL_SEP] # Use separator for CSV converter
340
340
  # Default: comma
341
341
  # Possible values: comma, space, tab, colon, semicolon, pipe
342
- [--api-email=API_EMAIL] # Email for accessing Workato API or set WORKATO_API_EMAIL environment variable
343
342
  [--api-token=API_TOKEN] # Token for accessing Workato API or set WORKATO_API_TOKEN environment variable
344
343
  ```
345
344
 
@@ -425,8 +424,6 @@ Options:
425
424
  -l, [--logo=LOGO] # Path to connector logo: png or jpeg file
426
425
  -n, [--notes=NOTES] # Release notes
427
426
  -c, [--connector=CONNECTOR] # Path to connector source code
428
- [--api-email=API_EMAIL] # Email for accessing Workato API.
429
- # If present overrides value from WORKATO_API_EMAIL environment variable.
430
427
  [--api-token=API_TOKEN] # Token for accessing Workato API.
431
428
  # If present overrides value from WORKATO_API_TOKEN environment variable.
432
429
  [--environment=ENVIRONMENT] # Data center specific URL to push connector code.
@@ -1124,7 +1121,7 @@ jobs:
1124
1121
  runs-on: ubuntu-latest
1125
1122
  strategy:
1126
1123
  matrix:
1127
- ruby-version: ['2.4.10', '2.5', '2.7']
1124
+ ruby-version: ['2.7', '3.0', '3.1']
1128
1125
 
1129
1126
  steps:
1130
1127
  - uses: actions/checkout@v2
@@ -1139,7 +1136,6 @@ jobs:
1139
1136
  run: bundle exec rspec
1140
1137
  # - name: Push to DEV workspace # Use this to push to DEV. This can be enabled when a PR is merged.
1141
1138
  # env:
1142
- # WORKATO_API_EMAIL: ${{ secrets.WORKATO_DEV_ENVIRONMENT_API_EMAIL}}
1143
1139
  # WORKATO_API_TOKEN: ${{ secrets.WORKATO_DEV_ENVIRONMENT_API_TOKEN}}
1144
1140
  # run: workato push
1145
1141
  ```
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.3.1
@@ -3,6 +3,8 @@
3
3
 
4
4
  require 'active_support/encrypted_configuration'
5
5
 
6
+ require_relative '../extension/metadata_fix_wrap_kw_args'
7
+
6
8
  module Workato
7
9
  module CLI
8
10
  class EditCommand
@@ -23,7 +25,7 @@ module Workato
23
25
 
24
26
  catch_editing_exceptions do
25
27
  encrypted_config.change do |tmp_path|
26
- system("#{ENV['EDITOR']} #{tmp_path}")
28
+ system("#{ENV.fetch('EDITOR', nil)} #{tmp_path}")
27
29
  end
28
30
  end
29
31
 
@@ -1,9 +1,12 @@
1
- # typed: false
1
+ # typed: true
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'thor'
5
+ require 'active_support/json'
5
6
  require_relative './multi_auth_selected_fallback'
6
7
 
8
+ Method.prepend(T::CompatibilityPatches::MethodExtensions)
9
+
7
10
  module Workato
8
11
  module CLI
9
12
  class ExecCommand
@@ -21,7 +24,7 @@ module Workato
21
24
  load_from_default_files
22
25
  inspect_params(params)
23
26
  output = with_progress { execute_path }
24
- show_output(output)
27
+ show_output(output.as_json)
25
28
  output
26
29
  end
27
30
 
@@ -65,8 +68,12 @@ module Workato
65
68
  oauth2_code: options[:oauth2_code],
66
69
  redirect_url: options[:redirect_url],
67
70
  refresh_token: options[:refresh_token],
71
+ from: options[:from].to_i,
72
+ frame_size: options[:frame_size]&.to_i || Workato::Connector::Sdk::Stream::DEFAULT_FRAME_SIZE,
68
73
  recipe_id: Workato::Connector::Sdk::Operation.recipe_id!
69
- }
74
+ }.tap do |h|
75
+ h[:to] = h[:from] + h[:frame_size] - 1
76
+ end
70
77
  end
71
78
 
72
79
  def connector
@@ -94,9 +101,10 @@ module Workato
94
101
  end
95
102
  end
96
103
 
97
- Workato::Connector::Sdk::Connection.on_settings_update = lambda do |message, &refresher|
104
+ Workato::Connector::Sdk::Connection.on_settings_update = lambda do |message, _settings_before, refresher|
98
105
  new_settings = refresher.call
99
106
  break unless new_settings
107
+ break new_settings if @settings == new_settings
100
108
 
101
109
  with_user_interaction do
102
110
  loop do
@@ -105,6 +113,7 @@ module Workato
105
113
  break new_settings if %w[n no].include?(answer)
106
114
  next unless %w[y yes].include?(answer)
107
115
 
116
+ @settings.merge!(new_settings)
108
117
  settings_store.update(new_settings)
109
118
  break new_settings
110
119
  end
@@ -135,11 +144,11 @@ module Workato
135
144
  end
136
145
 
137
146
  def execute_path
138
- connector.invoke(path, params)
147
+ InvokePath.new(path: path, connector: connector, params: params).call
139
148
  rescue Workato::Connector::Sdk::InvalidMultiAuthDefinition => e
140
- raise "#{e.message}. Please ensure:\n"\
149
+ raise "#{e.message}. Please ensure:\n" \
141
150
  "- 'selected' block is defined and returns value from 'options' list\n" \
142
- "- settings file contains value expected by 'selected' block\n\n"\
151
+ "- settings file contains value expected by 'selected' block\n\n" \
143
152
  'See more: https://docs.workato.com/developing-connectors/sdk/guides/authentication/multi_auth.html'
144
153
  rescue Exception => e # rubocop:disable Lint/RescueException
145
154
  raise DebugExceptionError, e if options[:debug]
@@ -149,9 +158,7 @@ module Workato
149
158
 
150
159
  def show_output(output)
151
160
  if options[:output].present?
152
- File.open(options[:output], 'w') do |f|
153
- f.write(JSON.dump(output))
154
- end
161
+ File.write(options[:output], JSON.dump(output))
155
162
  elsif options[:output].nil?
156
163
  say('OUTPUT') if verbose?
157
164
  jj output
@@ -214,6 +221,65 @@ module Workato
214
221
  alias puts log
215
222
  alias print log
216
223
  end
224
+
225
+ class InvokePath
226
+ extend T::Sig
227
+
228
+ sig do
229
+ params(
230
+ path: String,
231
+ connector: Workato::Connector::Sdk::Connector,
232
+ params: T::Hash[Symbol, T.untyped]
233
+ ).void
234
+ end
235
+ def initialize(path:, connector:, params:)
236
+ @path = T.let(path, String)
237
+ @connector = T.let(connector, Workato::Connector::Sdk::Connector)
238
+ @params = T.let(params, T::Hash[Symbol, T.untyped])
239
+ end
240
+
241
+ sig { returns(T.untyped) }
242
+ def call
243
+ invoke_path
244
+ end
245
+
246
+ private
247
+
248
+ sig { returns(String) }
249
+ attr_reader :path
250
+
251
+ sig { returns(Workato::Connector::Sdk::Connector) }
252
+ attr_reader :connector
253
+
254
+ sig { returns(T::Hash[Symbol, T.untyped]) }
255
+ attr_reader :params
256
+
257
+ sig { returns(T.untyped) }
258
+ def invoke_path
259
+ methods = path.split('.')
260
+ method = methods.pop
261
+ raise ArgumentError, 'path is not found' unless method
262
+
263
+ object = methods.inject(connector) { |obj, m| obj.public_send(m) }
264
+ output = invoke_method(object, method)
265
+ if output.respond_to?(:invoke)
266
+ invoke_method(output, :invoke)
267
+ else
268
+ output
269
+ end
270
+ end
271
+
272
+ sig { params(object: T.untyped, method: T.any(Symbol, String)).returns(T.untyped) }
273
+ def invoke_method(object, method)
274
+ parameters = object.method(method).parameters.reject { |p| p[0] == :block }.map(&:second)
275
+ args = params.values_at(*parameters)
276
+ if parameters.last == :args
277
+ args = args.take(args.length - 1) + Array.wrap(args.last).flatten(1)
278
+ end
279
+ object.public_send(method, *args)
280
+ end
281
+ end
282
+ private_constant :InvokePath
217
283
  end
218
284
  end
219
285
  end
@@ -50,8 +50,9 @@ module Workato
50
50
  enum: SchemaCommand::CSV_SEPARATORS,
51
51
  default: 'comma'
52
52
  method_option :api_email,
53
+ hide: true,
53
54
  type: :string,
54
- desc: 'Email for accessing Workato API or '\
55
+ desc: 'Email for accessing Workato API or ' \
55
56
  "set #{Workato::Connector::Sdk::WORKATO_API_EMAIL_ENV} environment variable"
56
57
  method_option :api_token,
57
58
  type: :string,
@@ -125,7 +126,7 @@ module Workato
125
126
  end
126
127
 
127
128
  def sanitized_filename(name)
128
- name.downcase.gsub(/[^0-9A-z.\-]/, '_')
129
+ name.downcase.gsub(/[^0-9A-z.-]/, '_')
129
130
  end
130
131
  end
131
132
  end
@@ -34,14 +34,14 @@ module Workato
34
34
  method_option :connector, type: :string, aliases: '-c', desc: 'Path to connector source code',
35
35
  lazy_default: Workato::Connector::Sdk::DEFAULT_CONNECTOR_PATH
36
36
  method_option :settings, type: :string, aliases: '-s',
37
- desc: 'Path to plain or encrypted file with connection configs, '\
37
+ desc: 'Path to plain or encrypted file with connection configs, ' \
38
38
  'passwords, tokens, secrets etc',
39
39
  lazy_default: Workato::Connector::Sdk::DEFAULT_ENCRYPTED_SETTINGS_PATH
40
40
  method_option :connection, type: :string, aliases: '-n',
41
41
  desc: 'Connection name if settings file contains multiple settings'
42
42
  method_option :key, type: :string, aliases: '-k',
43
43
  lazy_default: Workato::Connector::Sdk::DEFAULT_MASTER_KEY_PATH,
44
- desc: "Path to file with encrypt/decrypt key.\n"\
44
+ desc: "Path to file with encrypt/decrypt key.\n" \
45
45
  "NOTE: key from #{Workato::Connector::Sdk::DEFAULT_MASTER_KEY_ENV} has higher priority"
46
46
  method_option :input, type: :string, aliases: '-i', desc: 'Path to file with input JSON'
47
47
  method_option :closure, type: :string, desc: 'Path to file with next poll closure JSON'
@@ -61,6 +61,8 @@ module Workato
61
61
  method_option :oauth2_code, type: :string, desc: 'OAuth2 code exchange to tokens pair'
62
62
  method_option :redirect_url, type: :string, desc: 'OAuth2 callback url'
63
63
  method_option :refresh_token, type: :string, desc: 'OAuth2 refresh token'
64
+ method_option :from, type: :numeric, desc: 'Stream byte offset to read from'
65
+ method_option :frame_size, type: :numeric, desc: 'Stream chunk read size in bytes. Should be positive'
64
66
 
65
67
  method_option :debug, type: :boolean
66
68
 
@@ -75,7 +77,7 @@ module Workato
75
77
 
76
78
  method_option :key, type: :string, aliases: '-k',
77
79
  lazy_default: Workato::Connector::Sdk::DEFAULT_MASTER_KEY_PATH,
78
- desc: "Path to file with encrypt/decrypt key.\n"\
80
+ desc: "Path to file with encrypt/decrypt key.\n" \
79
81
  "NOTE: key from #{Workato::Connector::Sdk::DEFAULT_MASTER_KEY_ENV} has higher priority"
80
82
 
81
83
  def edit(path)
@@ -126,20 +128,21 @@ module Workato
126
128
  desc: 'Path to connector source code',
127
129
  lazy_default: Workato::Connector::Sdk::DEFAULT_CONNECTOR_PATH
128
130
  method_option :api_email,
131
+ hide: true,
129
132
  type: :string,
130
- desc: "Email for accessing Workato API.\n"\
131
- "If present overrides value from #{Workato::Connector::Sdk::WORKATO_API_EMAIL_ENV} "\
133
+ desc: "Email for accessing Workato API.\n" \
134
+ "If present overrides value from #{Workato::Connector::Sdk::WORKATO_API_EMAIL_ENV} " \
132
135
  'environment variable.'
133
136
  method_option :api_token,
134
137
  type: :string,
135
138
  desc: "Token for accessing Workato API.\n" \
136
- "If present overrides value from #{Workato::Connector::Sdk::WORKATO_API_TOKEN_ENV} "\
139
+ "If present overrides value from #{Workato::Connector::Sdk::WORKATO_API_TOKEN_ENV} " \
137
140
  'environment variable.'
138
141
  method_option :environment,
139
142
  type: :string,
140
- desc: "Data center specific URL to push connector code.\n"\
141
- "If present overrides value from #{Workato::Connector::Sdk::WORKATO_BASE_URL_ENV} "\
142
- "environment variable.\n"\
143
+ desc: "Data center specific URL to push connector code.\n" \
144
+ "If present overrides value from #{Workato::Connector::Sdk::WORKATO_BASE_URL_ENV} " \
145
+ "environment variable.\n" \
143
146
  "Examples: 'https://app.workato.com', 'https://app.eu.workato.com'"
144
147
  method_option :folder,
145
148
  type: :string,
@@ -171,7 +174,7 @@ module Workato
171
174
  type: :string,
172
175
  aliases: '-k',
173
176
  lazy_default: Workato::Connector::Sdk::DEFAULT_MASTER_KEY_PATH,
174
- desc: "Path to file with encrypt/decrypt key.\n"\
177
+ desc: "Path to file with encrypt/decrypt key.\n" \
175
178
  "NOTE: key from #{Workato::Connector::Sdk::DEFAULT_MASTER_KEY_ENV} has higher priority"
176
179
  method_option :port,
177
180
  type: :string,
@@ -191,6 +194,11 @@ module Workato
191
194
  ).call
192
195
  end
193
196
 
197
+ desc 'version', 'Shows gem version'
198
+ def version
199
+ puts Workato::Connector::Sdk::VERSION
200
+ end
201
+
194
202
  class << self
195
203
  def print_options(shell, options, group_name = nil)
196
204
  return if options.empty?
@@ -105,14 +105,14 @@ module Workato
105
105
 
106
106
  def ensure_oauth2_type
107
107
  unless connector.connection.authorization.oauth2?
108
- raise 'Authorization type is not OAuth2. '\
109
- 'For multi-auth connector ensure correct auth type was used. '\
108
+ raise 'Authorization type is not OAuth2. ' \
109
+ 'For multi-auth connector ensure correct auth type was used. ' \
110
110
  "Expected: 'oauth2', got: '#{connector.connection.authorization.type}''"
111
111
  end
112
112
  rescue Workato::Connector::Sdk::InvalidMultiAuthDefinition => e
113
- raise "#{e.message}. Please ensure:\n"\
113
+ raise "#{e.message}. Please ensure:\n" \
114
114
  "- 'selected' block is defined and returns value from 'options' list\n" \
115
- "- settings file contains value expected by 'selected' block\n\n"\
115
+ "- settings file contains value expected by 'selected' block\n\n" \
116
116
  'See more: https://docs.workato.com/developing-connectors/sdk/guides/authentication/multi_auth.html'
117
117
  end
118
118
 
@@ -5,6 +5,7 @@ require 'uri'
5
5
  require 'ruby-progressbar'
6
6
  require 'zip'
7
7
  require 'fileutils'
8
+ require 'thor'
8
9
 
9
10
  module Workato
10
11
  module CLI
@@ -35,8 +36,8 @@ module Workato
35
36
  @api_base_url = ENVIRONMENTS.fetch(options[:environment]) do
36
37
  options[:environment].presence || Workato::Connector::Sdk::WORKATO_BASE_URL
37
38
  end
38
- @api_email = options[:api_email] || ENV[Workato::Connector::Sdk::WORKATO_API_EMAIL_ENV]
39
- @api_token = options[:api_token] || ENV[Workato::Connector::Sdk::WORKATO_API_TOKEN_ENV]
39
+ @api_email = options[:api_email] || ENV.fetch(Workato::Connector::Sdk::WORKATO_API_EMAIL_ENV, nil)
40
+ @api_token = options[:api_token] || ENV.fetch(Workato::Connector::Sdk::WORKATO_API_TOKEN_ENV, nil)
40
41
  @folder_id = options[:folder]
41
42
  end
42
43
 
@@ -108,7 +109,7 @@ module Workato
108
109
  url = "#{api_base_url}#{API_IMPORT_PATH}/#{folder_id}"
109
110
  response = RestClient.post(
110
111
  url,
111
- File.open(zip_file_path),
112
+ File.open(zip_file_path, 'rb'),
112
113
  auth_headers.merge(
113
114
  'Content-Type' => 'application/zip'
114
115
  )
@@ -185,10 +186,25 @@ module Workato
185
186
  end
186
187
 
187
188
  def auth_headers
188
- {
189
- 'x-user-email' => api_email,
190
- 'x-user-token' => api_token
191
- }
189
+ @auth_headers ||=
190
+ if api_email.present?
191
+ warn <<~WARNING
192
+ You are using old authorization schema with --api-email and --api-token which is less secure and deprecated.
193
+ We strongly recommend migrating over to API Clients for authentication to Workato APIs.
194
+
195
+ Learn more: https://docs.workato.com/developing-connectors/sdk/cli/reference/cli-commands.html#workato-push
196
+
197
+ If you use API Client token but still see this message, ensure you do not pass --api-email param nor have #{Workato::Connector::Sdk::WORKATO_API_EMAIL_ENV} environment variable set.
198
+ WARNING
199
+ {
200
+ 'x-user-email' => api_email,
201
+ 'x-user-token' => api_token
202
+ }
203
+ else
204
+ {
205
+ 'Authorization' => "Bearer #{api_token}"
206
+ }
207
+ end
192
208
  end
193
209
 
194
210
  def folder_id
@@ -12,8 +12,8 @@ module Workato
12
12
  API_GENERATE_SCHEMA_PATH = '/api/sdk/generate_schema'
13
13
 
14
14
  def initialize(options:)
15
- @api_email = options[:api_email] || ENV[Workato::Connector::Sdk::WORKATO_API_EMAIL_ENV]
16
- @api_token = options[:api_token] || ENV[Workato::Connector::Sdk::WORKATO_API_TOKEN_ENV]
15
+ @api_email = options[:api_email] || ENV.fetch(Workato::Connector::Sdk::WORKATO_API_EMAIL_ENV, nil)
16
+ @api_token = options[:api_token] || ENV.fetch(Workato::Connector::Sdk::WORKATO_API_TOKEN_ENV, nil)
17
17
  @options = options
18
18
  end
19
19
 
@@ -68,10 +68,24 @@ module Workato
68
68
  end
69
69
 
70
70
  def auth_headers
71
- {
72
- 'x-user-email' => api_email,
73
- 'x-user-token' => api_token
74
- }
71
+ if api_email.present?
72
+ warn <<~WARNING
73
+ You are using old authorization schema with --api-email and --api-token which is less secure and deprecated.
74
+ We strongly recommend migrating over to API Clients for authentication to Workato APIs.
75
+
76
+ Learn more: https://docs.workato.com/developing-connectors/sdk/cli/reference/cli-commands.html#workato-generate-schema
77
+
78
+ If you use API Client token but still see this message, ensure you do not pass --api-email param nor have #{Workato::Connector::Sdk::WORKATO_API_EMAIL_ENV} environment variable set.
79
+ WARNING
80
+ {
81
+ 'x-user-email' => api_email,
82
+ 'x-user-token' => api_token
83
+ }
84
+ else
85
+ {
86
+ 'Authorization' => "Bearer #{api_token}"
87
+ }
88
+ end
75
89
  end
76
90
 
77
91
  private_constant :API_GENERATE_SCHEMA_PATH
@@ -13,7 +13,7 @@ module Workato
13
13
 
14
14
  def self.from_yaml(path = DEFAULT_ACCOUNT_PROPERTIES_PATH)
15
15
  File.open(path) do |f|
16
- instance.load_data(YAML.safe_load(ERB.new(f.read).result, [::Symbol]).to_hash)
16
+ instance.load_data(YAML.safe_load(ERB.new(f.read).result, permitted_classes: [::Symbol]).to_hash)
17
17
  end
18
18
  end
19
19
 
@@ -29,9 +29,9 @@ module Workato
29
29
  end
30
30
 
31
31
  def self.from_csv(path = './account_properties.csv')
32
- props = CSV.foreach(path, headers: true, return_headers: false).map do |row|
32
+ props = CSV.foreach(path, headers: true, return_headers: false).to_h do |row|
33
33
  [row[0], row[1]]
34
- end.to_h
34
+ end
35
35
  instance.load_data(props)
36
36
  end
37
37
 
@@ -11,29 +11,34 @@ module Workato
11
11
  extend T::Sig
12
12
  using BlockInvocationRefinements
13
13
 
14
+ include Dsl::ReinvokeAfter
15
+
14
16
  RETRY_DEFAULT_CODES = T.let([429, 500, 502, 503, 504, 507].freeze, T::Array[Integer])
15
17
  RETRY_DEFAULT_METHODS = T.let(%i[get head].freeze, T::Array[Symbol])
16
18
  RETRY_DELAY = T.let(5, Integer) # seconds
19
+ RETRY_DELAY_EXP_BASE = T.let(2, Integer)
17
20
  MAX_RETRIES = 3
18
21
 
19
- MAX_REINVOKES = 5
20
-
21
22
  sig do
22
23
  params(
23
24
  action: SorbetTypes::SourceHash,
24
25
  methods: SorbetTypes::SourceHash,
25
26
  connection: Connection,
26
- object_definitions: T.nilable(ObjectDefinitions)
27
+ object_definitions: T.nilable(ObjectDefinitions),
28
+ streams: Streams
27
29
  ).void
28
30
  end
29
- def initialize(action:, methods: {}, connection: Connection.new, object_definitions: nil)
31
+ def initialize(action:, methods: {}, connection: Connection.new, object_definitions: nil,
32
+ streams: ProhibitedStreams.new)
30
33
  super(
31
34
  operation: action,
32
35
  connection: connection,
33
36
  methods: methods,
34
- object_definitions: object_definitions
37
+ object_definitions: object_definitions,
38
+ streams: streams
35
39
  )
36
40
 
41
+ @retry_delay_factor = T.let(1, Integer)
37
42
  @retries_left = T.let(0, Integer)
38
43
  @retry_codes = T.let([], T::Array[Integer])
39
44
  @retry_methods = T.let([], T::Array[String])
@@ -58,33 +63,21 @@ module Workato
58
63
  &block)
59
64
  raise InvalidDefinitionError, "'execute' block is required for action" unless block || action[:execute]
60
65
 
61
- loop do
62
- if @reinvokes_remaining&.zero?
63
- raise "Max number of reinvokes on SDK Gem reached. Current limit is #{reinvoke_limit}"
64
- end
65
-
66
- reinvoke_sleep if @reinvoke_after
67
-
68
- reinvoke_reset
69
-
70
- result = super(
66
+ loop_reinvoke_after(continue) do |next_continue|
67
+ return super(
71
68
  settings,
72
69
  input,
73
70
  extended_input_schema,
74
71
  extended_output_schema,
75
- continue,
72
+ next_continue,
76
73
  &(block || action[:execute])
77
74
  )
78
-
79
- break result unless @reinvoke_after
80
-
81
- continue = @reinvoke_after.continue
82
75
  end
83
- rescue RequestError => e
76
+ rescue RequestFailedError => e
84
77
  raise e unless retry?(e)
85
78
 
86
79
  @retries_left -= 1
87
- sleep(RETRY_DELAY)
80
+ retry_sleep
88
81
  retry
89
82
  end
90
83
 
@@ -100,32 +93,6 @@ module Workato
100
93
  apply_output_schema(output, output_schema)
101
94
  end
102
95
 
103
- sig do
104
- params(
105
- continue: T::Hash[T.untyped, T.untyped],
106
- temp_output: T.nilable(T::Hash[T.untyped, T.untyped])
107
- ).void
108
- end
109
- def checkpoint!(continue:, temp_output: nil)
110
- # no-op
111
- end
112
-
113
- sig do
114
- params(
115
- seconds: Integer,
116
- continue: T::Hash[T.untyped, T.untyped],
117
- temp_output: T.nilable(T::Hash[T.untyped, T.untyped])
118
- ).void
119
- end
120
- def reinvoke_after(seconds:, continue:, temp_output: nil) # rubocop:disable Lint/UnusedMethodArgument
121
- @reinvokes_remaining = T.let(@reinvokes_remaining, T.nilable(Integer))
122
- @reinvokes_remaining = (@reinvokes_remaining ? @reinvokes_remaining - 1 : reinvoke_limit)
123
- @reinvoke_after = ReinvokeAfter.new(
124
- seconds: seconds,
125
- continue: continue
126
- )
127
- end
128
-
129
96
  private
130
97
 
131
98
  sig { returns(T::Array[T.any(Symbol, String, Regexp, Integer)]) }
@@ -150,10 +117,10 @@ module Workato
150
117
  retry_on_response.each { |m| m.is_a?(::Integer) ? @retry_codes << m : @retry_matchers << m }
151
118
  @retry_codes = RETRY_DEFAULT_CODES if @retry_codes.empty?
152
119
  @retry_methods = (retry_on_request.presence || RETRY_DEFAULT_METHODS).map(&:to_s).map(&:downcase)
153
- @retries_left = [[max_retries.is_a?(::Integer) && max_retries || MAX_RETRIES, MAX_RETRIES].min, 0].max
120
+ @retries_left = [[(max_retries.is_a?(::Integer) && max_retries) || MAX_RETRIES, MAX_RETRIES].min, 0].max
154
121
  end
155
122
 
156
- sig { params(exception: RequestError).returns(T::Boolean) }
123
+ sig { params(exception: RequestFailedError).returns(T::Boolean) }
157
124
  def retry?(exception)
158
125
  return false unless @retries_left.positive?
159
126
  return false unless @retry_codes.include?(exception.code.to_i)
@@ -165,28 +132,11 @@ module Workato
165
132
  end
166
133
 
167
134
  sig { void }
168
- def reinvoke_sleep
169
- sleep((ENV['WAIT_REINVOKE_AFTER'].presence || T.must(@reinvoke_after).seconds).to_f)
170
- end
171
-
172
- sig { returns(Integer) }
173
- def reinvoke_limit
174
- @reinvoke_limit = T.let(@reinvoke_limit, T.nilable(Integer))
175
- @reinvoke_limit ||= (ENV['MAX_REINVOKES'].presence || MAX_REINVOKES).to_i
176
- end
177
-
178
- sig { void }
179
- def reinvoke_reset
180
- @reinvoke_after = T.let(nil, T.nilable(ReinvokeAfter))
135
+ def retry_sleep
136
+ sleep(@retry_delay_factor * RETRY_DELAY)
137
+ @retry_delay_factor *= RETRY_DELAY_EXP_BASE
181
138
  end
182
139
 
183
- class ReinvokeAfter < T::Struct
184
- prop :seconds, T.any(Float, Integer)
185
- prop :continue, T::Hash[T.untyped, T.untyped]
186
- end
187
-
188
- private_constant :ReinvokeAfter
189
-
190
140
  alias action operation
191
141
  end
192
142
  end
@@ -4,27 +4,20 @@
4
4
  module Workato
5
5
  module Connector
6
6
  module Sdk
7
- # match proc's arguments, even if it's a lambda.
7
+ # Match proc's arguments, even if it's a lambda.
8
+ # @api private
8
9
  module BlockInvocationRefinements
9
- module CallRefinement
10
+ refine Proc do
10
11
  def call(*args, &block)
11
12
  super(*args.take(parameters.length), &block)
12
13
  end
13
14
  end
14
15
 
15
- refine Proc do
16
- prepend CallRefinement
17
- end
18
-
19
- module InstanceExecRefinement
16
+ refine BasicObject do
20
17
  def instance_exec(*args, &block)
21
18
  super(*args.take(block.parameters.length), &block)
22
19
  end
23
20
  end
24
-
25
- refine BasicObject do
26
- prepend InstanceExecRefinement
27
- end
28
21
  end
29
22
  end
30
23
  end