wisco 0.3.6 → 0.3.7
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/lib/wisco/commands/exec.rb +152 -10
- data/lib/wisco/commands/fixtures.rb +57 -2
- data/lib/wisco/exec_script.rb +160 -0
- data/lib/wisco/version.rb +1 -1
- data/lib/wisco.rb +3 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 942295e665d5ecea09078c736425531bb9846bfe29db26223bf52034ff4221b0
|
|
4
|
+
data.tar.gz: c56480bf18d42ac7797dd2b46f9d50146788f1590e673f4056bbe0ce55580347
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 797b1ac153469a31d1edd1781510bac1ac7c05a7f7b2545de34a48d40540a79fcbffd189c851b85d830f9ca63424a5f9006f1a85915bdd9bd6da01f9fe2da392
|
|
7
|
+
data.tar.gz: 7133a41ae9da79285993f77ccd32e65ff49c3b3c0d203140c1f3c128bdfa8657c8cd882d435ab180b1bd51811103e3c51f16f8c49ee67150388e11a5062e1448
|
data/lib/wisco/commands/exec.rb
CHANGED
|
@@ -4,6 +4,7 @@ require 'workato/cli/exec_command'
|
|
|
4
4
|
require_relative '../config'
|
|
5
5
|
require_relative '../connector'
|
|
6
6
|
require_relative '../path_utils'
|
|
7
|
+
require_relative '../exec_script'
|
|
7
8
|
|
|
8
9
|
module Wisco
|
|
9
10
|
module Commands
|
|
@@ -54,7 +55,7 @@ module Wisco
|
|
|
54
55
|
next
|
|
55
56
|
end
|
|
56
57
|
|
|
57
|
-
input_files = resolve_input_files(input, fixtures_dir)
|
|
58
|
+
input_files = resolve_input_files(input, fixtures_dir, debug: debug)
|
|
58
59
|
|
|
59
60
|
if input_files.empty?
|
|
60
61
|
if %w[pick_lists methods].include?(section)
|
|
@@ -71,19 +72,32 @@ module Wisco
|
|
|
71
72
|
end
|
|
72
73
|
|
|
73
74
|
input_files.each do |input_file|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
75
|
+
if File.extname(input_file).downcase == '.rb'
|
|
76
|
+
execute_ruby_script(section, key, input_file, fixtures_dir, target_dir,
|
|
77
|
+
connector_full_path, connection, config,
|
|
78
|
+
pagination: pagination, verbose: verbose,
|
|
79
|
+
extended: extended, closure: closure, config_fields: config_fields,
|
|
80
|
+
continue: continue, extended_input_schema: extended_input_schema,
|
|
81
|
+
extended_output_schema: extended_output_schema, debug: debug)
|
|
82
|
+
else
|
|
83
|
+
execute_one(section, key, input_file, fixtures_dir,
|
|
84
|
+
connector_full_path, connection, pagination: pagination, verbose: verbose,
|
|
85
|
+
extended: extended, closure: closure, config_fields: config_fields,
|
|
86
|
+
continue: continue, extended_input_schema: extended_input_schema,
|
|
87
|
+
extended_output_schema: extended_output_schema, debug: debug)
|
|
88
|
+
end
|
|
79
89
|
end
|
|
80
90
|
end
|
|
81
91
|
end
|
|
82
92
|
|
|
83
93
|
# Resolve the list of input files to execute.
|
|
84
94
|
# If an explicit input filename/path is given, use that (relative to fixtures_dir).
|
|
85
|
-
# Otherwise glob execute_
|
|
86
|
-
|
|
95
|
+
# Otherwise glob execute_*.{json,rb} in fixtures_dir and exclude files still containing
|
|
96
|
+
# their respective sentinel.
|
|
97
|
+
#
|
|
98
|
+
# In debug mode, prints which candidate files were found and which were
|
|
99
|
+
# skipped (because they still contain a sentinel comment).
|
|
100
|
+
def resolve_input_files(input, fixtures_dir, debug: false)
|
|
87
101
|
if input
|
|
88
102
|
path = File.absolute_path?(input) ? input : File.join(fixtures_dir, input)
|
|
89
103
|
unless File.exist?(path)
|
|
@@ -92,13 +106,28 @@ module Wisco
|
|
|
92
106
|
end
|
|
93
107
|
[path]
|
|
94
108
|
else
|
|
95
|
-
Dir.glob(File.join(fixtures_dir, 'execute_
|
|
96
|
-
|
|
109
|
+
candidates = Dir.glob(File.join(fixtures_dir, 'execute_*.{json,rb}')).select { |f| File.file?(f) }
|
|
110
|
+
warn "[exec] candidate files: #{candidates.map { |f| File.basename(f) }}" if debug
|
|
111
|
+
candidates.reject do |f|
|
|
112
|
+
if file_has_sentinel?(f)
|
|
113
|
+
warn "[exec] skipped (sentinel): #{File.basename(f)}" if debug
|
|
114
|
+
true
|
|
115
|
+
else
|
|
116
|
+
false
|
|
117
|
+
end
|
|
97
118
|
end
|
|
98
119
|
end
|
|
99
120
|
end
|
|
100
121
|
|
|
122
|
+
# Returns true if the file should be skipped. Each input format has its own
|
|
123
|
+
# sentinel convention:
|
|
124
|
+
# .json — first line exactly equals Wisco::Commands::Fixtures::SENTINEL
|
|
125
|
+
# .rb — first non-blank line matches `# WISCO_SKIP`
|
|
101
126
|
def file_has_sentinel?(path)
|
|
127
|
+
if File.extname(path).downcase == '.rb'
|
|
128
|
+
return Wisco::ExecScript.sentinel?(path)
|
|
129
|
+
end
|
|
130
|
+
|
|
102
131
|
first_line = begin
|
|
103
132
|
File.open(path, &:readline).chomp
|
|
104
133
|
rescue StandardError
|
|
@@ -223,6 +252,7 @@ module Wisco
|
|
|
223
252
|
cmd = Workato::CLI::ExecCommand.new(path: exec_path, options: options)
|
|
224
253
|
cmd.call
|
|
225
254
|
rescue StandardError => e
|
|
255
|
+
FileUtils.rm_f(output_file)
|
|
226
256
|
File.write(error_file, "#{e.class}: #{e.message}\n\n#{e.backtrace.join("\n")}\n")
|
|
227
257
|
Wisco::TerminalOutput.emit_error("Error executing #{section}.#{key} with #{input_file ? File.basename(input_file) : 'no input'}: #{e.message}")
|
|
228
258
|
Wisco::TerminalOutput.emit_error(" Details written to: #{error_file}")
|
|
@@ -237,6 +267,118 @@ module Wisco
|
|
|
237
267
|
File.write(output_file, pretty + "\n")
|
|
238
268
|
puts " Written: #{output_file}"
|
|
239
269
|
end
|
|
270
|
+
|
|
271
|
+
# Handles `execute_*.rb` scripts: evaluates the script to produce dynamic
|
|
272
|
+
# input, writes it to <subdir>/input.json, runs the connector item via
|
|
273
|
+
# ExecCommand, and writes <subdir>/output.json or <subdir>/error.txt.
|
|
274
|
+
# The subdirectory is named after the script (without .rb), e.g.
|
|
275
|
+
# execute_input.rb -> execute_input/.
|
|
276
|
+
def execute_ruby_script(section, key, script_path, fixtures_dir, target_dir,
|
|
277
|
+
connector_full_path, connection, config,
|
|
278
|
+
pagination: true, verbose: true, debug: false,
|
|
279
|
+
extended: true, closure: nil, config_fields: nil, continue: nil,
|
|
280
|
+
extended_input_schema: nil, extended_output_schema: nil)
|
|
281
|
+
subdir = File.join(fixtures_dir, File.basename(script_path, '.rb'))
|
|
282
|
+
FileUtils.mkdir_p(subdir)
|
|
283
|
+
input_file = File.join(subdir, 'input.json')
|
|
284
|
+
output_file = File.join(subdir, 'output.json')
|
|
285
|
+
error_file = File.join(subdir, 'error.txt')
|
|
286
|
+
|
|
287
|
+
# Step 1: evaluate the script to obtain dynamic input
|
|
288
|
+
connection_name = config['connection'] || 'default'
|
|
289
|
+
|
|
290
|
+
begin
|
|
291
|
+
generated = Wisco::ExecScript.evaluate(
|
|
292
|
+
script_path: script_path,
|
|
293
|
+
connector_full_path: connector_full_path,
|
|
294
|
+
target_dir: target_dir,
|
|
295
|
+
connection_name: connection_name
|
|
296
|
+
)
|
|
297
|
+
rescue StandardError => e
|
|
298
|
+
FileUtils.rm_f(input_file)
|
|
299
|
+
FileUtils.rm_f(output_file)
|
|
300
|
+
File.write(error_file, "#{e.class}: #{e.message}\n\n#{Array(e.backtrace).join("\n")}\n")
|
|
301
|
+
Wisco::TerminalOutput.emit_error("Error evaluating #{File.basename(script_path)}: #{e.message}")
|
|
302
|
+
Wisco::TerminalOutput.emit_error(" Details written to: #{error_file}")
|
|
303
|
+
return
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
File.write(input_file, JSON.pretty_generate(generated) + "\n")
|
|
307
|
+
puts " Generated: #{input_file}"
|
|
308
|
+
|
|
309
|
+
# Step 2: build ExecCommand options (mirrors execute_one)
|
|
310
|
+
use_args = %w[pick_lists methods].include?(section)
|
|
311
|
+
exec_path = if use_args
|
|
312
|
+
"#{section}.#{key}"
|
|
313
|
+
elsif section == 'triggers'
|
|
314
|
+
pagination ? "#{section}.#{key}.poll" : "#{section}.#{key}.poll_page"
|
|
315
|
+
else
|
|
316
|
+
"#{section}.#{key}.execute"
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
options = { connector: connector_full_path, output: output_file }
|
|
320
|
+
options[:connection] = connection if connection
|
|
321
|
+
options[:verbose] = verbose
|
|
322
|
+
if use_args
|
|
323
|
+
options[:args] = input_file
|
|
324
|
+
else
|
|
325
|
+
options[:input] = input_file
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
options[:closure] = resolve_option_path(closure, fixtures_dir) if closure
|
|
329
|
+
options[:config_fields] = resolve_option_path(config_fields, fixtures_dir) if config_fields
|
|
330
|
+
options[:continue] = resolve_option_path(continue, fixtures_dir) if continue
|
|
331
|
+
|
|
332
|
+
# extended schema files still live at the item's fixtures_dir (not the subdir)
|
|
333
|
+
unless use_args
|
|
334
|
+
eis = if extended_input_schema
|
|
335
|
+
resolve_option_path(extended_input_schema, fixtures_dir)
|
|
336
|
+
elsif extended
|
|
337
|
+
f = File.join(fixtures_dir, 'input_fields.json')
|
|
338
|
+
File.exist?(f) ? f : nil
|
|
339
|
+
end
|
|
340
|
+
options[:extended_input_schema] = eis if eis
|
|
341
|
+
|
|
342
|
+
eos = if extended_output_schema
|
|
343
|
+
resolve_option_path(extended_output_schema, fixtures_dir)
|
|
344
|
+
elsif extended
|
|
345
|
+
f = File.join(fixtures_dir, 'output_fields.json')
|
|
346
|
+
File.exist?(f) ? f : nil
|
|
347
|
+
end
|
|
348
|
+
options[:extended_output_schema] = eos if eos
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
if debug
|
|
352
|
+
warn "[exec.rb] script: #{script_path}"
|
|
353
|
+
warn "[exec.rb] subdir: #{subdir}"
|
|
354
|
+
warn "[exec.rb] path: #{exec_path}"
|
|
355
|
+
warn "[exec.rb] connector: #{connector_full_path}"
|
|
356
|
+
warn "[exec.rb] connection: #{connection.inspect}"
|
|
357
|
+
warn "[exec.rb] #{use_args ? 'args' : 'input'}: #{input_file}"
|
|
358
|
+
warn "[exec.rb] output: #{output_file}"
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
# Step 3: invoke ExecCommand against the generated input
|
|
362
|
+
begin
|
|
363
|
+
cmd = Workato::CLI::ExecCommand.new(path: exec_path, options: options)
|
|
364
|
+
cmd.call
|
|
365
|
+
rescue StandardError => e
|
|
366
|
+
FileUtils.rm_f(input_file)
|
|
367
|
+
FileUtils.rm_f(output_file)
|
|
368
|
+
File.write(error_file, "#{e.class}: #{e.message}\n\n#{e.backtrace.join("\n")}\n")
|
|
369
|
+
Wisco::TerminalOutput.emit_error("Error executing #{section}.#{key} with #{File.basename(script_path)}: #{e.message}")
|
|
370
|
+
Wisco::TerminalOutput.emit_error(" Details written to: #{error_file}")
|
|
371
|
+
return
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
FileUtils.rm_f(error_file)
|
|
375
|
+
|
|
376
|
+
return unless File.exist?(output_file)
|
|
377
|
+
|
|
378
|
+
pretty = JSON.pretty_generate(JSON.parse(File.read(output_file)))
|
|
379
|
+
File.write(output_file, pretty + "\n")
|
|
380
|
+
puts " Written: #{output_file}"
|
|
381
|
+
end
|
|
240
382
|
end
|
|
241
383
|
end
|
|
242
384
|
end
|
|
@@ -8,11 +8,34 @@ require_relative '../path_utils'
|
|
|
8
8
|
module Wisco
|
|
9
9
|
module Commands
|
|
10
10
|
module Fixtures
|
|
11
|
-
SENTINEL
|
|
11
|
+
SENTINEL = '# Remove this comment before updating. Files that include this line will be overwritten.'
|
|
12
|
+
RB_SENTINEL = '# WISCO_SKIP'
|
|
13
|
+
|
|
14
|
+
RB_TEMPLATE = <<~RUBY
|
|
15
|
+
# WISCO_SKIP
|
|
16
|
+
# Remove the WISCO_SKIP line above once this script is ready to run.
|
|
17
|
+
#
|
|
18
|
+
# The last expression in this file becomes the input passed to the connector item.
|
|
19
|
+
# Helper methods available inside the script:
|
|
20
|
+
# call_method(:name, *args) — invoke a methods: entry on the connector
|
|
21
|
+
# call_pick_list(:name, *args) — invoke a pick_lists: entry on the connector
|
|
22
|
+
# connection — Hash of decrypted settings.yaml(.enc)
|
|
23
|
+
#
|
|
24
|
+
# Example:
|
|
25
|
+
# require 'securerandom'
|
|
26
|
+
# {
|
|
27
|
+
# order_number: "ORD-\#{SecureRandom.hex(4).upcase}",
|
|
28
|
+
# created_at: Time.now.iso8601
|
|
29
|
+
# }
|
|
30
|
+
|
|
31
|
+
{
|
|
32
|
+
# TODO: fill in fields
|
|
33
|
+
}
|
|
34
|
+
RUBY
|
|
12
35
|
|
|
13
36
|
module_function
|
|
14
37
|
|
|
15
|
-
def run(path_arg, target_dir, overwrite: false, debug: false)
|
|
38
|
+
def run(path_arg, target_dir, overwrite: false, ruby: false, debug: false)
|
|
16
39
|
target_dir = File.expand_path(target_dir)
|
|
17
40
|
config_path = Wisco.config_path(target_dir)
|
|
18
41
|
|
|
@@ -44,8 +67,10 @@ module Wisco
|
|
|
44
67
|
|
|
45
68
|
if section == 'pick_lists'
|
|
46
69
|
process_pick_list(key, connector, fixtures_dir, overwrite: overwrite)
|
|
70
|
+
generate_execute_input_rb(fixtures_dir, overwrite: overwrite) if ruby
|
|
47
71
|
elsif section == 'methods'
|
|
48
72
|
process_method(key, connector, fixtures_dir, overwrite: overwrite)
|
|
73
|
+
generate_execute_input_rb(fixtures_dir, overwrite: overwrite) if ruby
|
|
49
74
|
else
|
|
50
75
|
# ── config_fields pre-check ──────────────────────────────────────
|
|
51
76
|
item = connector[section.to_sym]&.[](key.to_sym)
|
|
@@ -76,6 +101,7 @@ module Wisco
|
|
|
76
101
|
)
|
|
77
102
|
|
|
78
103
|
generate_execute_input(input_fields_file, fixtures_dir, overwrite: overwrite, debug: debug)
|
|
104
|
+
generate_execute_input_rb(fixtures_dir, overwrite: overwrite) if ruby
|
|
79
105
|
|
|
80
106
|
# ── output_fields ────────────────────────────────────────────────
|
|
81
107
|
output_fields_file = File.join(fixtures_dir, 'output_fields.json')
|
|
@@ -133,6 +159,35 @@ module Wisco
|
|
|
133
159
|
puts " Written: #{output_file}"
|
|
134
160
|
end
|
|
135
161
|
|
|
162
|
+
# Writes an `execute_input.rb` template into `fixtures_dir`. The template
|
|
163
|
+
# is prefixed with `# WISCO_SKIP` so it is identifiable as unedited and
|
|
164
|
+
# will be skipped by `wisco exec` until the user removes that line.
|
|
165
|
+
#
|
|
166
|
+
# Overwrite rules mirror generate_execute_input:
|
|
167
|
+
# - File absent -> write
|
|
168
|
+
# - File present, # WISCO_SKIP on L1 -> overwrite (still a template)
|
|
169
|
+
# - File present, no sentinel -> skip (user-edited); force with --overwrite
|
|
170
|
+
def generate_execute_input_rb(fixtures_dir, overwrite: false)
|
|
171
|
+
output_file = File.join(fixtures_dir, 'execute_input.rb')
|
|
172
|
+
|
|
173
|
+
if File.exist?(output_file)
|
|
174
|
+
first_line = begin
|
|
175
|
+
File.open(output_file, &:readline).chomp
|
|
176
|
+
rescue StandardError
|
|
177
|
+
''
|
|
178
|
+
end
|
|
179
|
+
has_sentinel = first_line.strip == RB_SENTINEL
|
|
180
|
+
|
|
181
|
+
unless has_sentinel || overwrite
|
|
182
|
+
puts " Skipped (user-edited): #{output_file}"
|
|
183
|
+
return
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
File.write(output_file, RB_TEMPLATE)
|
|
188
|
+
puts " Written: #{output_file}"
|
|
189
|
+
end
|
|
190
|
+
|
|
136
191
|
# Recursively converts a Workato schema array into a template hash.
|
|
137
192
|
# Scalars become "<type_value_required|optional>" placeholder strings.
|
|
138
193
|
# Objects expand into a nested hash via their properties.
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
require 'workato/connector/sdk'
|
|
2
|
+
require_relative 'terminal_output'
|
|
3
|
+
|
|
4
|
+
module Wisco
|
|
5
|
+
# Evaluates an `execute_*.rb` script and returns the value of its last
|
|
6
|
+
# expression. The script is eval'd inside a binding that exposes helpers
|
|
7
|
+
# (`call_method`, `call_pick_list`, `connection`) so the script can build
|
|
8
|
+
# dynamic input that varies per run.
|
|
9
|
+
module ExecScript
|
|
10
|
+
SENTINEL_REGEX = /\A\s*#\s*WISCO_SKIP\b/.freeze
|
|
11
|
+
|
|
12
|
+
module_function
|
|
13
|
+
|
|
14
|
+
# Returns true if the file's first non-blank line is a `# WISCO_SKIP`
|
|
15
|
+
# comment, in which case the script should be skipped by `wisco exec`.
|
|
16
|
+
def sentinel?(path)
|
|
17
|
+
File.foreach(path) do |line|
|
|
18
|
+
stripped = line.strip
|
|
19
|
+
next if stripped.empty?
|
|
20
|
+
return SENTINEL_REGEX.match?(line)
|
|
21
|
+
end
|
|
22
|
+
false
|
|
23
|
+
rescue StandardError
|
|
24
|
+
false
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Evaluates the script at `script_path` and returns the value of its last
|
|
28
|
+
# expression. Raises StandardError subclasses on:
|
|
29
|
+
# - syntax / runtime errors in the script
|
|
30
|
+
# - invalid return value (must be a Hash or Array)
|
|
31
|
+
#
|
|
32
|
+
# `connector_full_path` — absolute path to connector.rb (used to build
|
|
33
|
+
# the SDK Connector for helper invocations).
|
|
34
|
+
# `target_dir` — connector project root (used to find
|
|
35
|
+
# settings.yaml(.enc) + master.key).
|
|
36
|
+
# `connection_name` — connection key inside settings.yaml; defaults to 'default'.
|
|
37
|
+
def evaluate(script_path:, connector_full_path:, target_dir:, connection_name: 'default')
|
|
38
|
+
host = ScriptHost.new(connector_full_path, target_dir, connection_name)
|
|
39
|
+
source = File.read(script_path)
|
|
40
|
+
result = host.instance_eval(source, script_path, 1)
|
|
41
|
+
|
|
42
|
+
unless result.is_a?(Hash) || result.is_a?(Array)
|
|
43
|
+
raise InvalidReturn,
|
|
44
|
+
"Script must return a Hash (for actions/triggers) or Array/Hash (for methods/pick_lists). " \
|
|
45
|
+
"Got: #{result.class}"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
result
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
class InvalidReturn < StandardError; end
|
|
52
|
+
|
|
53
|
+
# Host object that the script is eval'd against. Exposes the helper API.
|
|
54
|
+
# Defined as a class (not a Module) so `instance_eval` gives the script
|
|
55
|
+
# access to standard top-level Ruby plus our helpers, without polluting
|
|
56
|
+
# Object globally.
|
|
57
|
+
class ScriptHost
|
|
58
|
+
def initialize(connector_full_path, target_dir, connection_name)
|
|
59
|
+
@connector_full_path = connector_full_path
|
|
60
|
+
@target_dir = target_dir
|
|
61
|
+
@connection_name = connection_name || 'default'
|
|
62
|
+
@sdk_connector = nil
|
|
63
|
+
@connection_loaded = false
|
|
64
|
+
@connection_cached = nil
|
|
65
|
+
@warned_settings = false
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Hash of decrypted settings for the configured connection. Returns {}
|
|
69
|
+
# and emits a one-time warning if settings can't be loaded.
|
|
70
|
+
def connection
|
|
71
|
+
return @connection_cached if @connection_loaded
|
|
72
|
+
|
|
73
|
+
@connection_loaded = true
|
|
74
|
+
@connection_cached = load_connection
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Invoke a connector `methods:` entry. Args are forwarded to the lambda
|
|
78
|
+
# as-is. Returns the lambda's return value.
|
|
79
|
+
#
|
|
80
|
+
# Example:
|
|
81
|
+
# call_method(:format_timestamp, Time.now)
|
|
82
|
+
def call_method(name, *args)
|
|
83
|
+
proxy = sdk_connector.methods
|
|
84
|
+
unless proxy.respond_to?(name.to_sym)
|
|
85
|
+
raise InvalidReturn, "No methods entry named '#{name}' found in connector."
|
|
86
|
+
end
|
|
87
|
+
proxy.public_send(name.to_sym, *args)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Invoke a connector `pick_lists:` entry. `args` is a Hash of named
|
|
91
|
+
# arguments for dependent pick lists. The SDK supplies `connection` to
|
|
92
|
+
# the lambda automatically.
|
|
93
|
+
#
|
|
94
|
+
# Examples:
|
|
95
|
+
# call_pick_list(:active_customers)
|
|
96
|
+
# call_pick_list(:customer_orders, customer_id: 123)
|
|
97
|
+
def call_pick_list(name, **args)
|
|
98
|
+
proxy = sdk_connector.pick_lists
|
|
99
|
+
unless proxy.respond_to?(name.to_sym)
|
|
100
|
+
raise InvalidReturn, "No pick_lists entry named '#{name}' found in connector."
|
|
101
|
+
end
|
|
102
|
+
# SDK signature: pick_list_name(settings = nil, args = {})
|
|
103
|
+
# Passing nil for settings tells the SDK to reuse the connector's settings.
|
|
104
|
+
proxy.public_send(name.to_sym, nil, args)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
private
|
|
108
|
+
|
|
109
|
+
def sdk_connector
|
|
110
|
+
@sdk_connector ||= Workato::Connector::Sdk::Connector.from_file(@connector_full_path, connection)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Tries (in order): settings.yaml.enc + master.key, then settings.yaml.
|
|
114
|
+
# Uses Workato::Connector::Sdk::Settings so encryption is handled by the
|
|
115
|
+
# SDK's own loader (same path it uses for `wisco exec`). Returns {} and
|
|
116
|
+
# warns once on any failure.
|
|
117
|
+
def load_connection
|
|
118
|
+
enc_file = File.join(@target_dir, 'settings.yaml.enc')
|
|
119
|
+
key_file = File.join(@target_dir, 'master.key')
|
|
120
|
+
yaml_file = File.join(@target_dir, 'settings.yaml')
|
|
121
|
+
|
|
122
|
+
if File.exist?(enc_file) && File.exist?(key_file)
|
|
123
|
+
read_settings(enc_file) do |name|
|
|
124
|
+
Workato::Connector::Sdk::Settings.from_encrypted_file(enc_file, key_file, name)
|
|
125
|
+
end
|
|
126
|
+
elsif File.exist?(yaml_file)
|
|
127
|
+
read_settings(yaml_file) do |name|
|
|
128
|
+
Workato::Connector::Sdk::Settings.from_file(yaml_file, name)
|
|
129
|
+
end
|
|
130
|
+
else
|
|
131
|
+
warn_settings("No settings.yaml or settings.yaml.enc found in #{@target_dir}")
|
|
132
|
+
{}
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Reads settings using a Settings.from_* loader. Tries with the configured
|
|
137
|
+
# connection name first; if that key isn't present at the top level
|
|
138
|
+
# (KeyError), falls back to loading the whole file as a flat hash.
|
|
139
|
+
def read_settings(path)
|
|
140
|
+
hash = begin
|
|
141
|
+
yield(@connection_name)
|
|
142
|
+
rescue KeyError
|
|
143
|
+
yield(nil)
|
|
144
|
+
end
|
|
145
|
+
return {} unless hash.respond_to?(:to_h)
|
|
146
|
+
|
|
147
|
+
hash.to_h
|
|
148
|
+
rescue StandardError => e
|
|
149
|
+
warn_settings("Failed to load settings from #{path}: #{e.message}")
|
|
150
|
+
{}
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def warn_settings(msg)
|
|
154
|
+
return if @warned_settings
|
|
155
|
+
@warned_settings = true
|
|
156
|
+
Wisco::TerminalOutput.emit_warning("[WARN] connection helper: #{msg}. Returning {}.")
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
data/lib/wisco/version.rb
CHANGED
data/lib/wisco.rb
CHANGED
|
@@ -127,12 +127,15 @@ module Wisco
|
|
|
127
127
|
get_users auto-detect section
|
|
128
128
|
DESC
|
|
129
129
|
option :overwrite, type: :boolean, default: false, desc: 'Overwrite execute_input.json even if user-edited'
|
|
130
|
+
option :ruby, type: :boolean, default: false,
|
|
131
|
+
desc: 'Also scaffold an execute_input.rb template for dynamic input scripts'
|
|
130
132
|
option :debug, type: :boolean, default: false, desc: 'Print ExecCommand call details'
|
|
131
133
|
def fixtures(path_arg, target_dir = nil)
|
|
132
134
|
Wisco::Commands::Fixtures.run(
|
|
133
135
|
path_arg,
|
|
134
136
|
target_dir || Dir.pwd,
|
|
135
137
|
overwrite: options[:overwrite],
|
|
138
|
+
ruby: options[:ruby],
|
|
136
139
|
debug: options[:debug]
|
|
137
140
|
)
|
|
138
141
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: wisco
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- mbillington
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-06-
|
|
11
|
+
date: 2026-06-07 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activesupport
|
|
@@ -77,6 +77,7 @@ files:
|
|
|
77
77
|
- lib/wisco/commands/schema.rb
|
|
78
78
|
- lib/wisco/config.rb
|
|
79
79
|
- lib/wisco/connector.rb
|
|
80
|
+
- lib/wisco/exec_script.rb
|
|
80
81
|
- lib/wisco/path_utils.rb
|
|
81
82
|
- lib/wisco/profile.rb
|
|
82
83
|
- lib/wisco/terminal_output.rb
|