openapi-sourcetools 0.7.1 → 0.8.1
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/bin/openapi-addheaders +8 -7
- data/bin/openapi-addparameters +50 -9
- data/bin/openapi-addresponses +8 -8
- data/bin/openapi-addschemas +10 -9
- data/bin/openapi-addsecurityschemes +108 -0
- data/bin/openapi-checkschemas +16 -15
- data/bin/openapi-frequencies +23 -25
- data/bin/openapi-generate +17 -14
- data/bin/openapi-merge +6 -6
- data/bin/openapi-modifypaths +16 -15
- data/bin/openapi-processpaths +15 -26
- data/lib/openapi/sourcetools/apiobjects.rb +191 -0
- data/lib/openapi/sourcetools/common.rb +82 -0
- data/lib/openapi/sourcetools/config.rb +158 -0
- data/lib/openapi/sourcetools/docs.rb +41 -0
- data/lib/openapi/sourcetools/gen.rb +121 -0
- data/lib/openapi/sourcetools/generate.rb +95 -0
- data/lib/openapi/sourcetools/helper.rb +93 -0
- data/lib/openapi/sourcetools/loaders.rb +163 -0
- data/lib/openapi/sourcetools/output.rb +83 -0
- data/lib/openapi/sourcetools/task.rb +137 -0
- data/lib/openapi/sourcetools/version.rb +13 -0
- data/lib/openapi/sourcetools.rb +16 -0
- metadata +43 -18
- data/lib/apiobjects.rb +0 -306
- data/lib/common.rb +0 -114
- data/lib/docs.rb +0 -33
- data/lib/gen.rb +0 -104
- data/lib/generate.rb +0 -90
- data/lib/helper.rb +0 -94
- data/lib/loaders.rb +0 -96
- data/lib/output.rb +0 -58
- data/lib/task.rb +0 -101
@@ -0,0 +1,16 @@
|
|
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 'sourcetools/task'
|
7
|
+
require_relative 'sourcetools/config'
|
8
|
+
require_relative 'sourcetools/version'
|
9
|
+
require_relative 'sourcetools/apiobjects'
|
10
|
+
# Other modules or classes are exposed via Gen attributes as class instances as needed.
|
11
|
+
# Docs is only needed for run-time storage of whatever loaders can handle.
|
12
|
+
# Loaders array is exposed and can be added to at run-time.
|
13
|
+
# Helper instance is accessible via Gen.h.
|
14
|
+
# Output is exposed via Gen.o and Gen.output. Note that if you assign to one,
|
15
|
+
# the other will not change.
|
16
|
+
# The rest are for internal implementation.
|
metadata
CHANGED
@@ -1,26 +1,47 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: openapi-sourcetools
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ismo Kärkkäinen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
12
|
-
dependencies:
|
13
|
-
|
11
|
+
date: 2025-01-31 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: deep_merge
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.2'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.2.2
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.2'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.2.2
|
33
|
+
description: |-
|
34
|
+
Tools for handling API specification in OpenAPI format.
|
35
|
+
Programs to replace of duplicate definitions with references. Other checks.
|
14
36
|
|
15
|
-
|
16
|
-
duplicate definitions with references. Other checks. Does not validate
|
17
|
-
the document against OpenAPI format specification.
|
37
|
+
Does not validate the document against OpenAPI format specification.
|
18
38
|
email: ismokarkkainen@icloud.com
|
19
39
|
executables:
|
20
40
|
- openapi-addheaders
|
21
41
|
- openapi-addparameters
|
22
42
|
- openapi-addresponses
|
23
43
|
- openapi-addschemas
|
44
|
+
- openapi-addsecurityschemes
|
24
45
|
- openapi-checkschemas
|
25
46
|
- openapi-frequencies
|
26
47
|
- openapi-generate
|
@@ -35,21 +56,25 @@ files:
|
|
35
56
|
- bin/openapi-addparameters
|
36
57
|
- bin/openapi-addresponses
|
37
58
|
- bin/openapi-addschemas
|
59
|
+
- bin/openapi-addsecurityschemes
|
38
60
|
- bin/openapi-checkschemas
|
39
61
|
- bin/openapi-frequencies
|
40
62
|
- bin/openapi-generate
|
41
63
|
- bin/openapi-merge
|
42
64
|
- bin/openapi-modifypaths
|
43
65
|
- bin/openapi-processpaths
|
44
|
-
- lib/
|
45
|
-
- lib/
|
46
|
-
- lib/
|
47
|
-
- lib/
|
48
|
-
- lib/
|
49
|
-
- lib/
|
50
|
-
- lib/
|
51
|
-
- lib/
|
52
|
-
- lib/
|
66
|
+
- lib/openapi/sourcetools.rb
|
67
|
+
- lib/openapi/sourcetools/apiobjects.rb
|
68
|
+
- lib/openapi/sourcetools/common.rb
|
69
|
+
- lib/openapi/sourcetools/config.rb
|
70
|
+
- lib/openapi/sourcetools/docs.rb
|
71
|
+
- lib/openapi/sourcetools/gen.rb
|
72
|
+
- lib/openapi/sourcetools/generate.rb
|
73
|
+
- lib/openapi/sourcetools/helper.rb
|
74
|
+
- lib/openapi/sourcetools/loaders.rb
|
75
|
+
- lib/openapi/sourcetools/output.rb
|
76
|
+
- lib/openapi/sourcetools/task.rb
|
77
|
+
- lib/openapi/sourcetools/version.rb
|
53
78
|
homepage: https://xn--ismo-krkkinen-gfbd.fi/openapi-sourcetools/index.html
|
54
79
|
licenses:
|
55
80
|
- UPL-1.0
|
@@ -63,14 +88,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
63
88
|
requirements:
|
64
89
|
- - ">="
|
65
90
|
- !ruby/object:Gem::Version
|
66
|
-
version: 3.
|
91
|
+
version: 3.2.5
|
67
92
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
93
|
requirements:
|
69
94
|
- - ">="
|
70
95
|
- !ruby/object:Gem::Version
|
71
96
|
version: '0'
|
72
97
|
requirements: []
|
73
|
-
rubygems_version: 3.
|
98
|
+
rubygems_version: 3.4.19
|
74
99
|
signing_key:
|
75
100
|
specification_version: 4
|
76
101
|
summary: Tools for creating source code from API specification.
|
data/lib/apiobjects.rb
DELETED
@@ -1,306 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative './common'
|
4
|
-
require 'set'
|
5
|
-
|
6
|
-
def same(a, b, ignored_keys = Set.new(%w[summary description]))
|
7
|
-
return a == b unless a.is_a?(Hash) && b.is_a?(Hash)
|
8
|
-
keys = Set.new(a.keys + b.keys) - ignored_keys
|
9
|
-
keys.to_a.each do |k|
|
10
|
-
return false unless a.key?(k) && b.key?(k)
|
11
|
-
return false unless same(a[k], b[k], ignored_keys)
|
12
|
-
end
|
13
|
-
true
|
14
|
-
end
|
15
|
-
|
16
|
-
def ref_string(name, schema_path)
|
17
|
-
"#{schema_path}/#{name}"
|
18
|
-
end
|
19
|
-
|
20
|
-
def reference(obj, schemas, schema_path, ignored_keys = Set.new(%w[summary description]), prefix = 'Schema')
|
21
|
-
# Check if identical schema has been added and if so, return the $ref string.
|
22
|
-
schemas.keys.sort.each do |k|
|
23
|
-
return ref_string(k, schema_path) if same(obj, schemas[k], ignored_keys)
|
24
|
-
end
|
25
|
-
# One of the numbers will not match existing keys. More number than keys.
|
26
|
-
(schemas.size + 1).times do |n|
|
27
|
-
# 'x' is to simplify find and replace (Schema1x vs Schema1 and Schema10)
|
28
|
-
k = "#{prefix}#{n}x"
|
29
|
-
next if schemas.key?(k)
|
30
|
-
schemas[k] = obj.merge
|
31
|
-
return ref_string(k, schema_path)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
class Components
|
36
|
-
attr_reader :path, :prefix, :anchor2ref, :schema_names
|
37
|
-
attr_accessor :items, :ignored_keys
|
38
|
-
|
39
|
-
def initialize(path, prefix, ignored_keys = %w[summary description examples example $anchor])
|
40
|
-
path = "#/#{path.join('/')}/" if path.is_a?(Array)
|
41
|
-
path = "#{path}/" unless path.end_with?('/')
|
42
|
-
@path = path
|
43
|
-
@prefix = prefix
|
44
|
-
@anchor2ref = {}
|
45
|
-
@schema_names = Set.new
|
46
|
-
@items = {}
|
47
|
-
@ignored_keys = Set.new(ignored_keys)
|
48
|
-
end
|
49
|
-
|
50
|
-
def add_options(opts)
|
51
|
-
opts.on('--use FIELD', 'Use FIELD in comparisons.') do |f|
|
52
|
-
@ignored_keys.delete(f)
|
53
|
-
end
|
54
|
-
opts.on('--ignore FIELD', 'Ignore FIELD in comparisons.') do |f|
|
55
|
-
@ignored_keys.add(f)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def help
|
60
|
-
%(All fields are used in object equality comparisons except:\n#{@ignored_keys.to_a.sort!.join("\n")})
|
61
|
-
end
|
62
|
-
|
63
|
-
def add_schema_name(name)
|
64
|
-
@schema_names.add(name)
|
65
|
-
end
|
66
|
-
|
67
|
-
def ref_string(name)
|
68
|
-
return nil if name.nil?
|
69
|
-
"#{@path}#{name}"
|
70
|
-
end
|
71
|
-
|
72
|
-
def reference(obj)
|
73
|
-
# Check if identical schema has been added. If so, return the $ref string.
|
74
|
-
@items.each do |k, v|
|
75
|
-
return ref_string(k) if same(obj, v, @ignored_keys)
|
76
|
-
end
|
77
|
-
# One of the numbers will not match existing keys. More number than keys.
|
78
|
-
(@items.size + 1).times do |n|
|
79
|
-
# 'x' is to simplify find and replace (Schema1x vs Schema1 and Schema10)
|
80
|
-
cand = "#{@prefix}#{n}x"
|
81
|
-
next if @items.key?(cand)
|
82
|
-
@items[cand] = obj.merge
|
83
|
-
@schema_names.add(cand)
|
84
|
-
return ref_string(cand)
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
def store_anchor(obj, ref = nil)
|
89
|
-
anchor_name = obj['$anchor']
|
90
|
-
return if anchor_name.nil?
|
91
|
-
ref = obj['$ref'] if ref.nil?
|
92
|
-
raise Exception, 'ref is nil and no $ref or it is nil' if ref.nil?
|
93
|
-
@anchor2ref[anchor_name] = ref
|
94
|
-
end
|
95
|
-
|
96
|
-
def alter_anchors
|
97
|
-
replacements = {}
|
98
|
-
@anchor2ref.each do |a, r|
|
99
|
-
next if @schema_names.member?(a)
|
100
|
-
replacements[a] = ref_string(a)
|
101
|
-
@schema_names.add(a)
|
102
|
-
end
|
103
|
-
replacements.each do |a, r|
|
104
|
-
@anchor2ref[a] = r
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
def anchor_ref_replacement(ref)
|
109
|
-
@anchor2ref[ref[1...ref.size]] || ref
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
class ServerPath
|
114
|
-
# Probably moves to a separate file once processpaths and frequencies receive
|
115
|
-
# some attention.
|
116
|
-
include Comparable
|
117
|
-
|
118
|
-
attr_accessor :parts
|
119
|
-
|
120
|
-
def initialize(parts)
|
121
|
-
@parts = parts
|
122
|
-
end
|
123
|
-
|
124
|
-
def <=>(other) # Variables are after fixed strings.
|
125
|
-
pp = other.is_a?(Array) ? other : p.parts
|
126
|
-
parts.each_index do |k|
|
127
|
-
return 1 if pp.size <= k # Longer comes after shorter.
|
128
|
-
pk = parts[k]
|
129
|
-
ppk = pp[k]
|
130
|
-
if pk.is_a? String
|
131
|
-
if ppk.is_a? String
|
132
|
-
c = pk <=> ppk
|
133
|
-
else
|
134
|
-
return -1
|
135
|
-
end
|
136
|
-
else
|
137
|
-
if ppk.is_a? String
|
138
|
-
return 1
|
139
|
-
else
|
140
|
-
c = pk.fetch('var', '') <=> ppk.fetch('var', '')
|
141
|
-
end
|
142
|
-
end
|
143
|
-
return c unless c.zero?
|
144
|
-
end
|
145
|
-
(parts.size < pp.size) ? -1 : 0
|
146
|
-
end
|
147
|
-
|
148
|
-
def compare(p, range = nil) # Not fit for sorting. Variable equals anything.
|
149
|
-
pp = p.is_a?(Array) ? p : p.parts
|
150
|
-
if range.nil?
|
151
|
-
range = 0...parts.size
|
152
|
-
elsif range.is_a? Number
|
153
|
-
range = range...(range + 1)
|
154
|
-
end
|
155
|
-
range.each do |k|
|
156
|
-
return 1 if pp.size <= k # Longer comes after shorter.
|
157
|
-
ppk = pp[k]
|
158
|
-
next unless ppk.is_a? String
|
159
|
-
pk = parts[k]
|
160
|
-
next unless pk.is_a? String
|
161
|
-
c = pk <=> ppk
|
162
|
-
return c unless c.zero?
|
163
|
-
end
|
164
|
-
(parts.size < pp.size) ? -1 : 0
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
# The rest probably ends up in a gem that orders schemas and does nothing else.
|
169
|
-
|
170
|
-
# Adds all refs found in the array to refs with given required state.
|
171
|
-
def gather_array_refs(refs, items, required)
|
172
|
-
items.each do |s|
|
173
|
-
r = s['$ref']
|
174
|
-
next if r.nil?
|
175
|
-
refs[r] = required || refs.fetch(r, false)
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
# For any key '$ref' adds to refs whether referred type is required.
|
180
|
-
# Requires that there are no in-lined schemas, openapi-addschemas has been run.
|
181
|
-
def gather_refs(refs, schema)
|
182
|
-
# This implies types mixed together according to examples. Needs mixed type.
|
183
|
-
# AND. Also, mixing may fail. Adds a new schema, do here.
|
184
|
-
items = schema['allOf']
|
185
|
-
return gather_array_refs(refs, items, true) unless items.nil?
|
186
|
-
# As long as one schema is fulfilled, it is ok. OR, first that fits.
|
187
|
-
items = schema['anyOf'] if items.nil?
|
188
|
-
# oneOf implies selection between different types. No multiple matches. XOR.
|
189
|
-
# Needs to ensure that later types do not match.
|
190
|
-
# Should check if there is enough difference to ensure single match.
|
191
|
-
# Use separate program run after addschemas to create allOf mixed schema
|
192
|
-
# and verify the others can be dealt with.
|
193
|
-
items = schema['oneOf'] if items.nil?
|
194
|
-
return gather_array_refs(refs, items, false) unless items.nil?
|
195
|
-
# Defaults below handle it if "type" is not "object".
|
196
|
-
reqs = schema.fetch('required', [])
|
197
|
-
schema.fetch('properties', {}).each do |name, spec|
|
198
|
-
r = spec['$ref']
|
199
|
-
next if r.nil?
|
200
|
-
refs[r] = reqs.include?(name) || refs.fetch(r, false)
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
class SchemaInfo
|
205
|
-
attr_accessor :ref, :schema, :direct_refs, :name, :post_refs
|
206
|
-
|
207
|
-
def initialize(ref, name, schema)
|
208
|
-
@ref = ref
|
209
|
-
@name = name
|
210
|
-
@schema = schema
|
211
|
-
@direct_refs = {}
|
212
|
-
gather_refs(@direct_refs, schema)
|
213
|
-
end
|
214
|
-
|
215
|
-
def set_post_refs(seen)
|
216
|
-
@post_refs = Set.new(@direct_refs.keys) - seen
|
217
|
-
end
|
218
|
-
|
219
|
-
def to_s
|
220
|
-
v = @direct_refs.keys.sort.map { |k| "#{k}:#{@direct_refs[k] ? 'req' : 'opt'}" }
|
221
|
-
"#{@ref}: #{v.join(' ')}"
|
222
|
-
end
|
223
|
-
end
|
224
|
-
|
225
|
-
def var_or_method_value(x, name)
|
226
|
-
if name.start_with?('@')
|
227
|
-
n = name
|
228
|
-
else
|
229
|
-
n = "@#{name}"
|
230
|
-
end
|
231
|
-
return x.instance_variable_get(n) if x.instance_variable_defined?(n)
|
232
|
-
return x.public_send(name) if x.respond_to?(name)
|
233
|
-
raise ArgumentError, "#{name} is not #{x.class} instance variable nor public method"
|
234
|
-
end
|
235
|
-
|
236
|
-
class SchemaOrderer
|
237
|
-
attr_accessor :schemas, :order, :orderer
|
238
|
-
|
239
|
-
def initialize(path, schema_specs)
|
240
|
-
@schemas = {}
|
241
|
-
schema_specs.each do |name, schema|
|
242
|
-
r = "#{path}#{name}"
|
243
|
-
@schemas[r] = SchemaInfo.new(r, name, schema)
|
244
|
-
end
|
245
|
-
end
|
246
|
-
|
247
|
-
def sort!(orderer = 'required_first')
|
248
|
-
case orderer
|
249
|
-
when 'required_first' then @order = required_first
|
250
|
-
when '<=>' then @order = @schemas.values.sort { |a, b| a <=> b }
|
251
|
-
else
|
252
|
-
@order = @schemas.values.sort do |a, b|
|
253
|
-
va = var_or_method_value(a, orderer)
|
254
|
-
vb = var_or_method_value(b, orderer)
|
255
|
-
va <=> vb
|
256
|
-
end
|
257
|
-
end
|
258
|
-
@orderer = orderer
|
259
|
-
seen = Set.new
|
260
|
-
@order.each do |si|
|
261
|
-
si.set_post_refs(seen)
|
262
|
-
seen.add(si.ref)
|
263
|
-
end
|
264
|
-
@order
|
265
|
-
end
|
266
|
-
|
267
|
-
def required_first
|
268
|
-
chosen = []
|
269
|
-
until chosen.size == @schemas.size
|
270
|
-
used = Set.new(chosen.map { |si| si.ref })
|
271
|
-
avail = @schemas.values.select { |si| !used.member?(si.ref) }
|
272
|
-
best = nil
|
273
|
-
avail.each do |si|
|
274
|
-
prereq = chosen.count { |x| x.direct_refs.fetch(si.ref, false) }
|
275
|
-
fulfilled = chosen.count { |x| si.direct_refs.fetch(x.ref, false) }
|
276
|
-
postreq = si.direct_refs.size - (prereq + fulfilled)
|
277
|
-
better = false
|
278
|
-
if best.nil?
|
279
|
-
better = true
|
280
|
-
else
|
281
|
-
# Minimize preceding types requiring this.
|
282
|
-
if prereq < best.first
|
283
|
-
better = true
|
284
|
-
elsif prereq == best.first
|
285
|
-
# Minimize remaining unfulfilled requires.
|
286
|
-
if postreq < best[1]
|
287
|
-
better = true
|
288
|
-
elsif postreq == best[1]
|
289
|
-
# Check mutual direct requirements.
|
290
|
-
best_req_si = best.last.direct_refs.fetch(si.ref, false)
|
291
|
-
si_req_best = si.direct_refs.fetch(best.last.ref, false)
|
292
|
-
if best_req_si
|
293
|
-
better = true unless si_req_best
|
294
|
-
end
|
295
|
-
# Order by name if no other difference.
|
296
|
-
better = si.ref < best.last.ref unless better
|
297
|
-
end
|
298
|
-
end
|
299
|
-
end
|
300
|
-
best = [ prereq, postreq, si ] if better
|
301
|
-
end
|
302
|
-
chosen.push(best.last)
|
303
|
-
end
|
304
|
-
chosen
|
305
|
-
end
|
306
|
-
end
|
data/lib/common.rb
DELETED
@@ -1,114 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Copyright © 2021-2024 Ismo Kärkkäinen
|
4
|
-
# Licensed under Universal Permissive License. See LICENSE.txt.
|
5
|
-
|
6
|
-
require 'pathname'
|
7
|
-
|
8
|
-
|
9
|
-
def aargh(message, return_value = nil)
|
10
|
-
message = message.map(&:to_s).join("\n") if message.is_a? Array
|
11
|
-
$stderr.puts message
|
12
|
-
return_value
|
13
|
-
end
|
14
|
-
|
15
|
-
def yesno(boolean)
|
16
|
-
boolean ? 'yes' : 'no'
|
17
|
-
end
|
18
|
-
|
19
|
-
def bury(doc, path, value)
|
20
|
-
(path.size - 1).times do |k|
|
21
|
-
p = path[k]
|
22
|
-
doc[p] = {} unless doc.key?(p)
|
23
|
-
doc = doc[p]
|
24
|
-
end
|
25
|
-
doc[path.last] = value
|
26
|
-
end
|
27
|
-
|
28
|
-
module Out
|
29
|
-
attr_reader :count
|
30
|
-
|
31
|
-
def put(message)
|
32
|
-
aargh(message)
|
33
|
-
count += 1
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def split_path(p, spec = false)
|
38
|
-
parts = []
|
39
|
-
p = p.strip
|
40
|
-
unless spec
|
41
|
-
q = p.index('?')
|
42
|
-
p.slice!(0...q) unless q.nil?
|
43
|
-
end
|
44
|
-
p.split('/').each do |s|
|
45
|
-
next if s.empty?
|
46
|
-
s = { var: s } if spec && s.include?('{')
|
47
|
-
parts.push(s)
|
48
|
-
end
|
49
|
-
parts
|
50
|
-
end
|
51
|
-
|
52
|
-
def load_source(input)
|
53
|
-
YAML.safe_load(input.nil? ? $stdin : File.read(input))
|
54
|
-
rescue Errno::ENOENT
|
55
|
-
aargh "Could not load #{input || 'stdin'}"
|
56
|
-
rescue StandardError => e
|
57
|
-
aargh "#{e}\nFailed to read #{input || 'stdin'}"
|
58
|
-
end
|
59
|
-
|
60
|
-
def dump_result(output, doc, error_return)
|
61
|
-
doc = YAML.dump(doc, line_width: 1_000_000) unless doc.is_a?(String)
|
62
|
-
if output.nil?
|
63
|
-
$stdout.puts doc
|
64
|
-
else
|
65
|
-
fp = Pathname.new output
|
66
|
-
fp.open('w') do |f|
|
67
|
-
f.puts doc
|
68
|
-
end
|
69
|
-
end
|
70
|
-
0
|
71
|
-
rescue StandardError => e
|
72
|
-
aargh([ e, "Failed to write output: #{output || 'stdout'}" ], error_return)
|
73
|
-
end
|
74
|
-
|
75
|
-
ServerPath = Struct.new(:parts) do
|
76
|
-
# Variables are after fixed strings.
|
77
|
-
def <=>(other)
|
78
|
-
pp = other.is_a?(Array) ? other : other.parts
|
79
|
-
parts.each_index do |k|
|
80
|
-
return 1 if pp.size <= k # Longer comes after shorter.
|
81
|
-
pk = parts[k]
|
82
|
-
ppk = pp[k]
|
83
|
-
if pk.is_a? String
|
84
|
-
return -1 unless ppk.is_a? String
|
85
|
-
c = pk <=> ppk
|
86
|
-
else
|
87
|
-
return 1 if ppk.is_a? String
|
88
|
-
c = pk.fetch('var', '') <=> ppk.fetch('var', '')
|
89
|
-
end
|
90
|
-
return c unless c.zero?
|
91
|
-
end
|
92
|
-
(parts.size < pp.size) ? -1 : 0
|
93
|
-
end
|
94
|
-
|
95
|
-
# Not fit for sorting. Variable equals anything.
|
96
|
-
def compare(p, range = nil)
|
97
|
-
pp = p.is_a?(Array) ? p : p.parts
|
98
|
-
if range.nil?
|
99
|
-
range = 0...parts.size
|
100
|
-
elsif range.is_a? Number
|
101
|
-
range = range...(range + 1)
|
102
|
-
end
|
103
|
-
range.each do |k|
|
104
|
-
return 1 if pp.size <= k # Longer comes after shorter.
|
105
|
-
ppk = pp[k]
|
106
|
-
next unless ppk.is_a? String
|
107
|
-
pk = parts[k]
|
108
|
-
next unless pk.is_a? String
|
109
|
-
c = pk <=> ppk
|
110
|
-
return c unless c.zero?
|
111
|
-
end
|
112
|
-
(parts.size < pp.size) ? -1 : 0
|
113
|
-
end
|
114
|
-
end
|
data/lib/docs.rb
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Copyright © 2024 Ismo Kärkkäinen
|
4
|
-
# Licensed under Universal Permissive License. See LICENSE.txt.
|
5
|
-
|
6
|
-
require_relative 'common'
|
7
|
-
|
8
|
-
|
9
|
-
class Docs
|
10
|
-
attr_reader :docs
|
11
|
-
|
12
|
-
def initialize
|
13
|
-
@docs = {}
|
14
|
-
end
|
15
|
-
|
16
|
-
def method_missing(method_name, *args)
|
17
|
-
name = method_name.to_s
|
18
|
-
if name.end_with?('=')
|
19
|
-
name = name[0...(name.size - 1)]
|
20
|
-
super unless @docs.key?(name)
|
21
|
-
@docs[name] = args.first
|
22
|
-
return args.first
|
23
|
-
end
|
24
|
-
super unless @docs.key?(name)
|
25
|
-
@docs[name]
|
26
|
-
end
|
27
|
-
|
28
|
-
def add(name, content)
|
29
|
-
return false if docs.key?(name)
|
30
|
-
@docs[name] = content
|
31
|
-
true
|
32
|
-
end
|
33
|
-
end
|
data/lib/gen.rb
DELETED
@@ -1,104 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Copyright © 2024 Ismo Kärkkäinen
|
4
|
-
# Licensed under Universal Permissive License. See LICENSE.txt.
|
5
|
-
|
6
|
-
require_relative 'task'
|
7
|
-
require_relative 'helper'
|
8
|
-
require_relative 'docs'
|
9
|
-
require_relative 'output'
|
10
|
-
|
11
|
-
|
12
|
-
module Gen
|
13
|
-
def self.add_doc(symbol, docstr)
|
14
|
-
return if docstr.nil?
|
15
|
-
@docsrc = [] unless instance_variable_defined?('@docsrc')
|
16
|
-
@docsrc.push("- #{symbol.to_s} : #{docstr}")
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.read_attr(symbol, default)
|
20
|
-
return if symbol.nil?
|
21
|
-
attr_reader(symbol)
|
22
|
-
module_function(symbol)
|
23
|
-
instance_variable_set("@#{symbol.to_s}", default)
|
24
|
-
end
|
25
|
-
|
26
|
-
def self.mod_attr2_reader(symbol, symbol2, docstr = nil, default = nil)
|
27
|
-
read_attr(symbol, default)
|
28
|
-
read_attr(symbol2, default)
|
29
|
-
add_doc(symbol, docstr)
|
30
|
-
end
|
31
|
-
|
32
|
-
def self.mod_attr_reader(symbol, docstr = nil, default = nil)
|
33
|
-
mod_attr2_reader(symbol, nil, docstr, default)
|
34
|
-
end
|
35
|
-
|
36
|
-
def self.rw_attr(symbol, default)
|
37
|
-
attr_accessor(symbol)
|
38
|
-
module_function(symbol)
|
39
|
-
s = symbol.to_s
|
40
|
-
module_function((s + '=').to_sym)
|
41
|
-
instance_variable_set("@#{s}", default)
|
42
|
-
end
|
43
|
-
|
44
|
-
def self.mod_attr2_accessor(symbol, symbol2, docstr = nil, default = nil)
|
45
|
-
rw_attr(symbol, default)
|
46
|
-
rw_attr(symbol2, default) unless symbol2.nil?
|
47
|
-
add_doc(symbol, docstr)
|
48
|
-
end
|
49
|
-
|
50
|
-
def self.mod_attr_accessor(symbol, docstr = nil, default = nil)
|
51
|
-
mod_attr2_accessor(symbol, nil, docstr, default)
|
52
|
-
end
|
53
|
-
|
54
|
-
mod_attr_reader :doc, 'OpenAPI document.'
|
55
|
-
mod_attr_reader :outdir, 'Output directory name.'
|
56
|
-
mod_attr_reader :d, 'Other documents object.', Docs.new
|
57
|
-
mod_attr_accessor :in_name, 'OpenAPI document name, nil if stdin.'
|
58
|
-
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.'
|
62
|
-
mod_attr_accessor :h, 'Instance of class with helper methods.'
|
63
|
-
mod_attr2_accessor :task, :t, 'Current task instance.'
|
64
|
-
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
|
67
|
-
|
68
|
-
def self.setup(document_content, input_name, output_directory)
|
69
|
-
@doc = document_content
|
70
|
-
@outdir = output_directory
|
71
|
-
unless input_name.nil?
|
72
|
-
@in_name = File.basename(input_name)
|
73
|
-
@in_basename = File.basename(input_name, '.*')
|
74
|
-
end
|
75
|
-
add_task(task: HelperTask.new)
|
76
|
-
end
|
77
|
-
|
78
|
-
def self.add_task(task:, name: nil, executable: false, x: nil)
|
79
|
-
@tasks.push(task)
|
80
|
-
# Since this method allows the user to pass their own task type instance,
|
81
|
-
# assign optional values with defaults only when clearly given.
|
82
|
-
@tasks.last.name = name unless name.nil?
|
83
|
-
@tasks.last.executable = executable unless executable == false
|
84
|
-
@tasks.last.x = x unless x.nil?
|
85
|
-
end
|
86
|
-
|
87
|
-
def self.add_write_content(name:, content:, executable: false)
|
88
|
-
add_task(task: WriteTask.new(name, content, executable))
|
89
|
-
end
|
90
|
-
|
91
|
-
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)
|
93
|
-
end
|
94
|
-
|
95
|
-
def self.document
|
96
|
-
@docsrc.join("\n") + %(
|
97
|
-
- add_task(task:, name: nil, executable: false, x: nil) : Adds task object.
|
98
|
-
- add_write_content(name:, content:, executable: false) : Add file write task.
|
99
|
-
- add(source:, template: nil, template_name: nil, name: nil,
|
100
|
-
executable: false, x: nil) :
|
101
|
-
Adds template task with source as object to process.
|
102
|
-
)
|
103
|
-
end
|
104
|
-
end
|