openapi-sourcetools 0.7.1 → 0.8.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.
@@ -1,12 +1,13 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- # Copyright © 2021-2024 Ismo Kärkkäinen
4
+ # Copyright © 2021-2025 Ismo Kärkkäinen
5
5
  # Licensed under Universal Permissive License. See LICENSE.txt.
6
6
 
7
- require_relative '../lib/common'
7
+ require_relative '../lib/openapi/sourcetools/apiobjects'
8
+ require_relative '../lib/openapi/sourcetools/common'
8
9
  require 'optparse'
9
- require 'yaml'
10
+ include OpenAPISourceTools
10
11
 
11
12
 
12
13
  def main
@@ -32,26 +33,22 @@ def main
32
33
  opts.on('-h', '--help', 'Print this help and exit.') do
33
34
  $stdout.puts %(#{opts}
34
35
 
35
- Processes API specification document path objects into form that is expected by
36
- later stage tools. Checks for paths that may be ambiguous.
36
+ Adds split path parts into API document path items under x-openapi-sourcetools
37
+ key. Checks for paths that may be ambiguous.
37
38
  )
38
39
  exit 0
39
40
  end
40
41
  end
41
42
  parser.order!
42
43
 
43
- doc = load_source(input_name)
44
+ doc = Common.load_source(input_name)
44
45
  return 2 if doc.nil?
45
46
 
46
47
  processed = {}
47
- doc.fetch('paths', {}).each_pair do |path, value|
48
- parts = split_path(path, true)
49
- processed[path] = {
50
- 'parts' => parts,
51
- 'orig' => value,
52
- 'lookalike' => [],
53
- path: ServerPath.new(parts)
54
- }
48
+ doc.fetch('paths', {}).each do |path, item|
49
+ parts = Common.split_path(path, true)
50
+ item['x-openapi-sourcetools-parts'] = parts # Added to original path item.
51
+ processed[path] = ApiObjects::ServerPath.new(parts)
55
52
  end
56
53
 
57
54
  # Find lookalike sets.
@@ -63,22 +60,14 @@ later stage tools. Checks for paths that may be ambiguous.
63
60
  k.times do |n|
64
61
  pn = paths[n]
65
62
  b = processed[pn]
66
- next unless a[:path].compare(b[:path]).zero?
67
- a['lookalike'].push pn
68
- b['lookalike'].push pk
63
+ next unless a.compare(b).zero?
69
64
  $stderr.puts("Similar: #{pn} #{pk}")
70
65
  lookalikes = true
71
66
  end
72
67
  end
73
- return aargh('Similar paths found.', 4) if lookalikes && error
68
+ return Common.aargh('Similar paths found.', 4) if lookalikes && error
74
69
 
75
- # Remove temporary fields.
76
- processed.each_value do |v|
77
- v.keys.each { |k| v.delete(k) if k.is_a? Symbol }
78
- end
79
- doc['paths'] = processed
80
-
81
- dump_result(output_name, YAML.dump(doc), 3)
70
+ Common.dump_result(output_name, doc, 3)
82
71
  end
83
72
 
84
- exit(main) if defined?($unit_test).nil?
73
+ exit(main) unless defined?($unit_test)
@@ -0,0 +1,191 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright © 2024-2025 Ismo Kärkkäinen
4
+ # Licensed under Universal Permissive License. See LICENSE.txt.
5
+
6
+ module OpenAPISourceTools
7
+ # Various classes for handling objects in the API specification.
8
+ # Used in various programs.
9
+ module ApiObjects
10
+
11
+ def self.same(a, b, ignored_keys = Set.new(%w[summary description]))
12
+ return a == b unless a.is_a?(Hash) && b.is_a?(Hash)
13
+ keys = Set.new(a.keys + b.keys) - ignored_keys
14
+ keys.to_a.each do |k|
15
+ return false unless a.key?(k) && b.key?(k)
16
+ return false unless same(a[k], b[k], ignored_keys)
17
+ end
18
+ true
19
+ end
20
+
21
+ def self.ref_string(name, schema_path)
22
+ "#{schema_path}/#{name}"
23
+ end
24
+
25
+ def self.reference(obj, schemas, schema_path, ignored_keys = Set.new(%w[summary description]), prefix = 'Schema')
26
+ # Check if identical schema has been added and if so, return the $ref string.
27
+ schemas.keys.sort.each do |k|
28
+ return ref_string(k, schema_path) if same(obj, schemas[k], ignored_keys)
29
+ end
30
+ # One of the numbers will not match existing keys. More number than keys.
31
+ (schemas.size + 1).times do |n|
32
+ # 'x' is to simplify find and replace (Schema1x vs Schema1 and Schema10)
33
+ k = "#{prefix}#{n}x"
34
+ next if schemas.key?(k)
35
+ schemas[k] = obj.merge
36
+ return ref_string(k, schema_path)
37
+ end
38
+ end
39
+
40
+ # A component in the API specification for reference and anchor handling.
41
+ class Components
42
+ attr_reader :path, :prefix, :anchor2ref, :schema_names
43
+ attr_accessor :items, :ignored_keys
44
+
45
+ def initialize(path, prefix, ignored_keys = %w[summary description examples example $anchor])
46
+ path = "#/#{path.join('/')}/" if path.is_a?(Array)
47
+ path = "#{path}/" unless path.end_with?('/')
48
+ @path = path
49
+ @prefix = prefix
50
+ @anchor2ref = {}
51
+ @schema_names = Set.new
52
+ @items = {}
53
+ @ignored_keys = Set.new(ignored_keys)
54
+ end
55
+
56
+ def add_options(opts)
57
+ opts.on('--use FIELD', 'Use FIELD in comparisons.') do |f|
58
+ @ignored_keys.delete(f)
59
+ end
60
+ opts.on('--ignore FIELD', 'Ignore FIELD in comparisons.') do |f|
61
+ @ignored_keys.add(f)
62
+ end
63
+ end
64
+
65
+ def help
66
+ %(All fields are used in object equality comparisons except:\n#{@ignored_keys.to_a.sort!.join("\n")})
67
+ end
68
+
69
+ def add_schema_name(name)
70
+ @schema_names.add(name)
71
+ end
72
+
73
+ def ref_string(name)
74
+ return nil if name.nil?
75
+ "#{@path}#{name}"
76
+ end
77
+
78
+ def reference(obj)
79
+ # Check if identical schema has been added. If so, return the $ref string.
80
+ @items.each do |k, v|
81
+ return ref_string(k) if ApiObjects.same(obj, v, @ignored_keys)
82
+ end
83
+ # One of the numbers will not match existing keys. More number than keys.
84
+ (@items.size + 1).times do |n|
85
+ # 'x' is to simplify find and replace (Schema1x vs Schema1 and Schema10)
86
+ cand = "#{@prefix}#{n}x"
87
+ next if @items.key?(cand)
88
+ @items[cand] = obj.merge
89
+ @schema_names.add(cand)
90
+ return ref_string(cand)
91
+ end
92
+ end
93
+
94
+ def store_anchor(obj, ref = nil)
95
+ anchor_name = obj['$anchor']
96
+ return if anchor_name.nil?
97
+ ref = obj['$ref'] if ref.nil?
98
+ raise StandardError, 'ref is nil and no $ref or it is nil' if ref.nil?
99
+ @anchor2ref[anchor_name] = ref
100
+ end
101
+
102
+ def alter_anchors
103
+ replacements = {}
104
+ @anchor2ref.each_key do |a|
105
+ next if @schema_names.member?(a)
106
+ replacements[a] = ref_string(a)
107
+ @schema_names.add(a)
108
+ end
109
+ replacements.each do |a, r|
110
+ @anchor2ref[a] = r
111
+ end
112
+ end
113
+
114
+ def anchor_ref_replacement(ref)
115
+ @anchor2ref[ref[1...ref.size]] || ref
116
+ end
117
+ end
118
+
119
+ # Represents path with fixed parts and variables.
120
+ class ServerPath
121
+ # Probably moves to a separate file once processpaths and frequencies receive
122
+ # some attention.
123
+ include Comparable
124
+
125
+ attr_accessor :parts
126
+
127
+ def initialize(parts)
128
+ @parts = parts
129
+ end
130
+
131
+ # Parameters are after fixed strings.
132
+ def <=>(other)
133
+ pp = other.is_a?(Array) ? other : other.parts
134
+ @parts.size.times do |k|
135
+ return 1 if pp.size <= k # Longer comes after shorter.
136
+ pk = @parts[k]
137
+ ppk = pp[k]
138
+ if pk.key?('fixed')
139
+ if ppk.key?('fixed')
140
+ c = pk['fixed'] <=> ppk['fixed']
141
+ else
142
+ return -1
143
+ end
144
+ else
145
+ if ppk.key?('fixed')
146
+ return 1
147
+ else
148
+ c = pk.fetch('parameter', '') <=> ppk.fetch('parameter', '')
149
+ end
150
+ end
151
+ return c unless c.zero?
152
+ end
153
+ (@parts.size < pp.size) ? -1 : 0
154
+ end
155
+
156
+ # Not fit for sorting. Variable equals anything.
157
+ def compare(other, range = nil)
158
+ pp = other.is_a?(Array) ? other : other.parts
159
+ if range.nil?
160
+ range = 0...@parts.size
161
+ elsif range.is_a? Number
162
+ range = range...(range + 1)
163
+ end
164
+ range.each do |k|
165
+ return 1 if pp.size <= k # Longer comes after shorter.
166
+ ppk = pp[k]
167
+ next unless ppk.key?('fixed')
168
+ pk = parts[k]
169
+ next unless pk.key?('fixed')
170
+ c = pk['fixed'] <=> ppk['fixed']
171
+ return c unless c.zero?
172
+ end
173
+ (@parts.size < pp.size) ? -1 : 0
174
+ end
175
+ end
176
+
177
+ def self.operation_objects(path_item)
178
+ keys = %w[operationId requestBody responses callbacks]
179
+ out = {}
180
+ path_item.each do |method, op|
181
+ next unless op.is_a?(Hash)
182
+ keys.each do |key|
183
+ next unless op.key?(key)
184
+ out[method] = op
185
+ break
186
+ end
187
+ end
188
+ out
189
+ end
190
+ end
191
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright © 2021-2025 Ismo Kärkkäinen
4
+ # Licensed under Universal Permissive License. See LICENSE.txt.
5
+
6
+ require 'pathname'
7
+ require 'yaml'
8
+
9
+ module OpenAPISourceTools
10
+ # Common methods used in programs and elsewhere gathered into one place.
11
+ module Common
12
+ def self.aargh(message, return_value = nil)
13
+ message = message.map(&:to_s).join("\n") if message.is_a? Array
14
+ $stderr.puts message
15
+ return_value
16
+ end
17
+
18
+ def self.yesno(boolean)
19
+ boolean ? 'yes' : 'no'
20
+ end
21
+
22
+ def self.bury(doc, path, value)
23
+ (path.size - 1).times do |k|
24
+ p = path[k]
25
+ doc[p] = {} unless doc.key?(p)
26
+ doc = doc[p]
27
+ end
28
+ doc[path.last] = value
29
+ end
30
+
31
+ module Out
32
+ attr_reader :count
33
+ module_function :count
34
+ attr_accessor :quiet
35
+ module_function :quiet
36
+ module_function :quiet=
37
+
38
+ def self.put(message)
39
+ Common.aargh(message) unless @quiet
40
+ @count = @count.nil? ? 1 : @count + 1
41
+ end
42
+ end
43
+
44
+ def self.split_path(p, spec = false)
45
+ parts = []
46
+ p = p.strip
47
+ unless spec
48
+ q = p.index('?')
49
+ p.slice!(0...q) unless q.nil?
50
+ end
51
+ p.split('/').each do |s|
52
+ next if s.empty?
53
+ s = { (spec && s.include?('{') ? 'parameter' : 'fixed') => s }
54
+ parts.push(s)
55
+ end
56
+ parts
57
+ end
58
+
59
+ def self.load_source(input)
60
+ YAML.safe_load(input.nil? ? $stdin : File.read(input))
61
+ rescue Errno::ENOENT
62
+ aargh "Could not load #{input || 'stdin'}"
63
+ rescue StandardError => e
64
+ aargh "#{e}\nFailed to read #{input || 'stdin'}"
65
+ end
66
+
67
+ def self.dump_result(output, doc, error_return)
68
+ doc = YAML.dump(doc, line_width: 1_000_000) unless doc.is_a?(String)
69
+ if output.nil?
70
+ $stdout.puts doc
71
+ else
72
+ fp = Pathname.new output
73
+ fp.open('w') do |f|
74
+ f.puts doc
75
+ end
76
+ end
77
+ 0
78
+ rescue StandardError => e
79
+ aargh([ e, "Failed to write output: #{output || 'stdout'}" ], error_return)
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,158 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright © 2024-2025 Ismo Kärkkäinen
4
+ # Licensed under Universal Permissive License. See LICENSE.txt.
5
+
6
+ require_relative 'task'
7
+ require_relative 'gen'
8
+ require 'find'
9
+ require 'yaml'
10
+
11
+ module OpenAPISourceTools
12
+ # Configuration file find and load convenience functions.
13
+ # See the first 3 methods. The rest are intended to be internal helpers.
14
+ module ConfigLoader
15
+
16
+ # A function to find all files with a given prefix.
17
+ # Prefix is taken from Gen.config if nil.
18
+ # Returns an array of ConfigFileInfo objects.
19
+ def self.find_files(name_prefix:, extensions: [ '.*' ])
20
+ name_prefix = Gen.config if name_prefix.nil?
21
+ raise ArgumentError, 'name_prefix or config must be set' if name_prefix.nil?
22
+ root, name_prefix = prepare_prefix(name_prefix, Gen.wd)
23
+ file_paths = find_filenames(root, name_prefix)
24
+ splitter = path_splitter(Gen.separator)
25
+ out = file_paths.map { |fp| convert_path_end(fp, splitter, root.size + 1, extensions) }
26
+ out.sort!
27
+ end
28
+
29
+ # A function to read all YAML files in an array of ConfigFileInfo objects.
30
+ # Returns the same as contents_array.
31
+ def self.read_contents(config_file_infos)
32
+ config_file_infos.each do |cfi|
33
+ c = YAML.safe_load_file(cfi.path)
34
+ # Check allows e.g. copyright and license files be named with config prefix
35
+ # for clarity, but ignored during config loading.
36
+ next if cfi.keys.empty? && !c.is_a?(Hash)
37
+ cfi.bury_content(c)
38
+ rescue Psych::SyntaxError
39
+ next # Was not YAML. Other files can be named using config prefix.
40
+ end
41
+ contents_array(config_file_infos)
42
+ end
43
+
44
+ # Maps an array of ConfigFileInfo objects to an array of their contents.
45
+ def self.contents_array(config_file_infos)
46
+ config_file_infos.map(&:content).reject(&:nil?)
47
+ end
48
+
49
+ class ConfigFileInfo
50
+ include Comparable
51
+
52
+ attr_reader :root, :keys, :path, :content
53
+
54
+ def initialize(pieces, path)
55
+ @keys = []
56
+ @root = nil
57
+ pieces.each do |p|
58
+ if p.is_a?(String)
59
+ if @root.nil?
60
+ @root = p
61
+ else
62
+ @keys.push(p)
63
+ end
64
+ else
65
+ break if p == :extension
66
+ end
67
+ end
68
+ @path = path
69
+ @content = nil
70
+ end
71
+
72
+ def bury_content(content)
73
+ # Turns chain of keys into nested Hashes.
74
+ @keys.reverse.each do |key|
75
+ c = { key => content }
76
+ content = c
77
+ end
78
+ @content = content
79
+ end
80
+
81
+ def <=>(other)
82
+ d = @root <=> other.root
83
+ return d unless d.zero?
84
+ d = @keys.size <=> other.keys.size
85
+ return d unless d.zero?
86
+ d = @keys <=> other.keys
87
+ return d unless d.zero?
88
+ @path <=> other.path
89
+ end
90
+ end
91
+
92
+ def self.prepare_prefix(name_prefix, root)
93
+ name_prefix_dir = File.dirname(name_prefix)
94
+ root = File.realpath(name_prefix_dir, root) unless name_prefix_dir == '.'
95
+ name_prefix = File.basename(name_prefix)
96
+ if name_prefix == '.' # Just being nice. Daft argument.
97
+ name_prefix = File.basename(root)
98
+ root = File.dirname(root)
99
+ end
100
+ [root, name_prefix]
101
+ end
102
+
103
+ def self.find_filenames(root, name_prefix)
104
+ full_prefix = File.join(root, name_prefix)
105
+ file_paths = []
106
+ Find.find(root) do |path|
107
+ next if path.size < full_prefix.size
108
+ is_dir = File.directory?(path)
109
+ if path.start_with?(full_prefix)
110
+ file_paths.push(path) unless is_dir
111
+ elsif is_dir
112
+ Find.prune
113
+ end
114
+ end
115
+ file_paths
116
+ end
117
+
118
+ def self.path_splitter(separator)
119
+ parts = [ Regexp.quote('/') ]
120
+ parts.push(Regexp.quote(separator)) if separator.is_a?(String) && !separator.empty?
121
+ Regexp.new("(#{parts.join('|')})")
122
+ end
123
+
124
+ def self.remove_extension(file_path, extensions)
125
+ extensions.each do |e|
126
+ if e == '.*'
127
+ idx = file_path.rindex('.')
128
+ next if idx.nil? # No . anywhere.
129
+ ext = file_path[idx..]
130
+ next unless ext.index('/').nil? # Last . is before file name.
131
+ return [ file_path[0...idx], ext ]
132
+ elsif file_path.end_with?(e)
133
+ return [ file_path[0..-(1 + e.size)], e ]
134
+ end
135
+ end
136
+ [ file_path, nil ]
137
+ end
138
+
139
+ def self.convert_path_end(path, splitter, prefix_size, extensions)
140
+ relevant, ext = remove_extension(path[prefix_size..], extensions)
141
+ pieces = relevant.split(splitter).map do |piece|
142
+ case piece
143
+ when '' then nil
144
+ when '/' then :dir
145
+ when Gen.separator then :separator
146
+ else
147
+ piece
148
+ end
149
+ end
150
+ unless ext.nil?
151
+ pieces.push(:extension)
152
+ pieces.push(ext)
153
+ end
154
+ pieces.compact!
155
+ ConfigFileInfo.new(pieces, path)
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright © 2024-2025 Ismo Kärkkäinen
4
+ # Licensed under Universal Permissive License. See LICENSE.txt.
5
+
6
+ module OpenAPISourceTools
7
+ # To hold documents loaded via command-line.
8
+ # Provides attribute accessor methods for each document.
9
+ # Exposed via Gen.d to tasks.
10
+ class Docs
11
+ attr_reader :docs
12
+
13
+ def initialize
14
+ @docs = {}
15
+ end
16
+
17
+ def method_missing(method_name, *args)
18
+ name = method_name.to_s
19
+ if name.end_with?('=')
20
+ name = name[0...(name.size - 1)]
21
+ super unless @docs.key?(name)
22
+ @docs[name] = args.first
23
+ return args.first
24
+ end
25
+ super unless @docs.key?(name)
26
+ @docs[name]
27
+ end
28
+
29
+ def respond_to_missing?(method_name, *args)
30
+ name = method_name.to_s
31
+ name = name[0...(name.size - 1)] if name.end_with?('=')
32
+ @docs.key?(name) || super
33
+ end
34
+
35
+ def add(name, content)
36
+ return false if docs.key?(name)
37
+ @docs[name] = content
38
+ true
39
+ end
40
+ end
41
+ end
@@ -1,37 +1,44 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright © 2024 Ismo Kärkkäinen
3
+ # Copyright © 2024-2025 Ismo Kärkkäinen
4
4
  # Licensed under Universal Permissive License. See LICENSE.txt.
5
5
 
6
6
  require_relative 'task'
7
7
  require_relative 'helper'
8
8
  require_relative 'docs'
9
9
  require_relative 'output'
10
+ require_relative 'config'
11
+ require 'deep_merge'
10
12
 
11
13
 
14
+ # The generation module that contains things visible to tasks.
12
15
  module Gen
13
16
  def self.add_doc(symbol, docstr)
14
17
  return if docstr.nil?
15
18
  @docsrc = [] unless instance_variable_defined?('@docsrc')
16
- @docsrc.push("- #{symbol.to_s} : #{docstr}")
19
+ @docsrc.push("- #{symbol} : #{docstr}")
17
20
  end
21
+ private_class_method :add_doc
18
22
 
19
23
  def self.read_attr(symbol, default)
20
24
  return if symbol.nil?
21
25
  attr_reader(symbol)
22
26
  module_function(symbol)
23
- instance_variable_set("@#{symbol.to_s}", default)
27
+ instance_variable_set("@#{symbol}", default)
24
28
  end
29
+ private_class_method :read_attr
25
30
 
26
31
  def self.mod_attr2_reader(symbol, symbol2, docstr = nil, default = nil)
27
32
  read_attr(symbol, default)
28
33
  read_attr(symbol2, default)
29
34
  add_doc(symbol, docstr)
30
35
  end
36
+ private_class_method :mod_attr2_reader
31
37
 
32
38
  def self.mod_attr_reader(symbol, docstr = nil, default = nil)
33
39
  mod_attr2_reader(symbol, nil, docstr, default)
34
40
  end
41
+ private_class_method :mod_attr_reader
35
42
 
36
43
  def self.rw_attr(symbol, default)
37
44
  attr_accessor(symbol)
@@ -40,39 +47,56 @@ module Gen
40
47
  module_function((s + '=').to_sym)
41
48
  instance_variable_set("@#{s}", default)
42
49
  end
50
+ private_class_method :rw_attr
43
51
 
44
52
  def self.mod_attr2_accessor(symbol, symbol2, docstr = nil, default = nil)
45
53
  rw_attr(symbol, default)
46
54
  rw_attr(symbol2, default) unless symbol2.nil?
47
55
  add_doc(symbol, docstr)
48
56
  end
57
+ private_class_method :mod_attr2_accessor
49
58
 
50
59
  def self.mod_attr_accessor(symbol, docstr = nil, default = nil)
51
60
  mod_attr2_accessor(symbol, nil, docstr, default)
52
61
  end
62
+ private_class_method :mod_attr_accessor
53
63
 
54
64
  mod_attr_reader :doc, 'OpenAPI document.'
55
65
  mod_attr_reader :outdir, 'Output directory name.'
56
- mod_attr_reader :d, 'Other documents object.', Docs.new
66
+ mod_attr_reader :d, 'Other documents object.', OpenAPISourceTools::Docs.new
67
+ mod_attr_reader :wd, 'Original working directory', Dir.pwd
68
+ mod_attr_reader :configuration, 'Generator internal configuration'
69
+ mod_attr_accessor :config, 'Configuration file name for next gem or Ruby file.'
70
+ mod_attr_accessor :separator, 'Key separator in config file names.', nil
57
71
  mod_attr_accessor :in_name, 'OpenAPI document name, nil if stdin.'
58
72
  mod_attr_accessor :in_basename, 'OpenAPI document basename, nil if stdin.'
59
- mod_attr_accessor :tasks, 'Tasks array.', []
60
- mod_attr_accessor :g, 'Hash for storing values visible to all tasks.', {}
61
- mod_attr_accessor :a, 'Intended for instance with defined attributes.'
73
+ mod_attr_reader :g, 'Hash for storing values visible to all tasks.', {}
74
+ mod_attr_accessor :x, 'Hash for storing values visible to tasks from processor.', {}
62
75
  mod_attr_accessor :h, 'Instance of class with helper methods.'
76
+ mod_attr_accessor :tasks, 'Tasks array.', []
63
77
  mod_attr2_accessor :task, :t, 'Current task instance.'
64
78
  mod_attr_accessor :task_index, 'Current task index.'
65
- mod_attr_accessor :loaders, 'Array of generator loader methods.', []
66
- mod_attr2_accessor :output, :o, 'Output-related methods.', Output.new
79
+ mod_attr_accessor :loaders, 'Array of processor loader methods.', []
80
+ mod_attr_accessor :output, 'Output-formatting helper.', OpenAPISourceTools::Output.new
81
+
82
+ def self.load_config(config_prefix)
83
+ cfg = {}
84
+ cfgs = OpenAPISourceTools::ConfigLoader.find_files(name_prefix: config_prefix)
85
+ cfgs = OpenAPISourceTools::ConfigLoader.read_contents(cfgs)
86
+ cfgs.each { |c| cfg.deep_merge!(c) }
87
+ cfg
88
+ end
89
+ private_class_method :load_config
67
90
 
68
- def self.setup(document_content, input_name, output_directory)
91
+ def self.setup(document_content, input_name, output_directory, config_prefix)
69
92
  @doc = document_content
70
93
  @outdir = output_directory
71
94
  unless input_name.nil?
72
95
  @in_name = File.basename(input_name)
73
96
  @in_basename = File.basename(input_name, '.*')
74
97
  end
75
- add_task(task: HelperTask.new)
98
+ @configuration = load_config(config_prefix)
99
+ add_task(task: OpenAPISourceTools::HelperTask.new)
76
100
  end
77
101
 
78
102
  def self.add_task(task:, name: nil, executable: false, x: nil)
@@ -85,11 +109,12 @@ module Gen
85
109
  end
86
110
 
87
111
  def self.add_write_content(name:, content:, executable: false)
88
- add_task(task: WriteTask.new(name, content, executable))
112
+ add_task(task: OpenAPISourceTools::WriteTask.new(name, content, executable))
89
113
  end
90
114
 
91
115
  def self.add(source:, template: nil, template_name: nil, name: nil, executable: false, x: nil)
92
- add_task(task: Task.new(source, template, template_name), name: name, executable: executable, x: x)
116
+ add_task(task: OpenAPISourceTools::Task.new(source, template, template_name),
117
+ name:, executable:, x:)
93
118
  end
94
119
 
95
120
  def self.document