goa_model_gen 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|