lib/ember-cli/app.rb in ember-cli-rails-0.4.3 vs lib/ember-cli/app.rb in ember-cli-rails-0.5.0

- old
+ new

@@ -1,359 +1,111 @@ -require "timeout" -require "ember-cli/html_page" -require "ember-cli/asset_resolver" +require "ember-cli/shell" +require "ember-cli/sprockets" +require "ember-cli/build_monitor" module EmberCli class App - ADDON_VERSION = "0.0.13" - EMBER_CLI_VERSIONS = [ "~> 0.1.5", "~> 0.2.0", "~> 1.13" ] + attr_reader :name, :options, :paths - class BuildError < StandardError; end - - attr_reader :name, :options, :paths, :pid - - delegate :root, to: :paths - def initialize(name, **options) - @name, @options = name.to_s, options - @paths = PathSet.new(self) + @name = name.to_s + @options = options + @paths = PathSet.new( + app: self, + configuration: EmberCli.configuration, + environment: Rails.env, + rails_root: Rails.root, + ember_cli_root: EmberCli.root, + ) + @shell = Shell.new( + paths: @paths, + env: env_hash, + options: options, + ) + @build = BuildMonitor.new(name, @paths) end def compile @compiled ||= begin prepare - silence_build{ exec command } - check_for_build_error! + @shell.compile + @build.check! copy_index_html_file true end end - def install_dependencies - if gemfile_path.exist? - exec "#{bundler_path} install" - end - - exec "#{npm_path} prune && #{npm_path} install" - - if bower_path.nil? - fail <<-FAIL - Bower is required by EmberCLI - - Install it with: - - $ npm install -g bower - FAIL + def build + if EmberCli.env.development? + build_and_watch else - exec "#{bower_path} prune && #{bower_path} install" + compile end + + @build.wait! end - def run - prepare - FileUtils.touch lockfile_path - cmd = command(watch: true) - @pid = exec(cmd, method: :spawn) - Process.detach pid - copy_index_html_file - set_on_exit_callback + def install_dependencies + @shell.install end - def run_tests + def test prepare - exec("#{ember_path} test") + @shell.test end - def stop - Process.kill :INT, pid if pid - @pid = nil + def sprockets + EmberCli::Sprockets.new(self) end - def index_html(sprockets:, head:, body:) - asset_resolver = AssetResolver.new( - app: self, - sprockets: sprockets, - ) - html_page = HtmlPage.new( - asset_resolver: asset_resolver, - content: index_file.read, - head: head, - body: body, - ) - - html_page.render - end - - def exposed_js_assets - [vendor_assets, application_assets] - end - alias exposed_css_assets exposed_js_assets - - def vendor_assets - "#{name}/vendor" - end - - def application_assets - "#{name}/#{ember_app_name}" - end - - def wait - Timeout.timeout(build_timeout) do - wait_for_build_complete_or_error - end - rescue Timeout::Error - suggested_timeout = build_timeout + 5 - - warn <<-MSG.strip_heredoc - ============================= WARNING! ============================= - - Seems like Ember #{name} application takes more than #{build_timeout} - seconds to compile. - - To prevent race conditions consider adjusting build timeout - configuration in your ember initializer: - - EmberCLI.configure do |config| - config.build_timeout = #{suggested_timeout} # in seconds - end - - Alternatively, you can set build timeout per application like this: - - EmberCLI.configure do |config| - config.app :#{name}, build_timeout: #{suggested_timeout} - end - - ============================= WARNING! ============================= - MSG - end - - def method_missing(method_name, *) - if path_method = supported_path_method(method_name) - paths.public_send(path_method) + def index_file + if EmberCli.env.production? + paths.applications.join("#{name}.html") else - super + paths.dist.join("index.html") end end - def respond_to_missing?(method_name, *) - if supported_path_method(method_name) - true - else - super - end - end - private - def set_on_exit_callback - @on_exit_callback ||= at_exit{ stop } + def build_and_watch + prepare + @shell.build_and_watch + copy_index_html_file end - def supported_path_method(original) - path_method = original.to_s[/\A(.+)_path\z/, 1] - path_method if path_method && paths.respond_to?(path_method) - end - - def silence_build(&block) - if ENV.fetch("EMBER_CLI_RAILS_VERBOSE") { EmberCli.env.production? } - yield - else - silence_stream STDOUT, &block - end - end - - def build_timeout - options.fetch(:build_timeout) { EmberCli.configuration.build_timeout } - end - - def watcher - options.fetch(:watcher) { EmberCli.configuration.watcher } - end - - def check_for_build_error! - raise_build_error! if build_error? - end - - def reset_build_error! - build_error_file_path.delete if build_error? - end - - def build_error? - build_error_file_path.exist? && build_error_file_path.size? - end - - def raise_build_error! - error = BuildError.new("EmberCLI app #{name.inspect} has failed to build") - error.set_backtrace build_error_file_path.readlines - fail error - end - def prepare @prepared ||= begin - check_dependencies! - check_addon! - check_ember_cli_version! - reset_build_error! + @build.reset symlink_to_assets_root - add_assets_to_precompile_list + sprockets.register! true end end - def check_ember_cli_version! - version = dev_dependencies.fetch("ember-cli").split(?-).first - - unless Helpers.match_version?(version, EMBER_CLI_VERSIONS) - fail <<-MSG.strip_heredoc - EmberCLI Rails require ember-cli NPM package version to be - #{EMBER_CLI_VERSIONS.last} to work properly (you have #{version}). - From within your EmberCLI directory please update your package.json - accordingly and run: - - $ npm install - - MSG - end - end - - def check_addon! - unless addon_present? - fail <<-MSG.strip_heredoc - EmberCLI Rails requires your Ember app to have an addon. - - From within your EmberCLI directory please run: - - $ npm install --save-dev ember-cli-rails-addon@#{ADDON_VERSION} - - in your Ember application root: #{root} - MSG - end - end - - def check_dependencies! - unless node_modules_present? - fail <<-MSG.strip_heredoc - EmberCLI app dependencies are not installed. From your Rails application root please run: - - $ bundle exec rake ember:install - - If you do not require Ember at this URL, you can restrict this check using the `enable` - option in the EmberCLI initializer. - MSG - end - end - - def assets_path - paths.assets.join(name) - end - def copy_index_html_file - if environment == "production" - FileUtils.cp(assets_path.join("index.html"), index_file) + if EmberCli.env.production? + FileUtils.cp(paths.app_assets.join("index.html"), index_file) end end - def index_file - if environment == "production" - applications_path.join("#{name}.html") - else - dist_path.join("index.html") - end - end - def symlink_to_assets_root - assets_path.make_symlink dist_path.join("assets") + paths.app_assets.make_symlink paths.dist rescue Errno::EEXIST # Sometimes happens when starting multiple Unicorn workers. # Ignoring... end - def add_assets_to_precompile_list - Rails.configuration.assets.precompile << /\A#{name}\// - end - - def command(watch: false) - watch_flag = "" - - if watch - watch_flag = "--watch" - - if watcher - watch_flag += " --watcher #{watcher}" - end - end - - "#{ember_path} build #{watch_flag} --environment #{environment} --output-path #{dist_path} #{redirect_errors} #{log_pipe}" - end - - def redirect_errors - "2> #{build_error_file_path}" - end - - def log_pipe - "| #{tee_path} -a #{log_path}" if tee_path - end - - def ember_app_name - @ember_app_name ||= options.fetch(:name){ package_json.fetch(:name) } - end - - def environment - EmberCli.env.production? ? "production" : "development" - end - - def package_json - @package_json ||= - JSON.parse(package_json_file_path.read).with_indifferent_access - end - - def addon_package_json - @addon_package_json ||= - JSON.parse(addon_package_json_file_path.read).with_indifferent_access - end - - def addon_version - addon_package_json.fetch("version") - end - - def dev_dependencies - package_json.fetch("devDependencies", {}) - end - - def addon_present? - addon_package_json_file_path.exist? && - addon_version == ADDON_VERSION - end - - def node_modules_present? - node_modules_path.exist? - end - def excluded_ember_deps Array.wrap(options[:exclude_ember_deps]).join(?,) end def env_hash ENV.to_h.tap do |vars| vars["RAILS_ENV"] = Rails.env - vars["DISABLE_FINGERPRINTING"] = "true" vars["EXCLUDE_EMBER_ASSETS"] = excluded_ember_deps - vars["BUNDLE_GEMFILE"] = gemfile_path.to_s if gemfile_path.exist? - end - end - - def exec(cmd, method: :system) - Dir.chdir root do - Kernel.public_send(method, env_hash, cmd, err: :out) || exit(1) - end - end - - def wait_for_build_complete_or_error - loop do - check_for_build_error! - break unless lockfile_path.exist? - sleep 0.1 + vars["BUNDLE_GEMFILE"] = paths.gemfile.to_s if paths.gemfile.exist? end end end end