#!/usr/bin/env ruby require_relative '../lib/flok' require 'thor' require 'fileutils' require 'webrick' require_relative '../spec/lib/helpers.rb' class FlokCLI < Thor desc "new ", "Create a new flok project and/or module, you may supply an absolute path or relative, the last entry in the path will be the module name and folder name of the project" def new path #Name of this project name = File.basename(path) #Get the directory of the given path, if path is only 'foo', then this will go into '.' (nop) Dir.chdir File.dirname(path) do Flok::Project.create name end end desc "build", "Build the products for a platform" def build raise "$PLATFORM was not set" unless ENV['PLATFORM'] platform = ENV['PLATFORM'] #Set the correct config.yml ENV['FLOK_CONFIG'] = File.expand_path("./config/platforms/#{platform}/config.yml") #Create a products folder if it dosen't already exist FileUtils.rm_r "./products" if File.directory? "./products" Dir.mkdir("./products") unless File.exists?("./products") #Go into the flok gem project local_products_path = File.join(Dir.pwd, "products") Dir.chdir(File.join(File.dirname(__FILE__), "../")) do #1. Use the rake task system('rake build:world') #2. Copy everything in the gems ./flok/products/$PLATFORM -> $PROJECT/products/$PLATFORM and ./flok/app/kern/services/*.rb -> #$PROJECT/products/$PLATFORM/services FileUtils.cp_r "./products/#{platform}", local_products_path #Copy built in services Flok.src_glob("rb", "./app/kern/services", File.join(local_products_path, platform, "services/kern_services.rb")) end #3. Build the client's ./app/controllers/*.rb into './products/$PLATFORM/user_compiler.js' controller_glob_path = "#{local_products_path}/#{platform}/glob/controllers.rb" Flok.src_glob_r("rb", './app/controllers', controller_glob_path) user_compiler_js = Flok::UserCompiler.compile File.read(controller_glob_path) services_config_js = File.read "./config/services.rb" Flok.src_glob("rb", './app/services', File.join(local_products_path, platform, "./services/user_services.rb")) #4. Move ./app/scripts/*.js into `./products/$PLATFORM/./glob/scripts.js` Flok.src_glob("js", './app/scripts', File.join(local_products_path, platform, "./glob/scripts.js")) #Save the current local user's project directory to reference user_project_dir = Dir.pwd #We are now inside the platform folder Dir.chdir File.join(local_products_path, platform) do #3. Put user_compiler_js in glob folder and services into ./services/user_services.rb File.write "glob/user_compiler.js", user_compiler_js #4. The `./products/$PLATFORM/services/*.rb` file are globbed into `./products/$PLATFORM/services/combined_services.rb` Flok.src_glob("rb", "./services/", "./services/combined_services.rb") #5. The service configuration in `./config/services.rb` is read and run through `services_compiler` and files from `./products/$PLATFORM/services/combined_services.rb` and write to ./glob/services.js services_js = Flok::ServicesCompiler.compile(File.read("./services/combined_services.rb"), services_config_js) File.write "./glob/services.js", services_js #6. Move application.js to the glob folder FileUtils.cp "application.js", "glob/application.js" FileUtils.rm "application.js" #7. The local project `./products/$PLATFORM/glob/application.js` and `./products/$PLATFORM/glob/user_compiler.js` and `./products/$PLATFORM/glob/services.js` and `./products/$PLATFORM/glob/scripts.js` are merged into `./products/$PLATFORM/glob/application_user.js.erb.hooks`. File.open "glob/application_user.js.erb.hooks", "w" do |f| f.puts File.read("glob/application.js") f.puts File.read("glob/user_compiler.js") f.puts File.read("glob/services.js") f.puts File.read("glob/scripts.js") end #9. The `hooks` compiler then runs over the source injecting any necessary hook code into the special comments by going through `./config/hooks.rb` in the user's project. erb_hooks_src = File.read "glob/application_user.js.erb.hooks" manifest = Flok::UserHooksToManifestOrchestrator.convert_hooks_to_manifest File.read("#{user_project_dir}/config/hooks.rb") erb_src = Flok::HooksCompiler.compile erb_hooks_src, manifest File.write "glob/application_user.js.erb", erb_src #9. The `erb` files is then sent to `./products/$PLATFORM/glob/application_user.js` with the below `ERB` variables allowable. erb_src = File.read "glob/application_user.js.erb" renderr = ERB.new(erb_src) context = ERBUserApplicationContext.new() new_src = renderr.result(context.get_binding) File.write "application_user.js", new_src end end desc "server", "Monitors for changes within your flok application and triggers an automatic rebuild of ./products/* for a PLATFORM when something in ./app changes" include SpecHelpers #Contains sh2 def server raise "$PLATFORM was not set" unless ENV['PLATFORM'] platform = ENV['PLATFORM'] #Ensure puts does something because it's on another thread $stdout.sync = true begin @pid = fork do server = WEBrick::HTTPServer.new :Port => 9992, :DocumentRoot => ".", :StartCallback => Proc.new { puts "SERVER STARTED" } @build_q = Queue.new @build_q.push 0 server.mount_proc "/" do |req, res| #Semaphore for build; multiple requests execute 1 build unless @build_q.empty? @build_q.pop _res = system("#{__FILE__} build") @build_q.push 0 else @build_q.pop @build_q.push 0 _res = true end $stderr.puts "res = #{_res}" #/products/application_user.js, etc. local path with dot path = "./products/#{platform}/#{req.path}" if _res == true res.body = File.read(path) else res.body = "" end res.header["Access-Control-Allow-Origin"] = "*" #res.header["Content-Type"] = "json/text" end server.start end loop do sleep 1 end ensure Process.kill :KILL, @pid end end #Part of the build command class ERBUserApplicationContext def get_binding return binding end def initialize #Debug / Release @debug = (ENV['FLOK_ENV'] == "DEBUG") @release = (ENV['FLOK_ENV'] == "RELEASE") end end end FlokCLI.start(ARGV)