eworld 1.2.2 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/core/aws_profile.rb +41 -0
- data/lib/eworld.rb +11 -33
- data/lib/routes/generate.rb +127 -0
- data/lib/routes/scan.rb +42 -6
- data/lib/rules/js/rule_js_parameters.rb +1 -2
- data/lib/scanners/controller_scanner.rb +137 -0
- data/lib/scanners/entity_scanner.rb +15 -0
- data/lib/scanners/permission_scanner.rb +15 -0
- data/lib/scanners/queue_scanner.rb +15 -0
- data/lib/scanners/route_scanner.rb +239 -0
- data/lib/version.rb +1 -1
- data/lib/writers/api_docs_writer.rb +32 -0
- data/lib/writers/base_writer.rb +21 -0
- data/lib/writers/controller_writer.rb +115 -0
- data/lib/writers/entity_writer.rb +15 -0
- data/lib/writers/js_docs_writer.rb +32 -0
- data/lib/writers/permission_writer.rb +15 -0
- data/lib/writers/queue_writer.rb +14 -0
- data/lib/writers/route_writer.rb +56 -0
- data/lib/writers/service_writer.rb +106 -0
- data/opt/config/schema.yml +7 -0
- data/opt/schema/controllers.yml +32 -0
- data/opt/schema/database.yml +0 -0
- data/opt/schema/routes.yml +77 -0
- metadata +24 -7
- data/lib/routes/generate_api_entities.rb +0 -35
- data/lib/routes/generate_ui_routes.rb +0 -41
@@ -0,0 +1,239 @@
|
|
1
|
+
module EWorld
|
2
|
+
|
3
|
+
class RouteScanner
|
4
|
+
|
5
|
+
SCHEMA_FILE = "#{EWorld::Opt::get_base_path}#{EWorld::Opt::OPT_PATH}/schema/routes.yml"
|
6
|
+
ROUTES = 'Routes'
|
7
|
+
FULLPATH = 'fullpath'
|
8
|
+
CODE = 'code'
|
9
|
+
PATH = 'path'
|
10
|
+
NAME = 'name'
|
11
|
+
META = 'meta'
|
12
|
+
COMPONENT = 'component'
|
13
|
+
TITLE = 'title'
|
14
|
+
TAB_PARENT = 'tabParent'
|
15
|
+
DISABLED = 'disabled'
|
16
|
+
ICON = 'icon'
|
17
|
+
INVISIBLE = 'invisible'
|
18
|
+
CHILDREN = 'children'
|
19
|
+
HAS_PAGE = 'hasPage'
|
20
|
+
|
21
|
+
# Responsible for scanning the .codegen/routes/routes.yml file.
|
22
|
+
# @return Array
|
23
|
+
def self.scan(project)
|
24
|
+
raise RuntimeError, "Expected project type to be: #{Blufin::Projects::TYPE_QUASAR}, instead got: #{project[Blufin::Projects::TYPE]}" unless project[Blufin::Projects::TYPE] == Blufin::Projects::TYPE_QUASAR
|
25
|
+
@errors = []
|
26
|
+
@codes = []
|
27
|
+
@files = [] # Holds short version of file name.
|
28
|
+
@files_expected = [] # Holds full-path to file.
|
29
|
+
@files_to_write = [] # Holds list of files that need to be created/stubbed.
|
30
|
+
begin
|
31
|
+
@td = project[Blufin::Projects::TRANSIENT_DATA]
|
32
|
+
@path_root = Blufin::Strings::remove_surrounding_slashes(@td[Blufin::Projects::CG_QUASAR_ROOT])
|
33
|
+
@path_routes_file = Blufin::Strings::remove_surrounding_slashes(@td[Blufin::Projects::CG_QUASAR_ROUTES_FILE])
|
34
|
+
@path_pages = Blufin::Strings::remove_surrounding_slashes(@td[Blufin::Projects::CG_QUASAR_PAGES])
|
35
|
+
@path_pages_ignore = @td[Blufin::Projects::CG_QUASAR_PAGES_IGNORE]
|
36
|
+
@project_path = Blufin::Projects::get_project_path(project[Blufin::Projects::PROJECT_ID])
|
37
|
+
@project_path_inner = Blufin::Projects::get_project_path(project[Blufin::Projects::PROJECT_ID], true)
|
38
|
+
routes_file = "#{@project_path_inner}/#{@path_routes_file}"
|
39
|
+
# Make sure file exists.
|
40
|
+
unless Blufin::Files::file_exists(routes_file)
|
41
|
+
@errors << Blufin::ScannerError::add_error(nil, "File not found: #{Blufin::Terminal::format_invalid(routes_file)}")
|
42
|
+
return {}, @errors
|
43
|
+
end
|
44
|
+
# Extract routes file content so we can parse/validate it.
|
45
|
+
routes_content = []
|
46
|
+
Blufin::Files::read_file(routes_file).each do |line|
|
47
|
+
line = line.gsub("\n", '').gsub(/^\s*const\s*routes\s*=\s*\[/, '{ Routes: [')
|
48
|
+
# Handle component/import lines.
|
49
|
+
if line =~ /^\s*component:\s*\(\)\s*=>\s*import\s*\(['"]\s*@/
|
50
|
+
line = line.gsub(/component:\s*\(\)\s*=>\s*import\s*\(['"]\s*@/, '')
|
51
|
+
line = line.gsub(/['"]\s*\)\s*/, '')
|
52
|
+
comma = (line == line.gsub(/,?\s*$/, '')) ? '' : ','
|
53
|
+
routes_content << "#{line.split('/')[0]}component: '#{line.gsub(/,?\s*$/, '').strip}'#{comma}"
|
54
|
+
next
|
55
|
+
end
|
56
|
+
break if line =~ /^\s*if\s*\(/
|
57
|
+
routes_content << line unless line.strip == ''
|
58
|
+
end
|
59
|
+
# Remove trailing semi-colon.
|
60
|
+
routes_content[routes_content.length - 1] = routes_content[routes_content.length - 1].gsub(/;*\s*$/, '')
|
61
|
+
routes_content << '}'
|
62
|
+
hash = {}
|
63
|
+
eval("hash = #{Blufin::Arrays::convert_line_array_to_string(routes_content)}")
|
64
|
+
json = JSON.parse(hash.to_json)
|
65
|
+
# Create tmp file so we can read it. There might be a better way but no time.
|
66
|
+
tmp_filename = "/tmp/routes-content-#{Blufin::Strings::random_string(2)}.yaml"
|
67
|
+
# Write tmp file.
|
68
|
+
Blufin::Files::write_file(tmp_filename, Blufin::Arrays::convert_string_to_line_array(json.to_yaml))
|
69
|
+
@routes_yml = Blufin::Yml::read_file(tmp_filename, SCHEMA_FILE)
|
70
|
+
@routes_yml[ROUTES].each do |parent|
|
71
|
+
parent_path = parent[PATH]
|
72
|
+
parent_title = parent.has_key?(META) ? parent[META][TITLE] : nil
|
73
|
+
parent_icon = parent.has_key?(META) ? parent[META][ICON] : nil
|
74
|
+
parent_has_page = parent.has_key?(META) ? (parent[META][HAS_PAGE] ? true : false) : false
|
75
|
+
parent_invisible = parent.has_key?(META) ? parent[META][INVISIBLE] : nil
|
76
|
+
error_prefix = "Parent path: #{parent_path} \xe2\x80\x94 "
|
77
|
+
# Make sure HAS_PAGE is only ever false.
|
78
|
+
@errors << Blufin::ScannerError::add_error(routes_file, "#{error_prefix}Unless has_page == true, it is not required.", "has_page: '#{parent_has_page}'") if parent.has_key?(META) && parent[META].has_key?(HAS_PAGE) && !parent_has_page
|
79
|
+
# Make sure we have the correct meta properties for parent (based on invisible property).
|
80
|
+
if parent_invisible
|
81
|
+
@errors << Blufin::ScannerError::add_error(routes_file, "#{error_prefix}Invisible routes shouldn't have: icon") unless parent_icon.nil?
|
82
|
+
else
|
83
|
+
@errors << Blufin::ScannerError::add_error(routes_file, "#{error_prefix}Missing meta property: icon") if parent_icon.nil?
|
84
|
+
end
|
85
|
+
@errors << Blufin::ScannerError::add_error(routes_file, "#{error_prefix}Missing meta property: title") if parent_title.nil?
|
86
|
+
# Make sure properties are in the correct order.
|
87
|
+
expected = {
|
88
|
+
PATH => true,
|
89
|
+
META => false,
|
90
|
+
COMPONENT => true,
|
91
|
+
CHILDREN => false
|
92
|
+
}
|
93
|
+
Blufin::Validate::assert_valid_keys(expected, parent.keys, routes_file)
|
94
|
+
# Make sure meta properties are in the correct order.
|
95
|
+
if parent.has_key?(META)
|
96
|
+
expected = {
|
97
|
+
TITLE => false,
|
98
|
+
ICON => false,
|
99
|
+
HAS_PAGE => false,
|
100
|
+
INVISIBLE => false
|
101
|
+
}
|
102
|
+
Blufin::Validate::assert_valid_keys(expected, parent[META].keys, routes_file)
|
103
|
+
end
|
104
|
+
# Make sure parent path(s) have a preceding slash.
|
105
|
+
@errors << Blufin::ScannerError::add_error(routes_file, "#{error_prefix}Parent path must have preceding slash.") unless parent[PATH] =~ /^\//
|
106
|
+
# Validate children, if they exist.
|
107
|
+
validate_children(parent, Blufin::Strings::remove_surrounding_slashes(parent[PATH]), routes_file, error_prefix) if parent.has_key?(CHILDREN)
|
108
|
+
end
|
109
|
+
|
110
|
+
rescue => e
|
111
|
+
|
112
|
+
Blufin::Terminal::print_exception(e)
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
# Check for rogue files.
|
117
|
+
path_to_pages = "#{@project_path_inner}/#{@path_pages}"
|
118
|
+
Blufin::Files::get_files_in_dir(path_to_pages).each do |file|
|
119
|
+
next if file =~ /#{path_to_pages}\/(#{@path_pages_ignore.join('|')})\/[a-z0-9]/
|
120
|
+
unless @files_expected.include?(file)
|
121
|
+
@errors << Blufin::ScannerError::add_error(routes_file, "Rogue file: #{file}")
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
return @files_to_write, @errors
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
private
|
130
|
+
|
131
|
+
# Recursive function to validate children.
|
132
|
+
# @return void
|
133
|
+
def self.validate_children(parent, parent_path, routes_file, error_prefix, validate_nested = true)
|
134
|
+
raise RuntimeError, "Expected key: #{CHILDREN}" unless parent.has_key?(CHILDREN)
|
135
|
+
children = parent[CHILDREN]
|
136
|
+
parent_has_page = parent.has_key?(META) ? (parent[META][HAS_PAGE] ? true : false) : false
|
137
|
+
# Make sure we have an array with items.
|
138
|
+
unless children.is_a?(Array) || children.length == 0
|
139
|
+
@errors << Blufin::ScannerError::add_error(routes_file, "#{error_prefix}Children must be an Array and cannot be empty.")
|
140
|
+
return
|
141
|
+
end
|
142
|
+
children.each_with_index do |child, idx|
|
143
|
+
# Make a more direct error prefix.
|
144
|
+
error_prefix = "Route: #{child[NAME]} \xe2\x80\x94 " if child.has_key?(NAME)
|
145
|
+
# Make sure properties are in the correct order.
|
146
|
+
expected = {
|
147
|
+
PATH => true,
|
148
|
+
NAME => true,
|
149
|
+
META => false,
|
150
|
+
COMPONENT => true,
|
151
|
+
CHILDREN => false
|
152
|
+
}
|
153
|
+
Blufin::Validate::assert_valid_keys(expected, child.keys, routes_file)
|
154
|
+
# Make sure meta properties are in the correct order.
|
155
|
+
if child.has_key?(META)
|
156
|
+
expected = {
|
157
|
+
FULLPATH => false,
|
158
|
+
CODE => false,
|
159
|
+
TITLE => false,
|
160
|
+
ICON => false,
|
161
|
+
TAB_PARENT => false,
|
162
|
+
DISABLED => false,
|
163
|
+
}
|
164
|
+
Blufin::Validate::assert_valid_keys(expected, child[META].keys, routes_file)
|
165
|
+
end
|
166
|
+
|
167
|
+
# TODO - If non-tabs, must have FULLPATH, CODE, TITLE
|
168
|
+
# TODO - If tabs, must have ICON, TAB_PARENT
|
169
|
+
|
170
|
+
expected_name = Blufin::Strings::remove_surrounding_slashes("#{parent_path}/#{child[PATH]}").gsub('/', '-')
|
171
|
+
# Handle special case for dashboard.
|
172
|
+
expected_name = 'dashboard' if child[NAME] == 'dashboard' && expected_name.strip == ''
|
173
|
+
expected_file = Blufin::Strings::remove_surrounding_slashes("#{parent_path}/#{child[PATH]}").split('/')
|
174
|
+
raise RuntimeError, "Expected file count should never be greater than 3: #{expected_file.inspect}" if expected_file.length > 3
|
175
|
+
fullpath = '' if expected_file.length == 0
|
176
|
+
fullpath = expected_file[0] if expected_file.length == 1
|
177
|
+
fullpath = "#{expected_file[0]}/#{expected_file[1]}" if expected_file.length == 2
|
178
|
+
fullpath = "#{expected_file[0]}/#{expected_file[1]}/#{expected_file[2]}" if expected_file.length == 3
|
179
|
+
expected_file = '' if expected_file.length == 0
|
180
|
+
expected_file = expected_file[0] if expected_file.length == 1
|
181
|
+
expected_file = "#{expected_file[0]}/#{expected_file[1]}" if expected_file.length == 2
|
182
|
+
expected_file = "#{expected_file[0]}/#{expected_file[1]}-#{expected_file[2]}" if expected_file.length == 3
|
183
|
+
# Check full path is correct.
|
184
|
+
@errors << Blufin::ScannerError::add_error(routes_file, "Expected meta.fullpath: #{fullpath}", "Got meta.fullpath: '#{child[META][FULLPATH]}'") if child[META].has_key?(FULLPATH) && child[META][FULLPATH].strip != fullpath
|
185
|
+
# Check the parent path.
|
186
|
+
if idx == 0
|
187
|
+
if validate_nested
|
188
|
+
@errors << Blufin::ScannerError::add_error(routes_file, "#{error_prefix}If #{HAS_PAGE} flag is set, 1st child must have empty path.", "path: '#{child[PATH]}'") if parent_has_page && child[PATH] != ''
|
189
|
+
@errors << Blufin::ScannerError::add_error(routes_file, "#{error_prefix}If #{HAS_PAGE} flag is NOT set, 1st child cannot have empty path.", "path: '#{child[PATH]}'") if !parent_has_page && child[PATH].strip == ''
|
190
|
+
# This handles the root paths, IE: 'dashboard/dashboard.vue'
|
191
|
+
expected_file = "#{expected_name}/#{expected_name}" if parent_has_page
|
192
|
+
else
|
193
|
+
@errors << Blufin::ScannerError::add_error(routes_file, "#{error_prefix}Cannot have empty path.", "path: '#{child[PATH]}'") if child[PATH].strip == ''
|
194
|
+
end
|
195
|
+
else
|
196
|
+
@errors << Blufin::ScannerError::add_error(routes_file, "#{error_prefix}Cannot have empty path.", "path: '#{child[PATH]}'") if child[PATH].strip == ''
|
197
|
+
end
|
198
|
+
expected_file = "/#{@path_pages}/#{Blufin::Strings::remove_surrounding_slashes(expected_file)}.vue"
|
199
|
+
actual_file = "#{@project_path_inner}/#{Blufin::Strings::remove_surrounding_slashes(expected_file)}"
|
200
|
+
# Make sure we don't have any duplicate files.
|
201
|
+
if @files.include?(expected_file)
|
202
|
+
@errors << Blufin::ScannerError::add_error(routes_file, "Duplicate file: #{expected_file}")
|
203
|
+
else
|
204
|
+
@files << expected_file
|
205
|
+
@files_expected << actual_file
|
206
|
+
end
|
207
|
+
|
208
|
+
@files_to_write << actual_file unless Blufin::Files::file_exists(actual_file)
|
209
|
+
|
210
|
+
@errors << Blufin::ScannerError::add_error(routes_file, "Expected name: #{expected_name}", "Got name: '#{child[NAME]}'") if child[NAME].strip != expected_name
|
211
|
+
@errors << Blufin::ScannerError::add_error(routes_file, "Expected component: #{expected_file}", "Got component: '#{child[COMPONENT]}'") if child[COMPONENT].strip != expected_file
|
212
|
+
|
213
|
+
# Make sure there are no duplicate codes.
|
214
|
+
if child[META].has_key?(CODE)
|
215
|
+
code = child[META][CODE]
|
216
|
+
if @codes.include?(code)
|
217
|
+
@errors << Blufin::ScannerError::add_error(routes_file, "Duplicate code: #{code}")
|
218
|
+
else
|
219
|
+
@codes << code
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
# Validate nested children (if any).
|
224
|
+
if child.has_key?(CHILDREN)
|
225
|
+
unless validate_nested
|
226
|
+
# This will probably never get hit, but just in case.
|
227
|
+
@errors << Blufin::ScannerError::add_error(routes_file, "#{error_prefix}Cannot go more than 3 levels deep.") unless validate_nested
|
228
|
+
return
|
229
|
+
end
|
230
|
+
validate_children(child, "#{parent_path}/#{child[PATH]}", routes_file, error_prefix, false)
|
231
|
+
end
|
232
|
+
|
233
|
+
end
|
234
|
+
|
235
|
+
end
|
236
|
+
|
237
|
+
end
|
238
|
+
|
239
|
+
end
|
data/lib/version.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
EWORLD_VERSION = '
|
1
|
+
EWORLD_VERSION = '2.0.0'
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module EWorld
|
2
|
+
|
3
|
+
class ApiDocsWriter < EWorld::BaseWriter
|
4
|
+
|
5
|
+
# Responsible for writing all the spring boot @RestController classes.
|
6
|
+
# @return void
|
7
|
+
def self.write(api_project, ui_project, controllers)
|
8
|
+
raise RuntimeError, "Expected project type to be: #{Blufin::Projects::TYPE_API_SIMPLE}, instead got: #{api_project[Blufin::Projects::TYPE]}" unless api_project[Blufin::Projects::TYPE] == Blufin::Projects::TYPE_API_SIMPLE
|
9
|
+
raise RuntimeError, "Expected project type to be: #{Blufin::Projects::TYPE_QUASAR}, instead got: #{ui_project[Blufin::Projects::TYPE]}" unless ui_project[Blufin::Projects::TYPE] == Blufin::Projects::TYPE_QUASAR
|
10
|
+
@generated = []
|
11
|
+
@overwritten = []
|
12
|
+
@project_path = Blufin::Projects::get_project_path(api_project[Blufin::Projects::PROJECT_ID])
|
13
|
+
@project_path_api = Blufin::Projects::get_project_path(api_project[Blufin::Projects::PROJECT_ID], true)
|
14
|
+
@project_path_ui = Blufin::Projects::get_project_path(ui_project[Blufin::Projects::PROJECT_ID], true)
|
15
|
+
@transient_data_api = api_project[Blufin::Projects::TRANSIENT_DATA]
|
16
|
+
@transient_data_ui = ui_project[Blufin::Projects::TRANSIENT_DATA]
|
17
|
+
|
18
|
+
# TODO - This needs better data...
|
19
|
+
@data = controllers
|
20
|
+
|
21
|
+
target_file = "#{@project_path}/#{Blufin::Strings::remove_surrounding_slashes(@transient_data_ui[Blufin::Projects::CG_QUASAR_ROOT])}/#{Blufin::Strings::remove_surrounding_slashes(@transient_data_ui[Blufin::Projects::CG_QUASAR_API_DOCS_FILE])}"
|
22
|
+
|
23
|
+
# Write the file.
|
24
|
+
@overwritten << target_file if Blufin::Files::write_file_if_changed(target_file, Blufin::Arrays::convert_string_to_line_array(JSON.pretty_generate(@data, { indent: ' ' })), write_empty_trailing_line: true)
|
25
|
+
|
26
|
+
return @generated, @overwritten
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module EWorld
|
2
|
+
|
3
|
+
class BaseWriter
|
4
|
+
|
5
|
+
PACKAGE = '{{--PACKAGE--}}'
|
6
|
+
CLASS = '{{--CLASS--}}'
|
7
|
+
CLASS_LOWER = '{{--CLASS-LOWER--}}'
|
8
|
+
IMPORTS = '{{--IMPORTS--}}'
|
9
|
+
|
10
|
+
# Generic method to get root path for Controllers/Services in Java.
|
11
|
+
# @return string.
|
12
|
+
def self.get_java_path_for(project_path, path)
|
13
|
+
controller_path = "#{project_path}/#{Blufin::Strings::remove_surrounding_slashes(path)}"
|
14
|
+
controller_path_parent = controller_path.split('/')
|
15
|
+
controller_path_parent.pop
|
16
|
+
"/#{Blufin::Strings::remove_surrounding_slashes(controller_path_parent.join('/'))}"
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
module EWorld
|
2
|
+
|
3
|
+
class ControllerWriter < EWorld::BaseWriter
|
4
|
+
|
5
|
+
PACKAGE_NAME = 'controllers'
|
6
|
+
ROOT_PATH = '{{--ROOT-PATH--}}'
|
7
|
+
METHODS = '{{--METHODS--}}'
|
8
|
+
|
9
|
+
|
10
|
+
# Responsible for writing all the spring boot @RestController classes.
|
11
|
+
# @return void
|
12
|
+
def self.write(api_project, ui_project, controllers)
|
13
|
+
raise RuntimeError, "Expected project type to be: #{Blufin::Projects::TYPE_API_SIMPLE}, instead got: #{api_project[Blufin::Projects::TYPE]}" unless api_project[Blufin::Projects::TYPE] == Blufin::Projects::TYPE_API_SIMPLE
|
14
|
+
raise RuntimeError, "Expected project type to be: #{Blufin::Projects::TYPE_QUASAR}, instead got: #{ui_project[Blufin::Projects::TYPE]}" unless ui_project[Blufin::Projects::TYPE] == Blufin::Projects::TYPE_QUASAR
|
15
|
+
@generated = []
|
16
|
+
@overwritten = []
|
17
|
+
@project_path = Blufin::Projects::get_project_path(api_project[Blufin::Projects::PROJECT_ID])
|
18
|
+
@project_path_api = Blufin::Projects::get_project_path(api_project[Blufin::Projects::PROJECT_ID], true)
|
19
|
+
@project_path_ui = Blufin::Projects::get_project_path(ui_project[Blufin::Projects::PROJECT_ID], true)
|
20
|
+
@transient_data_api = api_project[Blufin::Projects::TRANSIENT_DATA]
|
21
|
+
@transient_data_ui = ui_project[Blufin::Projects::TRANSIENT_DATA]
|
22
|
+
@controller_path = "#{EWorld::BaseWriter::get_java_path_for(@project_path, @transient_data_api['ControllerPath'])}/#{PACKAGE_NAME}"
|
23
|
+
|
24
|
+
# Loop controllers.
|
25
|
+
controllers.each { |clazz, data| write_controller(clazz, data) }
|
26
|
+
|
27
|
+
# TODO - REMOVE
|
28
|
+
# puts @transient_data_api.to_yaml
|
29
|
+
# puts @transient_data_ui.to_yaml
|
30
|
+
# puts
|
31
|
+
# puts "\x1B[38;5;154m#{controllers.to_yaml}\x1B[0m"
|
32
|
+
|
33
|
+
return @generated, @overwritten
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
# Write controllers.
|
40
|
+
# @return void
|
41
|
+
def self.write_controller(clazz, data)
|
42
|
+
|
43
|
+
content = <<TEMPLATE
|
44
|
+
package #{PACKAGE}.api.#{PACKAGE_NAME};
|
45
|
+
|
46
|
+
import #{PACKAGE}.api.system.auth.annotations.Secured;
|
47
|
+
import #{PACKAGE}.api.system.auth.data.Permission;
|
48
|
+
import #{PACKAGE}.api.system.rest.base.AbstractController;
|
49
|
+
import #{PACKAGE}.lib.constants.Constants;
|
50
|
+
import #{PACKAGE}.lib.exceptions.ClientErrorException;
|
51
|
+
import #{PACKAGE}.lib.exceptions.NotImplementedException;
|
52
|
+
import #{PACKAGE}.lib.exceptions.ServerErrorException;
|
53
|
+
import #{PACKAGE}.lib.rest.data.ClientData;
|
54
|
+
import #{PACKAGE}.lib.rest.response.ApiResponseBuilder;
|
55
|
+
import #{PACKAGE}.core.#{EWorld::ServiceWriter::PACKAGE_NAME}.#{CLASS}Service;
|
56
|
+
import org.springframework.beans.factory.annotation.Autowired;
|
57
|
+
import org.springframework.web.bind.annotation.RequestMapping;
|
58
|
+
import org.springframework.web.bind.annotation.RequestParam;
|
59
|
+
import org.springframework.web.bind.annotation.RestController;
|
60
|
+
import org.springframework.http.ResponseEntity;
|
61
|
+
import org.springframework.web.bind.annotation.GetMapping;
|
62
|
+
import org.springframework.web.bind.annotation.PostMapping;
|
63
|
+
import org.springframework.web.bind.annotation.PutMapping;
|
64
|
+
import org.springframework.web.bind.annotation.DeleteMapping;
|
65
|
+
|
66
|
+
import java.io.IOException;
|
67
|
+
import java.util.Arrays;
|
68
|
+
import java.util.List;
|
69
|
+
|
70
|
+
@RestController
|
71
|
+
@RequestMapping("#{ROOT_PATH}")
|
72
|
+
public class #{CLASS}Controller extends AbstractController {
|
73
|
+
|
74
|
+
@Autowired
|
75
|
+
#{CLASS}Service #{CLASS_LOWER}Service;#{METHODS}}
|
76
|
+
TEMPLATE
|
77
|
+
|
78
|
+
methods_output = ''
|
79
|
+
|
80
|
+
# Add all the end-points.
|
81
|
+
if data.has_key?('EndPoints') && data['EndPoints'].is_a?(Array)
|
82
|
+
methods_output = "\n"
|
83
|
+
data['EndPoints'].each do |end_point|
|
84
|
+
method = end_point['Method'].downcase
|
85
|
+
method = method[0].upcase + method[1..-1]
|
86
|
+
path = end_point['Path'].downcase
|
87
|
+
camel_case = Blufin::Strings::snake_case_to_camel_case(path.gsub('-', '_'))
|
88
|
+
method_title = "#{method.downcase}#{camel_case}"
|
89
|
+
methods_output += <<TEMPLATE
|
90
|
+
|
91
|
+
@Secured
|
92
|
+
@#{method}Mapping("#{Blufin::Strings::remove_surrounding_slashes(path)}")
|
93
|
+
public ResponseEntity #{method_title}() {
|
94
|
+
|
95
|
+
return ApiResponseBuilder.ok(#{CLASS_LOWER}Service.#{method_title}());
|
96
|
+
}
|
97
|
+
TEMPLATE
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
content = content.gsub(METHODS, methods_output)
|
102
|
+
content = content.gsub(PACKAGE, @transient_data_api['Package'])
|
103
|
+
content = content.gsub(CLASS, clazz)
|
104
|
+
content = content.gsub(CLASS_LOWER, clazz[0].downcase + clazz[1..-1])
|
105
|
+
content = content.gsub(ROOT_PATH, data['RootPath'])
|
106
|
+
|
107
|
+
file = "#{@controller_path}/#{clazz}Controller.java"
|
108
|
+
|
109
|
+
Blufin::Files::write_file_java(file, Blufin::Arrays::convert_string_to_line_array(content), nil, false)
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module EWorld
|
2
|
+
|
3
|
+
class JsDocsWriter < EWorld::BaseWriter
|
4
|
+
|
5
|
+
# Responsible for writing all the spring boot @RestController classes.
|
6
|
+
# @return void
|
7
|
+
def self.write(api_project, ui_project, js_data)
|
8
|
+
raise RuntimeError, "Expected project type to be: #{Blufin::Projects::TYPE_API_SIMPLE}, instead got: #{api_project[Blufin::Projects::TYPE]}" unless api_project[Blufin::Projects::TYPE] == Blufin::Projects::TYPE_API_SIMPLE
|
9
|
+
raise RuntimeError, "Expected project type to be: #{Blufin::Projects::TYPE_QUASAR}, instead got: #{ui_project[Blufin::Projects::TYPE]}" unless ui_project[Blufin::Projects::TYPE] == Blufin::Projects::TYPE_QUASAR
|
10
|
+
@generated = []
|
11
|
+
@overwritten = []
|
12
|
+
@project_path = Blufin::Projects::get_project_path(api_project[Blufin::Projects::PROJECT_ID])
|
13
|
+
@project_path_api = Blufin::Projects::get_project_path(api_project[Blufin::Projects::PROJECT_ID], true)
|
14
|
+
@project_path_ui = Blufin::Projects::get_project_path(ui_project[Blufin::Projects::PROJECT_ID], true)
|
15
|
+
@transient_data_api = api_project[Blufin::Projects::TRANSIENT_DATA]
|
16
|
+
@transient_data_ui = ui_project[Blufin::Projects::TRANSIENT_DATA]
|
17
|
+
|
18
|
+
# TODO - This needs better data...
|
19
|
+
@data = js_data
|
20
|
+
|
21
|
+
target_file = "#{@project_path}/#{Blufin::Strings::remove_surrounding_slashes(@transient_data_ui[Blufin::Projects::CG_QUASAR_ROOT])}/#{Blufin::Strings::remove_surrounding_slashes(@transient_data_ui['JsDocsFile'])}"
|
22
|
+
|
23
|
+
# Write the file.
|
24
|
+
@overwritten << target_file if Blufin::Files::write_file_if_changed(target_file, Blufin::Arrays::convert_string_to_line_array(JSON.pretty_generate(@data, { indent: ' ' })), write_empty_trailing_line: true)
|
25
|
+
|
26
|
+
return @generated, @overwritten
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module EWorld
|
2
|
+
|
3
|
+
class RouteWriter < EWorld::BaseWriter
|
4
|
+
|
5
|
+
# Responsible for writing the routes.js file.
|
6
|
+
# @return void
|
7
|
+
def self.write(project, files_to_write)
|
8
|
+
|
9
|
+
raise RuntimeError, "Expected project type to be: #{Blufin::Projects::TYPE_QUASAR}, instead got: #{project[Blufin::Projects::TYPE]}" unless project[Blufin::Projects::TYPE] == Blufin::Projects::TYPE_QUASAR
|
10
|
+
@generated = []
|
11
|
+
@overwritten = []
|
12
|
+
|
13
|
+
begin
|
14
|
+
|
15
|
+
files_to_write.each do |file|
|
16
|
+
Blufin::Files::write_file(file, Blufin::Arrays::convert_string_to_line_array(get_blank_file_content))
|
17
|
+
@generated << file
|
18
|
+
end
|
19
|
+
|
20
|
+
rescue => e
|
21
|
+
|
22
|
+
Blufin::Terminal::print_exception(e)
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
return @generated, @overwritten
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
# Returns the contents of a blank file.
|
33
|
+
# @return string
|
34
|
+
def self.get_blank_file_content
|
35
|
+
<<TEMPLATE
|
36
|
+
<template>
|
37
|
+
<div>
|
38
|
+
<base-title h="5">{{ $route.meta.title }}</base-title>
|
39
|
+
</div>
|
40
|
+
</template>
|
41
|
+
|
42
|
+
<script>
|
43
|
+
export default {
|
44
|
+
data() {
|
45
|
+
return {};
|
46
|
+
}
|
47
|
+
};
|
48
|
+
</script>
|
49
|
+
|
50
|
+
<style scoped type="text/scss" lang="scss"></style>
|
51
|
+
TEMPLATE
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
module EWorld
|
2
|
+
|
3
|
+
class ServiceWriter < EWorld::BaseWriter
|
4
|
+
|
5
|
+
PACKAGE_NAME = 'services'
|
6
|
+
AUTOWIRED = '{{--AUTOWIRED--}}'
|
7
|
+
METHODS = '{{--METHODS--}}'
|
8
|
+
|
9
|
+
# Responsible for writing all the spring boot @RestController classes.
|
10
|
+
# @return void
|
11
|
+
def self.write(api_project, ui_project, controllers)
|
12
|
+
raise RuntimeError, "Expected project type to be: #{Blufin::Projects::TYPE_API_SIMPLE}, instead got: #{api_project[Blufin::Projects::TYPE]}" unless api_project[Blufin::Projects::TYPE] == Blufin::Projects::TYPE_API_SIMPLE
|
13
|
+
raise RuntimeError, "Expected project type to be: #{Blufin::Projects::TYPE_QUASAR}, instead got: #{ui_project[Blufin::Projects::TYPE]}" unless ui_project[Blufin::Projects::TYPE] == Blufin::Projects::TYPE_QUASAR
|
14
|
+
@generated = []
|
15
|
+
@overwritten = []
|
16
|
+
@project_path = Blufin::Projects::get_project_path(api_project[Blufin::Projects::PROJECT_ID])
|
17
|
+
@project_path_api = Blufin::Projects::get_project_path(api_project[Blufin::Projects::PROJECT_ID], true)
|
18
|
+
@project_path_ui = Blufin::Projects::get_project_path(ui_project[Blufin::Projects::PROJECT_ID], true)
|
19
|
+
@transient_data_api = api_project[Blufin::Projects::TRANSIENT_DATA]
|
20
|
+
@transient_data_ui = ui_project[Blufin::Projects::TRANSIENT_DATA]
|
21
|
+
@service_path = "#{EWorld::BaseWriter::get_java_path_for(@project_path, @transient_data_api['ServicePath'])}/#{PACKAGE_NAME}"
|
22
|
+
|
23
|
+
# Loop controllers.
|
24
|
+
controllers.each do |clazz, data|
|
25
|
+
write_java_service(clazz, data)
|
26
|
+
write_axios_service(clazz, data)
|
27
|
+
end
|
28
|
+
|
29
|
+
return @generated, @overwritten
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
# Write Java services.
|
36
|
+
# @return void
|
37
|
+
def self.write_java_service(clazz, data)
|
38
|
+
|
39
|
+
file = "#{@service_path}/#{clazz}Service.java"
|
40
|
+
|
41
|
+
methods = {}
|
42
|
+
|
43
|
+
# TODO NOW - Here we need to parse in the stuff from the java file scanner.
|
44
|
+
|
45
|
+
autowired_output = ''
|
46
|
+
methods_output = ''
|
47
|
+
|
48
|
+
if data.has_key?('EndPoints') && data['EndPoints'].is_a?(Array)
|
49
|
+
methods_output = "\n"
|
50
|
+
data['EndPoints'].each do |end_point|
|
51
|
+
method = end_point['Method'].downcase
|
52
|
+
method = method[0].upcase + method[1..-1]
|
53
|
+
path = end_point['Path'].downcase
|
54
|
+
camel_case = Blufin::Strings::snake_case_to_camel_case(path.gsub('-', '_'))
|
55
|
+
method_title = "#{method.downcase}#{camel_case}"
|
56
|
+
if methods.has_key?(method_title)
|
57
|
+
|
58
|
+
# TODO - Must scan file here ...
|
59
|
+
|
60
|
+
else
|
61
|
+
|
62
|
+
methods_output += <<TEMPLATE
|
63
|
+
|
64
|
+
public Object #{method_title}() {
|
65
|
+
|
66
|
+
return null;
|
67
|
+
}
|
68
|
+
TEMPLATE
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
methods.each do |method|
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
content = <<TEMPLATE
|
78
|
+
package #{PACKAGE}.core.#{PACKAGE_NAME};
|
79
|
+
|
80
|
+
import gov.hi.dhs.fmm.lib.rest.request.AbstractService;
|
81
|
+
import org.springframework.stereotype.Service;
|
82
|
+
|
83
|
+
@Service
|
84
|
+
public class #{CLASS}Service extends AbstractService {#{AUTOWIRED}#{METHODS}}
|
85
|
+
TEMPLATE
|
86
|
+
|
87
|
+
content = content.gsub(AUTOWIRED, autowired_output)
|
88
|
+
content = content.gsub(METHODS, methods_output)
|
89
|
+
content = content.gsub(PACKAGE, @transient_data_api['Package'])
|
90
|
+
content = content.gsub(CLASS, clazz)
|
91
|
+
|
92
|
+
Blufin::Files::write_file_java(file, Blufin::Arrays::convert_string_to_line_array(content), nil, false)
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
# Write Axios services.
|
97
|
+
# @return void
|
98
|
+
def self.write_axios_service(clazz, data)
|
99
|
+
|
100
|
+
# TODO - Overwrite Axios Service.
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|