schemaforge 0.1.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 +7 -0
- data/LICENSE.txt +19 -0
- data/README.md +25 -0
- data/exe/schemaforge +44 -0
- data/lib/schema_forge/builtin_types.rb +44 -0
- data/lib/schema_forge/errors.rb +17 -0
- data/lib/schema_forge/generator.rb +391 -0
- data/lib/schema_forge/hooks.rb +35 -0
- data/lib/schema_forge/loader.rb +132 -0
- data/lib/schema_forge/naming.rb +37 -0
- data/lib/schema_forge/parser.rb +346 -0
- data/lib/schema_forge/resolver.rb +332 -0
- data/lib/schema_forge/schema.rb +47 -0
- data/lib/schema_forge/version.rb +5 -0
- data/lib/schema_forge/writer.rb +17 -0
- data/lib/schema_forge.rb +49 -0
- metadata +71 -0
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SchemaForge
|
|
4
|
+
class Resolver
|
|
5
|
+
def self.resolve(doc)
|
|
6
|
+
new(doc).resolve
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def initialize(doc)
|
|
10
|
+
@doc = doc
|
|
11
|
+
@target_ns = doc.target_namespace
|
|
12
|
+
@promoted = []
|
|
13
|
+
@existing_names = doc.types.filter_map(&:name).to_set
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def resolve
|
|
17
|
+
new_types = @doc.types.map { |t| promote_within(t, parent_name: t.name) }
|
|
18
|
+
new_elements = @doc.elements.map { |e| promote_in_element(e, parent_name: e.name) }
|
|
19
|
+
@doc = Schema::Document.new(
|
|
20
|
+
target_namespace: @doc.target_namespace,
|
|
21
|
+
namespaces: @doc.namespaces,
|
|
22
|
+
types: new_types + @promoted,
|
|
23
|
+
elements: new_elements,
|
|
24
|
+
groups: @doc.groups,
|
|
25
|
+
attribute_groups: @doc.attribute_groups,
|
|
26
|
+
imports: @doc.imports,
|
|
27
|
+
includes: @doc.includes
|
|
28
|
+
)
|
|
29
|
+
expand_groups_and_flatten_extensions
|
|
30
|
+
@types_by_qname = build_index
|
|
31
|
+
check_all_type_refs
|
|
32
|
+
@doc
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def index_groups
|
|
38
|
+
@doc.groups.to_h { |g| [[@target_ns, g.name], g] }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def index_attribute_groups
|
|
42
|
+
@doc.attribute_groups.to_h { |ag| [[@target_ns, ag.name], ag] }
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def expand_groups_and_flatten_extensions
|
|
46
|
+
groups_idx = index_groups
|
|
47
|
+
ag_idx = index_attribute_groups
|
|
48
|
+
|
|
49
|
+
new_types = @doc.types.map { |t| expand_in_type(t, groups_idx, ag_idx) }
|
|
50
|
+
new_types = new_types.map { |t| flatten_extension(t, new_types, ag_idx) }
|
|
51
|
+
|
|
52
|
+
@doc = Schema::Document.new(
|
|
53
|
+
target_namespace: @doc.target_namespace,
|
|
54
|
+
namespaces: @doc.namespaces,
|
|
55
|
+
types: new_types,
|
|
56
|
+
elements: @doc.elements,
|
|
57
|
+
groups: @doc.groups,
|
|
58
|
+
attribute_groups: @doc.attribute_groups,
|
|
59
|
+
imports: @doc.imports,
|
|
60
|
+
includes: @doc.includes
|
|
61
|
+
)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def expand_in_type(type, groups_idx, ag_idx)
|
|
65
|
+
return type unless type.is_a?(Schema::ComplexType)
|
|
66
|
+
|
|
67
|
+
new_attributes = type.attributes + ag_refs_to_attributes(type.attribute_groups, ag_idx)
|
|
68
|
+
new_content = expand_groups_in_content(type.content, groups_idx)
|
|
69
|
+
|
|
70
|
+
Schema::ComplexType.new(
|
|
71
|
+
name: type.name, anonymous: type.anonymous, base: type.base, derivation: type.derivation,
|
|
72
|
+
attributes: new_attributes, attribute_groups: [],
|
|
73
|
+
content: new_content, mixed: type.mixed, doc: type.doc
|
|
74
|
+
)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def ag_refs_to_attributes(refs, ag_idx)
|
|
78
|
+
refs.flat_map do |ref|
|
|
79
|
+
ag = ag_idx[[ref.ref.namespace, ref.ref.local_name]]
|
|
80
|
+
raise ResolveError.new("unresolved attributeGroup ref: #{ref.ref.local_name}", source: nil) unless ag
|
|
81
|
+
|
|
82
|
+
ag.attributes + ag_refs_to_attributes(ag.attribute_groups, ag_idx)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def expand_groups_in_content(content, groups_idx)
|
|
87
|
+
case content
|
|
88
|
+
when Schema::Sequence
|
|
89
|
+
Schema::Sequence.new(items: content.items.flat_map do |i|
|
|
90
|
+
expand_particle(i, groups_idx)
|
|
91
|
+
end, min_occurs: content.min_occurs, max_occurs: content.max_occurs)
|
|
92
|
+
when Schema::Choice
|
|
93
|
+
Schema::Choice.new(items: content.items.flat_map do |i|
|
|
94
|
+
expand_particle(i, groups_idx)
|
|
95
|
+
end, min_occurs: content.min_occurs, max_occurs: content.max_occurs)
|
|
96
|
+
else
|
|
97
|
+
content
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def expand_particle(particle, groups_idx)
|
|
102
|
+
case particle
|
|
103
|
+
when Schema::GroupRef
|
|
104
|
+
g = groups_idx[[particle.ref.namespace, particle.ref.local_name]]
|
|
105
|
+
raise ResolveError.new("unresolved group ref: #{particle.ref.local_name}", source: nil) unless g
|
|
106
|
+
|
|
107
|
+
case g.content
|
|
108
|
+
when Schema::Sequence, Schema::Choice then g.content.items
|
|
109
|
+
else []
|
|
110
|
+
end
|
|
111
|
+
when Schema::Sequence, Schema::Choice
|
|
112
|
+
[expand_groups_in_content(particle, groups_idx)]
|
|
113
|
+
else
|
|
114
|
+
[particle]
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def flatten_extension(type, all_types, ag_idx)
|
|
119
|
+
return type unless type.is_a?(Schema::ComplexType) && type.derivation == :extension && type.base
|
|
120
|
+
|
|
121
|
+
base = all_types.find { |t| t.is_a?(Schema::ComplexType) && t.name == type.base.local_name }
|
|
122
|
+
return type unless base # base is in another namespace or built-in (simpleContent extension)
|
|
123
|
+
|
|
124
|
+
base_flat = flatten_extension(base, all_types, ag_idx)
|
|
125
|
+
Schema::ComplexType.new(
|
|
126
|
+
name: type.name, anonymous: type.anonymous, base: type.base, derivation: type.derivation,
|
|
127
|
+
attributes: base_flat.attributes + type.attributes,
|
|
128
|
+
attribute_groups: type.attribute_groups,
|
|
129
|
+
content: merge_content(base_flat.content, type.content),
|
|
130
|
+
mixed: type.mixed,
|
|
131
|
+
doc: type.doc
|
|
132
|
+
)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def merge_content(base_content, derived_content)
|
|
136
|
+
return derived_content if base_content.nil?
|
|
137
|
+
return base_content if derived_content.nil?
|
|
138
|
+
if base_content.is_a?(Schema::Sequence) && derived_content.is_a?(Schema::Sequence)
|
|
139
|
+
return Schema::Sequence.new(items: base_content.items + derived_content.items, min_occurs: 1,
|
|
140
|
+
max_occurs: 1)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
derived_content
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def build_index
|
|
147
|
+
idx = {}
|
|
148
|
+
@doc.types.each { |t| idx[[@doc.target_namespace, t.name]] = t }
|
|
149
|
+
idx
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# ----- Promotion -----
|
|
153
|
+
|
|
154
|
+
def promote_within(type, parent_name:)
|
|
155
|
+
case type
|
|
156
|
+
when Schema::ComplexType
|
|
157
|
+
new_attributes = type.attributes.map { |a| promote_in_attribute(a, parent_name: parent_name) }
|
|
158
|
+
new_content = promote_in_content(type.content, parent_name: parent_name)
|
|
159
|
+
Schema::ComplexType.new(
|
|
160
|
+
name: type.name, anonymous: type.anonymous, base: type.base, derivation: type.derivation,
|
|
161
|
+
attributes: new_attributes, attribute_groups: type.attribute_groups,
|
|
162
|
+
content: new_content, mixed: type.mixed, doc: type.doc
|
|
163
|
+
)
|
|
164
|
+
else
|
|
165
|
+
type
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def promote_in_element(elem, parent_name:)
|
|
170
|
+
if elem.inline_type
|
|
171
|
+
promoted_name = synthesize_name(parent_name)
|
|
172
|
+
promoted = rename(elem.inline_type, promoted_name)
|
|
173
|
+
promoted = promote_within(promoted, parent_name: promoted_name)
|
|
174
|
+
@promoted << promoted
|
|
175
|
+
Schema::Element.new(
|
|
176
|
+
name: elem.name,
|
|
177
|
+
type_ref: Schema::TypeRef.new(namespace: @target_ns, local_name: promoted_name),
|
|
178
|
+
inline_type: nil,
|
|
179
|
+
min_occurs: elem.min_occurs, max_occurs: elem.max_occurs,
|
|
180
|
+
nillable: elem.nillable, default: elem.default, fixed: elem.fixed, doc: elem.doc
|
|
181
|
+
)
|
|
182
|
+
else
|
|
183
|
+
elem
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def promote_in_attribute(attr, parent_name:)
|
|
188
|
+
if attr.inline_type
|
|
189
|
+
promoted_name = synthesize_name(parent_name, "#{pascal_case(attr.name)}Attr")
|
|
190
|
+
promoted = rename(attr.inline_type, promoted_name)
|
|
191
|
+
promoted = promote_within(promoted, parent_name: promoted_name)
|
|
192
|
+
@promoted << promoted
|
|
193
|
+
Schema::Attribute.new(
|
|
194
|
+
name: attr.name,
|
|
195
|
+
type_ref: Schema::TypeRef.new(namespace: @target_ns, local_name: promoted_name),
|
|
196
|
+
inline_type: nil,
|
|
197
|
+
use: attr.use, default: attr.default, fixed: attr.fixed, doc: attr.doc
|
|
198
|
+
)
|
|
199
|
+
else
|
|
200
|
+
attr
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def promote_in_content(content, parent_name:)
|
|
205
|
+
case content
|
|
206
|
+
when Schema::Sequence
|
|
207
|
+
Schema::Sequence.new(
|
|
208
|
+
items: content.items.map { |i| promote_in_particle(i, parent_name: parent_name) },
|
|
209
|
+
min_occurs: content.min_occurs, max_occurs: content.max_occurs
|
|
210
|
+
)
|
|
211
|
+
when Schema::Choice
|
|
212
|
+
Schema::Choice.new(
|
|
213
|
+
items: content.items.map { |i| promote_in_particle(i, parent_name: parent_name) },
|
|
214
|
+
min_occurs: content.min_occurs, max_occurs: content.max_occurs
|
|
215
|
+
)
|
|
216
|
+
else
|
|
217
|
+
content
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def promote_in_particle(particle, parent_name:)
|
|
222
|
+
case particle
|
|
223
|
+
when Schema::Element
|
|
224
|
+
promote_in_element(particle, parent_name: "#{parent_name}_#{pascal_case(particle.name)}")
|
|
225
|
+
when Schema::Sequence, Schema::Choice
|
|
226
|
+
promote_in_content(particle, parent_name: parent_name)
|
|
227
|
+
else
|
|
228
|
+
particle
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def rename(type, new_name)
|
|
233
|
+
case type
|
|
234
|
+
when Schema::ComplexType
|
|
235
|
+
Schema::ComplexType.new(
|
|
236
|
+
name: new_name, anonymous: false, base: type.base, derivation: type.derivation,
|
|
237
|
+
attributes: type.attributes, attribute_groups: type.attribute_groups,
|
|
238
|
+
content: type.content, mixed: type.mixed, doc: type.doc
|
|
239
|
+
)
|
|
240
|
+
when Schema::SimpleType
|
|
241
|
+
Schema::SimpleType.new(name: new_name, anonymous: false, body: type.body, doc: type.doc)
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def synthesize_name(*parts)
|
|
246
|
+
base = parts.compact.map { |p| pascal_case(p) }.join("_")
|
|
247
|
+
candidate = base
|
|
248
|
+
counter = 1
|
|
249
|
+
while @existing_names.include?(candidate)
|
|
250
|
+
counter += 1
|
|
251
|
+
candidate = "#{base}_#{counter}"
|
|
252
|
+
end
|
|
253
|
+
@existing_names << candidate
|
|
254
|
+
candidate
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def pascal_case(name)
|
|
258
|
+
return "" if name.nil?
|
|
259
|
+
|
|
260
|
+
name.to_s.gsub(/[^A-Za-z0-9]+/, "_").split("_").map { |s| s[0].to_s.upcase + s[1..].to_s }.join
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
# ----- Validation walk (TypeRef checks) -----
|
|
264
|
+
|
|
265
|
+
def check_all_type_refs
|
|
266
|
+
@doc.types.each { |t| walk(t) }
|
|
267
|
+
@doc.elements.each { |e| walk_element(e) }
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
def walk(node)
|
|
271
|
+
case node
|
|
272
|
+
when Schema::ComplexType
|
|
273
|
+
check_ref(node.base) if node.base
|
|
274
|
+
node.attributes.each { |a| walk_attribute(a) }
|
|
275
|
+
walk_content(node.content) if node.content
|
|
276
|
+
when Schema::SimpleType
|
|
277
|
+
walk_simple_body(node.body) if node.body
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
def walk_content(node)
|
|
282
|
+
case node
|
|
283
|
+
when Schema::Sequence, Schema::Choice
|
|
284
|
+
node.items.each { |item| walk_particle(item) }
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
def walk_particle(node)
|
|
289
|
+
case node
|
|
290
|
+
when Schema::Element then walk_element(node)
|
|
291
|
+
when Schema::Sequence, Schema::Choice then walk_content(node)
|
|
292
|
+
when Schema::GroupRef, Schema::Any then nil
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
def walk_element(elem)
|
|
297
|
+
check_ref(elem.type_ref) if elem.type_ref
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
def walk_attribute(attr)
|
|
301
|
+
check_ref(attr.type_ref) if attr.type_ref
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
def walk_simple_body(body)
|
|
305
|
+
case body
|
|
306
|
+
when Schema::Restriction then check_restriction(body)
|
|
307
|
+
when Schema::List then check_list(body)
|
|
308
|
+
when Schema::Union then check_union(body)
|
|
309
|
+
end
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
def check_restriction(body)
|
|
313
|
+
check_ref(body.base) if body.base
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
def check_list(body)
|
|
317
|
+
check_ref(body.item_type) if body.item_type.is_a?(Schema::TypeRef)
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
def check_union(body)
|
|
321
|
+
body.member_types.each { |member| check_ref(member) if member.is_a?(Schema::TypeRef) }
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
def check_ref(ref)
|
|
325
|
+
return if ref.nil?
|
|
326
|
+
return if BuiltinTypes.builtin?(ref.namespace, ref.local_name)
|
|
327
|
+
return if @types_by_qname.key?([ref.namespace, ref.local_name])
|
|
328
|
+
|
|
329
|
+
raise ResolveError.new("unresolved type reference: {#{ref.namespace}}#{ref.local_name}", source: nil)
|
|
330
|
+
end
|
|
331
|
+
end
|
|
332
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SchemaForge
|
|
4
|
+
module Schema
|
|
5
|
+
Document = Data.define(
|
|
6
|
+
:target_namespace, :namespaces, :types, :elements,
|
|
7
|
+
:groups, :attribute_groups, :imports, :includes
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
ComplexType = Data.define(
|
|
11
|
+
:name, :anonymous, :base, :derivation,
|
|
12
|
+
:attributes, :attribute_groups, :content, :mixed, :doc
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
SimpleType = Data.define(:name, :anonymous, :body, :doc)
|
|
16
|
+
|
|
17
|
+
Element = Data.define(
|
|
18
|
+
:name, :type_ref, :inline_type,
|
|
19
|
+
:min_occurs, :max_occurs, :nillable, :default, :fixed, :doc
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
Attribute = Data.define(
|
|
23
|
+
:name, :type_ref, :inline_type, :use, :default, :fixed, :doc
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
Sequence = Data.define(:items, :min_occurs, :max_occurs)
|
|
27
|
+
Choice = Data.define(:items, :min_occurs, :max_occurs)
|
|
28
|
+
|
|
29
|
+
Group = Data.define(:name, :content)
|
|
30
|
+
GroupRef = Data.define(:ref, :min_occurs, :max_occurs)
|
|
31
|
+
AttributeGroup = Data.define(:name, :attributes, :attribute_groups)
|
|
32
|
+
AttributeGroupRef = Data.define(:ref)
|
|
33
|
+
|
|
34
|
+
Restriction = Data.define(:base, :facets)
|
|
35
|
+
Extension = Data.define(:base, :content, :attributes, :attribute_groups)
|
|
36
|
+
|
|
37
|
+
List = Data.define(:item_type)
|
|
38
|
+
Union = Data.define(:member_types)
|
|
39
|
+
|
|
40
|
+
TypeRef = Data.define(:namespace, :local_name)
|
|
41
|
+
|
|
42
|
+
Any = Data.define(:namespace, :process_contents, :min_occurs, :max_occurs)
|
|
43
|
+
|
|
44
|
+
Import = Data.define(:namespace, :schema_location)
|
|
45
|
+
Include = Data.define(:schema_location)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
|
|
5
|
+
module SchemaForge
|
|
6
|
+
module Writer
|
|
7
|
+
module_function
|
|
8
|
+
|
|
9
|
+
def write(output_dir, source_path, content)
|
|
10
|
+
FileUtils.mkdir_p(output_dir)
|
|
11
|
+
base = File.basename(source_path, ".*")
|
|
12
|
+
target = File.join(output_dir, "#{base}.rb")
|
|
13
|
+
File.write(target, content)
|
|
14
|
+
target
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
data/lib/schema_forge.rb
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "schema_forge/version"
|
|
4
|
+
require_relative "schema_forge/errors"
|
|
5
|
+
require_relative "schema_forge/builtin_types"
|
|
6
|
+
require_relative "schema_forge/schema"
|
|
7
|
+
require_relative "schema_forge/parser"
|
|
8
|
+
require_relative "schema_forge/loader"
|
|
9
|
+
require_relative "schema_forge/resolver"
|
|
10
|
+
require_relative "schema_forge/naming"
|
|
11
|
+
require_relative "schema_forge/hooks"
|
|
12
|
+
require_relative "schema_forge/generator"
|
|
13
|
+
require_relative "schema_forge/writer"
|
|
14
|
+
|
|
15
|
+
module SchemaForge
|
|
16
|
+
module_function
|
|
17
|
+
|
|
18
|
+
def generate(input:, output:, module_name: "Schema", hooks: nil, fetch_remote: true)
|
|
19
|
+
each_xsd(input) do |path|
|
|
20
|
+
source = generate_one(path, module_name: module_name, hooks: hooks, fetch_remote: fetch_remote)
|
|
21
|
+
Writer.write(output, path, source)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def generate_string(input:, module_name: "Schema", hooks: nil, fetch_remote: true)
|
|
26
|
+
paths = enumerate_xsd(input)
|
|
27
|
+
raise ArgumentError, "generate_string requires a single XSD file, got: #{input}" if paths.size != 1
|
|
28
|
+
|
|
29
|
+
generate_one(paths.first, module_name: module_name, hooks: hooks, fetch_remote: fetch_remote)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def each_xsd(input, &)
|
|
33
|
+
enumerate_xsd(input).each(&)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def enumerate_xsd(input)
|
|
37
|
+
if File.directory?(input)
|
|
38
|
+
Dir[File.join(input, "*.xsd")]
|
|
39
|
+
else
|
|
40
|
+
[input]
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def generate_one(path, module_name:, hooks:, fetch_remote:)
|
|
45
|
+
doc = Loader.load(path, fetch_remote: fetch_remote)
|
|
46
|
+
resolved = Resolver.resolve(doc)
|
|
47
|
+
Generator.new(module_name: module_name, hooks: hooks).emit(resolved)
|
|
48
|
+
end
|
|
49
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: schemaforge
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- igbanam
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: nokogiri
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '1.16'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '1.16'
|
|
26
|
+
description: Parses XSD files and emits Ruby Data.define value objects with runtime
|
|
27
|
+
validation.
|
|
28
|
+
email:
|
|
29
|
+
- xigbanam@gmail.com
|
|
30
|
+
executables:
|
|
31
|
+
- schemaforge
|
|
32
|
+
extensions: []
|
|
33
|
+
extra_rdoc_files: []
|
|
34
|
+
files:
|
|
35
|
+
- LICENSE.txt
|
|
36
|
+
- README.md
|
|
37
|
+
- exe/schemaforge
|
|
38
|
+
- lib/schema_forge.rb
|
|
39
|
+
- lib/schema_forge/builtin_types.rb
|
|
40
|
+
- lib/schema_forge/errors.rb
|
|
41
|
+
- lib/schema_forge/generator.rb
|
|
42
|
+
- lib/schema_forge/hooks.rb
|
|
43
|
+
- lib/schema_forge/loader.rb
|
|
44
|
+
- lib/schema_forge/naming.rb
|
|
45
|
+
- lib/schema_forge/parser.rb
|
|
46
|
+
- lib/schema_forge/resolver.rb
|
|
47
|
+
- lib/schema_forge/schema.rb
|
|
48
|
+
- lib/schema_forge/version.rb
|
|
49
|
+
- lib/schema_forge/writer.rb
|
|
50
|
+
licenses:
|
|
51
|
+
- MIT
|
|
52
|
+
metadata:
|
|
53
|
+
rubygems_mfa_required: 'true'
|
|
54
|
+
rdoc_options: []
|
|
55
|
+
require_paths:
|
|
56
|
+
- lib
|
|
57
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: 3.2.0
|
|
62
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
63
|
+
requirements:
|
|
64
|
+
- - ">="
|
|
65
|
+
- !ruby/object:Gem::Version
|
|
66
|
+
version: '0'
|
|
67
|
+
requirements: []
|
|
68
|
+
rubygems_version: 4.0.10
|
|
69
|
+
specification_version: 4
|
|
70
|
+
summary: Generate Ruby Data.define value objects from XSD schemas.
|
|
71
|
+
test_files: []
|