class EWorld::RouteScanner
Constants
- CHILDREN
- CODE
- COMPONENT
- DISABLED
- FULLPATH
- HAS_PAGE
- ICON
- INVISIBLE
- META
- NAME
- PATH
- ROUTES
- SCHEMA_FILE
- TAB_PARENT
- TITLE
Public Class Methods
scan(project)
click to toggle source
Responsible for scanning the .codegen/routes/routes.yml file. @return Array
# File lib/scanners/route_scanner.rb, line 23 def self.scan(project) 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 @errors = [] @codes = [] @files = [] # Holds short version of file name. @files_expected = [] # Holds full-path to file. @files_to_write = [] # Holds list of files that need to be created/stubbed. begin @td = project[Blufin::Projects::TRANSIENT_DATA] @path_root = Blufin::Strings::remove_surrounding_slashes(@td[Blufin::Projects::CG_QUASAR_ROOT]) @path_routes_file = Blufin::Strings::remove_surrounding_slashes(@td[Blufin::Projects::CG_QUASAR_ROUTES_FILE]) @path_pages = Blufin::Strings::remove_surrounding_slashes(@td[Blufin::Projects::CG_QUASAR_PAGES]) @path_pages_ignore = @td[Blufin::Projects::CG_QUASAR_PAGES_IGNORE] @project_path = Blufin::Projects::get_project_path(project[Blufin::Projects::PROJECT_ID]) @project_path_inner = Blufin::Projects::get_project_path(project[Blufin::Projects::PROJECT_ID], true) routes_file = "#{@project_path_inner}/#{@path_routes_file}" # Make sure file exists. unless Blufin::Files::file_exists(routes_file) @errors << Blufin::ScannerError::add_error(nil, "File not found: #{Blufin::Terminal::format_invalid(routes_file)}") return {}, @errors end # Extract routes file content so we can parse/validate it. routes_content = [] Blufin::Files::read_file(routes_file).each do |line| line = line.gsub("\n", '').gsub(/^\s*const\s*routes\s*=\s*\[/, '{ Routes: [') # Handle component/import lines. if line =~ /^\s*component:\s*\(\)\s*=>\s*import\s*\(['"]\s*@/ line = line.gsub(/component:\s*\(\)\s*=>\s*import\s*\(['"]\s*@/, '') line = line.gsub(/['"]\s*\)\s*/, '') comma = (line == line.gsub(/,?\s*$/, '')) ? '' : ',' routes_content << "#{line.split('/')[0]}component: '#{line.gsub(/,?\s*$/, '').strip}'#{comma}" next end break if line =~ /^\s*if\s*\(/ routes_content << line unless line.strip == '' end # Remove trailing semi-colon. routes_content[routes_content.length - 1] = routes_content[routes_content.length - 1].gsub(/;*\s*$/, '') routes_content << '}' hash = {} eval("hash = #{Blufin::Arrays::convert_line_array_to_string(routes_content)}") json = JSON.parse(hash.to_json) # Create tmp file so we can read it. There might be a better way but no time. tmp_filename = "/tmp/routes-content-#{Blufin::Strings::random_string(2)}.yaml" # Write tmp file. Blufin::Files::write_file(tmp_filename, Blufin::Arrays::convert_string_to_line_array(json.to_yaml)) @routes_yml = Blufin::Yml::read_file(tmp_filename, SCHEMA_FILE) @routes_yml[ROUTES].each do |parent| parent_path = parent[PATH] parent_title = parent.has_key?(META) ? parent[META][TITLE] : nil parent_icon = parent.has_key?(META) ? parent[META][ICON] : nil parent_has_page = parent.has_key?(META) ? (parent[META][HAS_PAGE] ? true : false) : false parent_invisible = parent.has_key?(META) ? parent[META][INVISIBLE] : nil error_prefix = "Parent path: #{parent_path} \xe2\x80\x94 " # Make sure HAS_PAGE is only ever false. @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 # Make sure we have the correct meta properties for parent (based on invisible property). if parent_invisible @errors << Blufin::ScannerError::add_error(routes_file, "#{error_prefix}Invisible routes shouldn't have: icon") unless parent_icon.nil? else @errors << Blufin::ScannerError::add_error(routes_file, "#{error_prefix}Missing meta property: icon") if parent_icon.nil? end @errors << Blufin::ScannerError::add_error(routes_file, "#{error_prefix}Missing meta property: title") if parent_title.nil? # Make sure properties are in the correct order. expected = { PATH => true, META => false, COMPONENT => true, CHILDREN => false } Blufin::Validate::assert_valid_keys(expected, parent.keys, routes_file) # Make sure meta properties are in the correct order. if parent.has_key?(META) expected = { TITLE => false, ICON => false, HAS_PAGE => false, INVISIBLE => false } Blufin::Validate::assert_valid_keys(expected, parent[META].keys, routes_file) end # Make sure parent path(s) have a preceding slash. @errors << Blufin::ScannerError::add_error(routes_file, "#{error_prefix}Parent path must have preceding slash.") unless parent[PATH] =~ /^\// # Validate children, if they exist. validate_children(parent, Blufin::Strings::remove_surrounding_slashes(parent[PATH]), routes_file, error_prefix) if parent.has_key?(CHILDREN) end rescue => e Blufin::Terminal::print_exception(e) end # Check for rogue files. path_to_pages = "#{@project_path_inner}/#{@path_pages}" Blufin::Files::get_files_in_dir(path_to_pages).each do |file| next if file =~ /#{path_to_pages}\/(#{@path_pages_ignore.join('|')})\/[a-z0-9]/ unless @files_expected.include?(file.downcase) @errors << Blufin::ScannerError::add_error(routes_file, "Rogue file: #{file}") end end return @files_to_write, @errors end
Private Class Methods
validate_children(parent, parent_path, routes_file, error_prefix, validate_nested = true)
click to toggle source
Recursive function to validate children. @return void
# File lib/scanners/route_scanner.rb, line 133 def self.validate_children(parent, parent_path, routes_file, error_prefix, validate_nested = true) raise RuntimeError, "Expected key: #{CHILDREN}" unless parent.has_key?(CHILDREN) children = parent[CHILDREN] parent_has_page = parent.has_key?(META) ? (parent[META][HAS_PAGE] ? true : false) : false # Make sure we have an array with items. unless children.is_a?(Array) || children.length == 0 @errors << Blufin::ScannerError::add_error(routes_file, "#{error_prefix}Children must be an Array and cannot be empty.") return end children.each_with_index do |child, idx| # Make a more direct error prefix. error_prefix = "Route: #{child[NAME]} \xe2\x80\x94 " if child.has_key?(NAME) # Make sure properties are in the correct order. expected = { PATH => true, NAME => true, META => false, COMPONENT => true, CHILDREN => false } Blufin::Validate::assert_valid_keys(expected, child.keys, routes_file) # Make sure meta properties are in the correct order. if child.has_key?(META) expected = { FULLPATH => false, CODE => false, TITLE => false, ICON => false, TAB_PARENT => false, DISABLED => false, } Blufin::Validate::assert_valid_keys(expected, child[META].keys, routes_file) end # TODO - If non-tabs, must have FULLPATH, CODE, TITLE # TODO - If tabs, must have ICON, TAB_PARENT (AND TAB PARENT MUST MATCH PARENT). expected_name = Blufin::Strings::remove_surrounding_slashes("#{parent_path}/#{child[PATH]}").gsub('/', '-') # Handle special case for dashboard. expected_name = 'dashboard' if child[NAME] == 'dashboard' && expected_name.strip == '' expected_file = Blufin::Strings::remove_surrounding_slashes("#{parent_path}/#{child[PATH]}").split('/') raise RuntimeError, "Expected file count should never be greater than 3: #{expected_file.inspect}" if expected_file.length > 3 fullpath = '' if expected_file.length == 0 fullpath = expected_file[0] if expected_file.length == 1 fullpath = "#{expected_file[0]}/#{expected_file[1]}" if expected_file.length == 2 fullpath = "#{expected_file[0]}/#{expected_file[1]}/#{expected_file[2]}" if expected_file.length == 3 expected_file = '' if expected_file.length == 0 expected_file = expected_file[0] if expected_file.length == 1 expected_file = "#{expected_file[0]}/#{expected_file[1]}" if expected_file.length == 2 expected_file = "#{expected_file[0]}/#{expected_file[1]}-#{expected_file[2]}" if expected_file.length == 3 # Check full path is correct. @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 # Check the parent path. if idx == 0 if validate_nested @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] != '' @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 == '' # This handles the root paths, IE: 'dashboard/dashboard.vue' expected_file = "#{expected_name}/#{expected_name}" if parent_has_page else @errors << Blufin::ScannerError::add_error(routes_file, "#{error_prefix}Cannot have empty path.", "path: '#{child[PATH]}'") if child[PATH].strip == '' end else @errors << Blufin::ScannerError::add_error(routes_file, "#{error_prefix}Cannot have empty path.", "path: '#{child[PATH]}'") if child[PATH].strip == '' end expected_file = "/#{@path_pages}/#{Blufin::Strings::remove_surrounding_slashes(expected_file)}.vue" actual_file = "#{@project_path_inner}/#{Blufin::Strings::remove_surrounding_slashes(expected_file)}" # Make sure we don't have any duplicate files. if @files.include?(expected_file) @errors << Blufin::ScannerError::add_error(routes_file, "Duplicate file: #{expected_file}") else @files << expected_file @files_expected << actual_file.downcase end @files_to_write << actual_file unless Blufin::Files::file_exists(actual_file) @errors << Blufin::ScannerError::add_error(routes_file, "Expected name: #{expected_name}", "Got name: '#{child[NAME]}'") if child[NAME].strip != expected_name @errors << Blufin::ScannerError::add_error(routes_file, "Expected component: #{expected_file}", "Got component: '#{child[COMPONENT]}'") if child[COMPONENT].strip != expected_file # Make sure there are no duplicate codes. if child[META].has_key?(CODE) code = child[META][CODE] if @codes.include?(code) @errors << Blufin::ScannerError::add_error(routes_file, "Duplicate code: #{code}") else @codes << code end end # Validate nested children (if any). if child.has_key?(CHILDREN) unless validate_nested # This will probably never get hit, but just in case. @errors << Blufin::ScannerError::add_error(routes_file, "#{error_prefix}Cannot go more than 3 levels deep.") unless validate_nested return end validate_children(child, "#{parent_path}/#{child[PATH]}", routes_file, error_prefix, false) end end end