goa_model_gen 0.3.0 → 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 +4 -4
- data/lib/goa_model_gen/cli.rb +14 -26
- data/lib/goa_model_gen/config.rb +1 -1
- data/lib/goa_model_gen/field.rb +4 -0
- data/lib/goa_model_gen/generator.rb +16 -8
- data/lib/goa_model_gen/golang_helper.rb +19 -0
- data/lib/goa_model_gen/loader.rb +43 -19
- data/lib/goa_model_gen/source_file.rb +31 -0
- data/lib/goa_model_gen/templates/model.go.erb +11 -13
- data/lib/goa_model_gen/templates/model_validation.go.erb +1 -1
- data/lib/goa_model_gen/type.rb +21 -0
- data/lib/goa_model_gen/version.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 721bb2c0d07817d9853be4f1dae801b682b51d636416880e464b29ace1477949
|
4
|
+
data.tar.gz: 2a5c2e05448fd86fb2b3bef0d5b3693589fd325c45830763ea82f29a1e924f39
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bd7b88d3471523df596f2b07ad5cb974c5ca6a127ed75cca19a5615d8b432a5edf812341047c554a7988358f0dfa6ef9548ecf5857d435b8b17cd0ded2f60ece
|
7
|
+
data.tar.gz: d1cb7ccfbe6dd50baeede29910cdcafbdace04d8b55d2fbf322143fb76f42017b5bf8c9dbfb23a20be748bb827765a95c5eb1841834b6c5df83b4450de62f56f
|
data/lib/goa_model_gen/cli.rb
CHANGED
@@ -32,22 +32,22 @@ module GoaModelGen
|
|
32
32
|
desc "show FILE1...", "Show model info from definition files"
|
33
33
|
def show(*paths)
|
34
34
|
show_version_if_required
|
35
|
-
load_types_for(paths) do |
|
36
|
-
puts "types in #{
|
37
|
-
puts YAML.dump(types)
|
35
|
+
load_types_for(paths) do |source_file|
|
36
|
+
puts "types in #{source_file.yaml_path}"
|
37
|
+
puts YAML.dump(source_file.types)
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
41
|
desc "model FILE1...", "Generate model files from definition files"
|
42
42
|
def model(*paths)
|
43
43
|
show_version_if_required
|
44
|
-
load_types_for(paths) do |
|
45
|
-
generator = new_generator.tap{|g| g.
|
44
|
+
load_types_for(paths) do |source_file|
|
45
|
+
generator = new_generator.tap{|g| g.source_file = source_file }
|
46
46
|
[
|
47
47
|
{path: 'templates/model.go.erb', suffix: '.go', overwrite: true},
|
48
48
|
{path: 'templates/model_validation.go.erb', suffix: '_validation.go', overwrite: false},
|
49
49
|
].each do |d|
|
50
|
-
dest = File.join(cfg.model_dir, File.basename(path, ".*") + d[:suffix])
|
50
|
+
dest = File.join(cfg.model_dir, File.basename(source_file.path, ".*") + d[:suffix])
|
51
51
|
generator.run(d[:path], dest, overwrite: d[:overwrite])
|
52
52
|
end
|
53
53
|
end
|
@@ -56,10 +56,10 @@ module GoaModelGen
|
|
56
56
|
desc "converter FILE1...", "Generate converter files from definition files and swagger.yaml"
|
57
57
|
def converter(*paths)
|
58
58
|
show_version_if_required
|
59
|
-
load_types_for(paths) do |
|
60
|
-
generator = new_generator.tap{|g| g.types = types }
|
61
|
-
dest = File.join(cfg.controller_dir, File.basename(
|
62
|
-
if types.any?{|t| !!t.payload || !!t.media_type}
|
59
|
+
load_types_for(paths) do |source_file|
|
60
|
+
generator = new_generator.tap{|g| g.types = source_file.types }
|
61
|
+
dest = File.join(cfg.controller_dir, File.basename(source_file.yaml_path, ".*") + "_conv.go")
|
62
|
+
if source_file.types.any?{|t| !!t.payload || !!t.media_type}
|
63
63
|
generator.run('templates/converter.go.erb', dest, overwrite: true)
|
64
64
|
end
|
65
65
|
end
|
@@ -88,24 +88,12 @@ module GoaModelGen
|
|
88
88
|
end
|
89
89
|
|
90
90
|
def load_types_for(paths)
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
types = GoaModelGen::ModelLoader.new(path).load_types
|
96
|
-
types.each{|t| t.assign_swagger_types(swagger_loader) }
|
97
|
-
types.each{|t| defined_types[t.name] = t }
|
98
|
-
path_to_types[path] = types
|
99
|
-
end
|
100
|
-
paths.each do |path|
|
101
|
-
types = path_to_types[path]
|
102
|
-
types.each{|t| t.assign_field_type_base(defined_types) }
|
103
|
-
end
|
104
|
-
paths.each do |path|
|
105
|
-
yield(path, path_to_types[path])
|
91
|
+
loader = GoaModelGen::Loader.new(cfg)
|
92
|
+
source_files = loader.load(paths)
|
93
|
+
source_files.each do |source_file|
|
94
|
+
yield(source_file)
|
106
95
|
end
|
107
96
|
end
|
108
|
-
|
109
97
|
end
|
110
98
|
|
111
99
|
end
|
data/lib/goa_model_gen/config.rb
CHANGED
data/lib/goa_model_gen/field.rb
CHANGED
@@ -62,6 +62,10 @@ module GoaModelGen
|
|
62
62
|
].map{|k,v| v ? "#{k}:\"#{v}\"" : nil}.compact.join(' ')
|
63
63
|
end
|
64
64
|
|
65
|
+
def definition
|
66
|
+
"#{ name } #{ type } `#{ tag }`"
|
67
|
+
end
|
68
|
+
|
65
69
|
# https://swagger.io/docs/specification/data-models/data-types/
|
66
70
|
# https://tour.golang.org/basics/11
|
67
71
|
# https://golang.org/pkg/go/types/#pkg-variables
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require "goa_model_gen"
|
2
|
+
require "goa_model_gen/golang_helper"
|
2
3
|
|
3
4
|
require "erb"
|
4
5
|
|
@@ -9,23 +10,30 @@ module GoaModelGen
|
|
9
10
|
class Generator
|
10
11
|
# These are used in templates
|
11
12
|
attr_reader :config
|
12
|
-
attr_accessor :
|
13
|
+
attr_accessor :source_file
|
13
14
|
|
14
15
|
def initialize(config)
|
15
16
|
@config = config
|
16
17
|
end
|
17
18
|
|
18
|
-
def
|
19
|
-
|
20
|
-
|
19
|
+
def golang_helper
|
20
|
+
@golang_helper ||= GolangHelper.new
|
21
|
+
end
|
22
|
+
|
23
|
+
def generate(template_path)
|
24
|
+
abs_path = File.expand_path('../' + template_path, __FILE__)
|
21
25
|
erb = ERB.new(File.read(abs_path), nil, "-")
|
22
26
|
erb.filename = abs_path
|
23
27
|
content = erb.result(binding)
|
24
|
-
open(path, 'w'){|f| f.puts(content) }
|
25
|
-
if (File.extname(path) == '.go') && !config.gofmt_disabled
|
26
|
-
system("gofmt -w #{path}")
|
27
|
-
end
|
28
28
|
end
|
29
29
|
|
30
|
+
def run(template_path, output_path, overwrite: false)
|
31
|
+
return if File.exist?(output_path) && !overwrite
|
32
|
+
content = generate(template_path)
|
33
|
+
open(output_path, 'w'){|f| f.puts(content) }
|
34
|
+
if (File.extname(output_path) == '.go') && !config.gofmt_disabled
|
35
|
+
system("gofmt -w #{output_path}")
|
36
|
+
end
|
37
|
+
end
|
30
38
|
end
|
31
39
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module GoaModelGen
|
2
|
+
class GolangHelper
|
3
|
+
|
4
|
+
PARTITION_PATTERNS = [
|
5
|
+
/\A[^\.\/]+(?:\/.+)?\z/,
|
6
|
+
/\Agopkg\.in\//,
|
7
|
+
/\Agolang\.org\//,
|
8
|
+
/\Agoogle\.golang\.org\//,
|
9
|
+
/\Agithub\.com\//,
|
10
|
+
]
|
11
|
+
|
12
|
+
def partition(paths)
|
13
|
+
groups = paths.group_by do |path|
|
14
|
+
PARTITION_PATTERNS.index{|ptn| ptn =~ path} || PARTITION_PATTERNS.length
|
15
|
+
end
|
16
|
+
groups.keys.sort.map{|k| groups[k].sort }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/goa_model_gen/loader.rb
CHANGED
@@ -4,6 +4,7 @@ require "yaml"
|
|
4
4
|
|
5
5
|
require "goa_model_gen/type"
|
6
6
|
require "goa_model_gen/field"
|
7
|
+
require "goa_model_gen/source_file"
|
7
8
|
|
8
9
|
module GoaModelGen
|
9
10
|
class BaseLoader
|
@@ -16,12 +17,6 @@ module GoaModelGen
|
|
16
17
|
@raw = YAML.load_file(path)
|
17
18
|
end
|
18
19
|
|
19
|
-
def load_types
|
20
|
-
raw[types_key].map do |name, definition|
|
21
|
-
build_type(name, definition)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
20
|
def build_type(name, d)
|
26
21
|
kind.new(name, d).tap do |t|
|
27
22
|
if d[fields_key]
|
@@ -35,19 +30,6 @@ module GoaModelGen
|
|
35
30
|
def build_field(name, f)
|
36
31
|
Field.new(name, f)
|
37
32
|
end
|
38
|
-
|
39
|
-
def dig(path)
|
40
|
-
dig_into(raw, path.split('/'), [])
|
41
|
-
end
|
42
|
-
|
43
|
-
def dig_into(hash, keys, footprints)
|
44
|
-
# puts "dig_into(hash, #{keys.inspect}, #{footprints.inspect})"
|
45
|
-
key = keys.shift
|
46
|
-
value = hash[key]
|
47
|
-
return value if keys.empty?
|
48
|
-
raise "No data for #{key} in #{footprints.join('/')}" if value.nil?
|
49
|
-
return dig_into(value, keys, footprints + [key])
|
50
|
-
end
|
51
33
|
end
|
52
34
|
|
53
35
|
class ModelLoader < BaseLoader
|
@@ -55,6 +37,13 @@ module GoaModelGen
|
|
55
37
|
super(path, Model, 'types', 'fields')
|
56
38
|
end
|
57
39
|
|
40
|
+
def load_file
|
41
|
+
types = raw[types_key].map do |name, definition|
|
42
|
+
build_type(name, definition)
|
43
|
+
end
|
44
|
+
SourceFile.new(path, types)
|
45
|
+
end
|
46
|
+
|
58
47
|
def build_field(name, f)
|
59
48
|
fd = f.is_a?(Hash) ? f : {'type' => f.to_s}
|
60
49
|
fd['type'] ||= 'string'
|
@@ -94,5 +83,40 @@ module GoaModelGen
|
|
94
83
|
raise "#{name} not found in #{path}" unless r
|
95
84
|
r
|
96
85
|
end
|
86
|
+
|
87
|
+
def dig(path)
|
88
|
+
dig_into(raw, path.split('/'), [])
|
89
|
+
end
|
90
|
+
|
91
|
+
def dig_into(hash, keys, footprints)
|
92
|
+
# puts "dig_into(hash, #{keys.inspect}, #{footprints.inspect})"
|
93
|
+
key = keys.shift
|
94
|
+
value = hash[key]
|
95
|
+
return value if keys.empty?
|
96
|
+
raise "No data for #{key} in #{footprints.join('/')}" if value.nil?
|
97
|
+
return dig_into(value, keys, footprints + [key])
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
class Loader
|
102
|
+
attr_reader :config
|
103
|
+
def initialize(config)
|
104
|
+
@config = config
|
105
|
+
end
|
106
|
+
|
107
|
+
def load_types(paths)
|
108
|
+
swagger_loader = GoaModelGen::SwaggerLoader.new(config.swagger_yaml)
|
109
|
+
defined_types = {}
|
110
|
+
files = paths.map do |path|
|
111
|
+
GoaModelGen::ModelLoader.new(path).load_file.tap do |f|
|
112
|
+
f.types.each{|t| t.assign_swagger_types(swagger_loader) }
|
113
|
+
f.types.each{|t| defined_types[t.name] = t }
|
114
|
+
end
|
115
|
+
end
|
116
|
+
files.each do |f|
|
117
|
+
f.types.each{|t| t.assign_field_type_base(defined_types) }
|
118
|
+
end
|
119
|
+
return files
|
120
|
+
end
|
97
121
|
end
|
98
122
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require 'goa_model_gen'
|
3
|
+
require 'goa_model_gen/type'
|
4
|
+
|
5
|
+
require "active_support/core_ext/string"
|
6
|
+
|
7
|
+
module GoaModelGen
|
8
|
+
class SourceFile
|
9
|
+
attr_reader :yaml_path, :types
|
10
|
+
def initialize(yaml_path, types)
|
11
|
+
@yaml_path, @types = yaml_path, types
|
12
|
+
end
|
13
|
+
|
14
|
+
def model_dependencies
|
15
|
+
@model_dependencies ||= calc_model_dependencies
|
16
|
+
end
|
17
|
+
|
18
|
+
def calc_model_dependencies
|
19
|
+
r = []
|
20
|
+
r << "github.com/goadesign/goa/uuid" if types.any?(&:use_uuid?)
|
21
|
+
if types.any?(&:store?)
|
22
|
+
r << "fmt"
|
23
|
+
r << "golang.org/x/net/context"
|
24
|
+
r << "google.golang.org/appengine/datastore"
|
25
|
+
r << "google.golang.org/appengine/log"
|
26
|
+
end
|
27
|
+
r << "time" if types.any?(&:has_time_field?)
|
28
|
+
r.uniq
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -1,29 +1,27 @@
|
|
1
1
|
package model
|
2
2
|
|
3
|
+
<%- unless source_file.model_dependencies.empty? -%>
|
3
4
|
import (
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
"google.golang.org/appengine/datastore"
|
9
|
-
"google.golang.org/appengine/log"
|
5
|
+
<%- golang_helper.partition(source_file.model_dependencies).each do |group| -%>
|
6
|
+
<%- group.each do |path| -%>
|
7
|
+
"<%= path %>"
|
8
|
+
<%- end -%>
|
10
9
|
|
11
|
-
<%- if types.select(&:store?).any?{|m| m.goon['id_type'] == 'UUID'} -%>
|
12
|
-
"github.com/goadesign/goa/uuid"
|
13
10
|
<%- end -%>
|
14
11
|
)
|
12
|
+
<%- end -%>
|
15
13
|
|
16
|
-
<%- types.each do |type| -%>
|
14
|
+
<%- source_file.types.each do |type| -%>
|
17
15
|
<%- if !type.fields.empty? -%>
|
18
16
|
type <%= type.name %> struct {
|
19
17
|
<%- if type.goon -%>
|
20
|
-
<%= type.
|
18
|
+
<%= type.id_definition %>
|
21
19
|
<%- if type.parent -%>
|
22
20
|
ParentKey *datastore.Key `datastore:"-" goon:"parent" json:"-"`
|
23
21
|
<%- end -%>
|
24
22
|
<%- end -%>
|
25
23
|
<%- type.fields.each do |field| -%>
|
26
|
-
<%= field.
|
24
|
+
<%= field.definition %>
|
27
25
|
<%- end -%>
|
28
26
|
}
|
29
27
|
<%- elsif type.base -%>
|
@@ -40,7 +38,7 @@ const (
|
|
40
38
|
|
41
39
|
<%- end -%>
|
42
40
|
|
43
|
-
<%- types.select(&:store?).each do |model| -%>
|
41
|
+
<%- source_file.types.select(&:store?).each do |model| -%>
|
44
42
|
func (m *<%= model.name %>) PrepareToCreate() error {
|
45
43
|
<%- if model.fields.any?{|f| f.name == "CreatedAt"} -%>
|
46
44
|
if m.CreatedAt.IsZero() {
|
@@ -71,7 +69,7 @@ func (m *<%= model.name %>) Parent(ctx context.Context) (*<%= model.parent %>, e
|
|
71
69
|
|
72
70
|
<%- end -%>
|
73
71
|
|
74
|
-
<%- types.select(&:store?).each do |model| -%>
|
72
|
+
<%- source_file.types.select(&:store?).each do |model| -%>
|
75
73
|
<%- store_name = "#{model.name}Store" -%>
|
76
74
|
type <%= store_name %> struct{
|
77
75
|
<%- if model.parent -%>
|
@@ -4,7 +4,7 @@ import (
|
|
4
4
|
"gopkg.in/go-playground/validator.v9"
|
5
5
|
)
|
6
6
|
|
7
|
-
<%- types.select(&:store?).each do |model| -%>
|
7
|
+
<%- source_file.types.select(&:store?).each do |model| -%>
|
8
8
|
func (m *<%= model.name %>) Validate() error {
|
9
9
|
validator := validator.New()
|
10
10
|
return validator.Struct(m)
|
data/lib/goa_model_gen/type.rb
CHANGED
@@ -16,6 +16,15 @@ module GoaModelGen
|
|
16
16
|
def assign_field_type_base(types)
|
17
17
|
self.fields.each{|f| f.assign_type_base(types) }
|
18
18
|
end
|
19
|
+
|
20
|
+
def use_uuid?
|
21
|
+
false
|
22
|
+
end
|
23
|
+
|
24
|
+
TIME_TYPE_PATTERN = /\Atime\./
|
25
|
+
def has_time_field?
|
26
|
+
fields.any?{|f| f.type =~ TIME_TYPE_PATTERN}
|
27
|
+
end
|
19
28
|
end
|
20
29
|
|
21
30
|
class Model < Type
|
@@ -58,6 +67,10 @@ module GoaModelGen
|
|
58
67
|
s.blank? ? nil : s[0].downcase + s[1..-1]
|
59
68
|
end
|
60
69
|
|
70
|
+
def id_definition
|
71
|
+
goon && "#{id_name} #{id_golang_type } `datastore:\"-\" goon:\"id\" json:\"#{ id_name.underscore }\"`"
|
72
|
+
end
|
73
|
+
|
61
74
|
def parent
|
62
75
|
goon && goon['parent']
|
63
76
|
end
|
@@ -66,6 +79,11 @@ module GoaModelGen
|
|
66
79
|
!!goon
|
67
80
|
end
|
68
81
|
|
82
|
+
# @override
|
83
|
+
def use_uuid?
|
84
|
+
goon && (goon['id_type'] == 'UUID')
|
85
|
+
end
|
86
|
+
|
69
87
|
def key_id_method
|
70
88
|
case id_golang_type
|
71
89
|
when 'int64' then 'IntID'
|
@@ -110,6 +128,9 @@ module GoaModelGen
|
|
110
128
|
end
|
111
129
|
end
|
112
130
|
|
131
|
+
def field_by(name)
|
132
|
+
fields.detect{|f| f.name == name}
|
133
|
+
end
|
113
134
|
end
|
114
135
|
|
115
136
|
class SwaggerDef < Type
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: goa_model_gen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- akm
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-11-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -120,7 +120,9 @@ files:
|
|
120
120
|
- lib/goa_model_gen/field.rb
|
121
121
|
- lib/goa_model_gen/generator.rb
|
122
122
|
- lib/goa_model_gen/goa.rb
|
123
|
+
- lib/goa_model_gen/golang_helper.rb
|
123
124
|
- lib/goa_model_gen/loader.rb
|
125
|
+
- lib/goa_model_gen/source_file.rb
|
124
126
|
- lib/goa_model_gen/templates/converter.go.erb
|
125
127
|
- lib/goa_model_gen/templates/converter_base.go.erb
|
126
128
|
- lib/goa_model_gen/templates/goon.go.erb
|
@@ -148,7 +150,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
148
150
|
version: '0'
|
149
151
|
requirements: []
|
150
152
|
rubyforge_project:
|
151
|
-
rubygems_version: 2.7.
|
153
|
+
rubygems_version: 2.7.6
|
152
154
|
signing_key:
|
153
155
|
specification_version: 4
|
154
156
|
summary: Generate model files for goa in golang
|