wisco 0.3.8 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a6489b0aaac5c9626f27141afebc7b4dda9b087c2cf94fee0744b9b603de4953
4
- data.tar.gz: 298e1469cd688e9d824fd091d32ea84526934637b96e92a4ea19243dfb715e49
3
+ metadata.gz: 9d0223c07b265d6b699acec69facb0abc3cded752a3b99791454507bf8623490
4
+ data.tar.gz: 82b76acb11a65728840067d60bb809f0fb4f88421b0efeac922b967915cef2dc
5
5
  SHA512:
6
- metadata.gz: 4b711094e3bf5990c6a591a9a75356660c86d813a76df331f101c8cf48ecbf3d98edcf9f4ede28c4c3cff1448f19991ef89383a1fecb5c78c8a21a3b1a1ce88c
7
- data.tar.gz: 1581e25abeb992cb6eee659407561df32a47ecbe2cacacf9bb5ea55650eabe27015114c97cf6d5f5bcbba4acbf5593416c1bb5b37ca612f682b7095ba3708ccb
6
+ metadata.gz: 91cae2af261537aa28ab79a66f817fc4095f06c7d2f7cc16281e181872e4d5101b09386cc31793b1d8da09dbf03040946d2b162c41d3705062c4a7b77a5bd7a9
7
+ data.tar.gz: 8355aa7b644b559c082d656ca19134b3af9c3a2803f1e31ba7e27b4a31d11af9ea1788a558f259e69d7c4d0af88b5e6f27abf19d223b312c1aa1c273cda93d9b
@@ -6,6 +6,7 @@ require_relative '../config'
6
6
  require_relative '../connector'
7
7
  require_relative '../path_utils'
8
8
  require_relative '../exec_script'
9
+ require_relative 'fixtures'
9
10
 
10
11
  module Wisco
11
12
  module Commands
@@ -14,7 +15,8 @@ module Wisco
14
15
 
15
16
  def run(path_arg, target_dir, input: nil, pagination: true, verbose: false, debug: false,
16
17
  extended: true, closure: nil, config_fields: nil, continue: nil,
17
- extended_input_schema: nil, extended_output_schema: nil)
18
+ extended_input_schema: nil, extended_output_schema: nil,
19
+ summary: true, summary_lines: 20)
18
20
  target_dir = File.expand_path(target_dir)
19
21
  config_path = Wisco.config_path(target_dir)
20
22
 
@@ -51,12 +53,12 @@ module Wisco
51
53
  fixture_dir_output = fixtures_dir.sub(connector_path, '.')
52
54
 
53
55
  unless File.directory?(fixtures_dir)
54
- Wisco::TerminalOutput.emit_error("Error: fixtures directory not found: #{fixture_dir_output}")
55
- Wisco::TerminalOutput.emit_error(" Run '#{Wisco::CLI_NAME} fixtures #{section}.#{key}' first.")
56
- next
56
+ puts " Auto-setup: running fixtures for #{section}.#{key}"
57
+ Wisco::Commands::Fixtures.run("#{section}.#{key}", target_dir, debug: debug)
57
58
  end
58
59
 
59
60
  input_files = resolve_input_files(input, fixtures_dir, debug: debug)
61
+ batch = pairs.length > 1 || input_files.length > 1
60
62
 
61
63
  if input_files.empty?
62
64
  if %w[pick_lists methods].include?(section)
@@ -65,9 +67,14 @@ module Wisco
65
67
  pagination: pagination, verbose: verbose, extended: extended,
66
68
  closure: closure, config_fields: config_fields, continue: continue,
67
69
  extended_input_schema: extended_input_schema,
68
- extended_output_schema: extended_output_schema, debug: debug)
70
+ extended_output_schema: extended_output_schema, debug: debug,
71
+ summary: summary, summary_lines: summary_lines, batch: batch)
69
72
  else
70
73
  Wisco::TerminalOutput.emit_warning(" Warning: No ready input files found in #{fixture_dir_output}")
74
+ input_template = File.join(fixtures_dir, 'execute_input.json')
75
+ if File.exist?(input_template)
76
+ Wisco::TerminalOutput.emit_info(" Fill in #{File.join(fixture_dir_output, 'execute_input.json')} and re-run.")
77
+ end
71
78
  end
72
79
  next
73
80
  end
@@ -79,13 +86,15 @@ module Wisco
79
86
  pagination: pagination, verbose: verbose,
80
87
  extended: extended, closure: closure, config_fields: config_fields,
81
88
  continue: continue, extended_input_schema: extended_input_schema,
82
- extended_output_schema: extended_output_schema, debug: debug)
89
+ extended_output_schema: extended_output_schema, debug: debug,
90
+ summary: summary, summary_lines: summary_lines, batch: batch)
83
91
  else
84
92
  execute_one(section, key, input_file, fixtures_dir,
85
93
  connector_full_path, connection, pagination: pagination, verbose: verbose,
86
94
  extended: extended, closure: closure, config_fields: config_fields,
87
95
  continue: continue, extended_input_schema: extended_input_schema,
88
- extended_output_schema: extended_output_schema, debug: debug)
96
+ extended_output_schema: extended_output_schema, debug: debug,
97
+ summary: summary, summary_lines: summary_lines, batch: batch)
89
98
  end
90
99
  end
91
100
  end
@@ -184,7 +193,8 @@ module Wisco
184
193
  def execute_one(section, key, input_file, fixtures_dir, connector_full_path, connection,
185
194
  pagination: true, verbose: false, debug: false,
186
195
  extended: true, closure: nil, config_fields: nil, continue: nil,
187
- extended_input_schema: nil, extended_output_schema: nil)
196
+ extended_input_schema: nil, extended_output_schema: nil,
197
+ summary: true, summary_lines: 20, batch: false)
188
198
  stem = input_file ? File.basename(input_file, '.*') : 'execute'
189
199
  output_file = File.join(fixtures_dir, "output_#{stem}.json")
190
200
  error_file = File.join(fixtures_dir, "error_#{stem}.txt")
@@ -265,12 +275,14 @@ module Wisco
265
275
  end
266
276
 
267
277
  FileUtils.rm_f(error_file)
268
-
269
278
  return unless File.exist?(output_file)
270
279
 
271
- pretty = JSON.pretty_generate(JSON.parse(File.read(output_file)))
280
+ parsed = JSON.parse(File.read(output_file))
281
+ pretty = JSON.pretty_generate(parsed)
272
282
  File.write(output_file, pretty + "\n")
273
283
  puts " Written: #{output_file}"
284
+ display_output_summary(parsed, pretty, section: section, summary: summary,
285
+ summary_lines: summary_lines, batch: batch)
274
286
  end
275
287
 
276
288
  # Handles `execute_*.rb` scripts: evaluates the script to produce dynamic
@@ -282,7 +294,8 @@ module Wisco
282
294
  connector_full_path, connection, config,
283
295
  pagination: true, verbose: false, debug: false,
284
296
  extended: true, closure: nil, config_fields: nil, continue: nil,
285
- extended_input_schema: nil, extended_output_schema: nil)
297
+ extended_input_schema: nil, extended_output_schema: nil,
298
+ summary: true, summary_lines: 20, batch: false)
286
299
  subdir = File.join(fixtures_dir, File.basename(script_path, '.rb'))
287
300
  FileUtils.mkdir_p(subdir)
288
301
  input_file = File.join(subdir, 'input.json')
@@ -377,14 +390,88 @@ module Wisco
377
390
  end
378
391
 
379
392
  FileUtils.rm_f(error_file)
380
-
381
393
  return unless File.exist?(output_file)
382
394
 
383
- pretty = JSON.pretty_generate(JSON.parse(File.read(output_file)))
395
+ parsed = JSON.parse(File.read(output_file))
396
+ pretty = JSON.pretty_generate(parsed)
384
397
  File.write(output_file, pretty + "\n")
385
398
  puts " Written: #{output_file}"
399
+ display_output_summary(parsed, pretty, section: section, summary: summary,
400
+ summary_lines: summary_lines, batch: batch)
401
+ end
402
+
403
+ # ── Output summary ─────────────────────────────────────────────────────
404
+
405
+ def display_output_summary(parsed, pretty, section:, summary:, summary_lines:, batch:)
406
+ return unless summary
407
+
408
+ if section == 'pick_lists'
409
+ if batch
410
+ count = parsed.is_a?(Array) ? parsed.length : '?'
411
+ puts " Items: #{count}"
412
+ else
413
+ display_pick_list_table(parsed)
414
+ end
415
+ return
416
+ end
417
+
418
+ puts pretty if !batch && pretty.lines.length <= (summary_lines || 20)
419
+ puts " #{format_summary(parsed)}"
420
+ end
421
+
422
+ def display_pick_list_table(data)
423
+ unless data.is_a?(Array) && !data.empty?
424
+ puts ' (empty)'
425
+ return
426
+ end
427
+
428
+ rows = data.select { |item| item.is_a?(Array) && item.length >= 2 }
429
+
430
+ if rows.empty?
431
+ puts " Items: #{data.length} (unexpected format)"
432
+ return
433
+ end
434
+
435
+ max_col = 60
436
+ labels = rows.map { |item| truncate_str(item[0].to_s, max_col) }
437
+ values = rows.map { |item| truncate_str(item[1].to_s, max_col) }
438
+
439
+ col1_w = [labels.map(&:length).max, 'Label'.length].max
440
+ col2_w = [values.map(&:length).max, 'Value'.length].max
441
+ num_w = rows.length.to_s.length
442
+
443
+ puts " Items: #{rows.length}"
444
+ puts " | #{'#'.ljust(num_w)} | #{'Label'.ljust(col1_w)} | #{'Value'.ljust(col2_w)} |"
445
+ puts " |#{'-' * (num_w + 2)}|#{'-' * (col1_w + 2)}|#{'-' * (col2_w + 2)}|"
446
+ rows.each_with_index do |_, i|
447
+ puts " | #{(i + 1).to_s.ljust(num_w)} | #{labels[i].ljust(col1_w)} | #{values[i].ljust(col2_w)} |"
448
+ end
449
+ end
450
+
451
+ def format_summary(parsed)
452
+ case parsed
453
+ when Array
454
+ return 'Array: 0 items' if parsed.empty?
455
+ first_str = parsed.first.inspect
456
+ first_str = "#{first_str[0, 97]}…" if first_str.length > 100
457
+ "Array: #{parsed.length} #{parsed.length == 1 ? 'item' : 'items'} — first: #{first_str}"
458
+ when Hash
459
+ return 'Hash: 0 keys' if parsed.empty?
460
+ keys = parsed.keys.first(20)
461
+ suffix = parsed.keys.length > 20 ? " (+#{parsed.keys.length - 20} more)" : ''
462
+ "Hash: #{parsed.keys.length} keys — #{keys.join(', ')}#{suffix}"
463
+ when NilClass
464
+ '(nil)'
465
+ else
466
+ "Value: #{parsed.inspect}"
467
+ end
468
+ end
469
+
470
+ def truncate_str(str, max)
471
+ str.length > max ? "#{str[0, max - 1]}…" : str
386
472
  end
387
473
 
474
+ # ── SDK array-args normalisation ───────────────────────────────────────
388
475
  # The Workato SDK's InvokePath#invoke_method applies Array.wrap(args.last).flatten(1)
389
476
  # when the last parameter is *args, which incorrectly unwraps array-valued positional
390
477
  # arguments one level too many. These helpers compensate by pre-wrapping Array elements
@@ -12,9 +12,14 @@ module Wisco
12
12
 
13
13
  module_function
14
14
 
15
- def run(subcommand, target, sort: nil)
15
+ def run(subcommand, target, sort: nil, format: nil)
16
16
  validate_sort!(sort)
17
17
 
18
+ if format
19
+ run_formatted(target, format: format)
20
+ return
21
+ end
22
+
18
23
  case subcommand
19
24
  when nil then run_tree(target)
20
25
  when 'actions' then run_actions(target, sort: sort)
@@ -93,6 +98,69 @@ module Wisco
93
98
  run_triggers(target_dir, sort: sort)
94
99
  end
95
100
 
101
+ # ---------------------------------------------------------------------------
102
+ # Machine-readable output
103
+ # ---------------------------------------------------------------------------
104
+
105
+ def run_formatted(target_dir, format:)
106
+ require 'yaml' if format.downcase == 'yaml'
107
+ connector = Wisco::Connector.load_connector_from_config(target_dir)
108
+ data = build_connector_hash(connector)
109
+ if format.downcase == 'yaml'
110
+ puts data.to_yaml
111
+ else
112
+ puts JSON.pretty_generate(data)
113
+ end
114
+ end
115
+
116
+ def build_connector_hash(connector)
117
+ {
118
+ 'title' => connector[:title].to_s,
119
+ 'connection' => build_connection(connector[:connection]),
120
+ 'actions' => build_section(connector[:actions]),
121
+ 'triggers' => build_section(connector[:triggers]),
122
+ 'methods' => (connector[:methods] || {}).keys.map(&:to_s).sort,
123
+ 'pick_lists' => (connector[:pick_lists] || {}).keys.map(&:to_s).sort
124
+ }
125
+ end
126
+
127
+ def build_connection(conn)
128
+ return { 'fields' => [] } unless conn.is_a?(Hash)
129
+
130
+ fields = conn[:fields] || []
131
+ { 'fields' => fields.map { |f| safe_serialize(f) }.compact }
132
+ end
133
+
134
+ def build_section(section)
135
+ return {} unless section.is_a?(Hash)
136
+
137
+ section.keys.sort_by(&:to_s).each_with_object({}) do |key, h|
138
+ item = section[key]
139
+ h[key.to_s] = {
140
+ 'title' => title_for(key, item),
141
+ 'subtitle' => subtitle_for(item).to_s
142
+ }
143
+ end
144
+ end
145
+
146
+ # Recursively converts a connector value to a JSON-safe structure.
147
+ # Proc/lambda values are dropped (returned as nil so callers can compact).
148
+ def safe_serialize(value)
149
+ case value
150
+ when Hash
151
+ value.each_with_object({}) do |(k, v), h|
152
+ next if v.is_a?(Proc)
153
+
154
+ serialized = safe_serialize(v)
155
+ h[k.to_s] = serialized
156
+ end
157
+ when Array then value.map { |v| safe_serialize(v) }
158
+ when Proc then nil
159
+ when Symbol then value.to_s
160
+ else value
161
+ end
162
+ end
163
+
96
164
  # ---------------------------------------------------------------------------
97
165
  # List utilities
98
166
  # ---------------------------------------------------------------------------
data/lib/wisco/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Wisco
2
- VERSION = '0.3.8'
2
+ VERSION = '0.4.0'
3
3
  end
data/lib/wisco.rb CHANGED
@@ -68,13 +68,14 @@ module Wisco
68
68
  all Show tree + actions + triggers
69
69
  PATH defaults to the current directory.
70
70
  DESC
71
- option :sort, type: :string, desc: 'Sort actions/triggers by key or title', enum: %w[key title]
71
+ option :sort, type: :string, desc: 'Sort actions/triggers by key or title', enum: %w[key title]
72
+ option :format, type: :string, desc: 'Machine-readable output format (use with "all")', enum: %w[json yaml]
72
73
  def list(subcommand = nil, path = nil)
73
74
  if subcommand&.match?(%r{^[./~\\]|^[A-Za-z]:[/\\]})
74
75
  path = subcommand
75
76
  subcommand = nil
76
77
  end
77
- Wisco::Commands::List.run(subcommand, path || Dir.pwd, sort: options[:sort])
78
+ Wisco::Commands::List.run(subcommand, path || Dir.pwd, sort: options[:sort], format: options[:format])
78
79
  end
79
80
 
80
81
  desc 'exec PATH [TARGET_DIR]', 'Execute connector methods against fixture data'
@@ -98,7 +99,9 @@ module Wisco
98
99
  option :continue, type: :string, desc: 'Continue JSON file (multistep actions)'
99
100
  option :'extended-input-schema', type: :string, desc: 'Extended input schema JSON (overrides --extended auto-detection)'
100
101
  option :'extended-output-schema', type: :string, desc: 'Extended output schema JSON (overrides --extended auto-detection)'
101
- option :debug, type: :boolean, default: false, desc: 'Print ExecCommand call details'
102
+ option :debug, type: :boolean, default: false, desc: 'Print ExecCommand call details'
103
+ option :summary, type: :boolean, default: true, desc: 'Show output summary after execution (use --no-summary to disable)'
104
+ option :'summary-lines', type: :numeric, default: 20, desc: 'Max output lines to display in full before switching to summary-only'
102
105
  def exec(path_arg, target_dir = nil)
103
106
  Wisco::Commands::Exec.run(
104
107
  path_arg,
@@ -112,7 +115,9 @@ module Wisco
112
115
  continue: options[:continue],
113
116
  extended_input_schema: options[:extended_input_schema],
114
117
  extended_output_schema: options[:extended_output_schema],
115
- debug: options[:debug]
118
+ debug: options[:debug],
119
+ summary: options[:summary],
120
+ summary_lines: options[:'summary-lines']
116
121
  )
117
122
  end
118
123
 
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.8
4
+ version: 0.4.0
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-13 00:00:00.000000000 Z
11
+ date: 2026-06-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport