# frozen_string_literal: true module Lux extend self ENV_PROD = ENV['RACK_ENV'] == 'production' ENV_DEV = ENV['RACK_ENV'] == 'development' ENV_TEST = ENV['RACK_ENV'] == 'test' LUX_LIVE = ENV['LUX_LIVE'] == 'true' LUX_VERBOSE = ENV['LUX_VERBOSE'] == 'true' LUX_CLI = $0 == 'pry' || $0.index('/run.rb') || ENV['RACK_ENV'] == 'test' VERSION = File.read File.expand_path('../../../.version', __FILE__).chomp CONFIG ||= Hashie::Mash.new EVENTS ||= {} BACKGROUND_THREADS ||= [] Kernel.at_exit { BACKGROUND_THREADS.each { |t| t.join } } define_method(:prod?) { ENV_PROD } define_method(:dev?) { ENV_DEV } define_method(:test?) { ENV_TEST } define_method(:live?) { LUX_LIVE } # is on a live web server define_method(:verbose?) { LUX_VERBOSE } # show verbose output define_method(:cli?) { $0 == 'pry' || $0.index('/run.rb') || ENV['RACK_ENV'] == 'test' } def env(key=nil) return ENV['RACK_ENV'] unless key die "ENV['#{key}'] not found" if ENV[key].nil? ENV[key] end def config(key=nil) return CONFIG unless key die 'Lux.config.%s not found' % key if CONFIG[key].nil? CONFIG[key].kind_of?(Proc) ? CONFIG[key].call() : CONFIG[key] end def thread Thread.current[:lux] end def page Thread.current[:lux][:page] end def page=(what) Thread.current[:lux][:page] = what end def cache Lux::Cache end def root @@lux_app_root ||= Pathname.new(Dir.pwd).freeze end def fw_root @@lux_fw_root ||= Pathname.new(File.expand_path('../../', File.dirname(__FILE__))).freeze end def error data Lux::Error.show(data) end def log what return unless Lux.config(:log_to_stdout) puts what end def uid Thread.current[:uid_cnt] ||= 0 "uid-#{Thread.current[:uid_cnt]+=1}" end def on name, ref=nil, &proc EVENTS[name] ||= [] if block_given? puts "* event: #{name} defined".white EVENTS[name].push(proc) else for func in EVENTS[name] ref.instance_eval(&func) end end end # if block given, simple new thread bg job # if string given, eval it in bg # if object given, instance it and run it def delay *args if block_given? BACKGROUND_THREADS.push Thread.new { yield } elsif args[0] # Lux.delay(mail_object, :deliver) Lux::DelayedJob.push(*args) else Lux::DelayedJob end end def speed loops=1 render_start = Time.now loops.times { yield } num = ((Time.now-render_start)*1000).to_i.to_s num = num.sub(/(\d)(\d{3})$/,'\1s \2') num = "#{num}ms" loops == 1 ? num : "Done #{loops.to_s.sub(/(\d)(\d{3})$/,'\1s \2')} loops in #{num}" end def consumed_memory `ps -o rss -p #{$$}`.chomp.split("\n").last.to_i / 1000 end end # handy :) # renders full pages and exposes page object (req, res) in yiled # for easy and powerful testing # Hash :qs, Hash :post, String :method, Hash :cookies, Hash :session # https://github.com/rack/rack/blob/master/test/spec_request.rb def Lux(path, in_opts={}, &block) allowed_opts = [:qs, :post, :method, :session, :cookies] in_opts.keys.each { |k| die "#{k} is not allowed as opts param. allowed are #{allowed_opts}" unless allowed_opts.index(k) } opts = {} if in_opts[:post] opts[:query_string] = in_opts[:post] opts[:request_method] = :post else opts[:query_string] = in_opts[:qs] || {} opts[:request_method] ||= in_opts[:method] || :get end opts[:request_method] = opts[:request_method].to_s.upcase opts[:query_string] = opts[:query_string].to_query if opts[:query_string].class.to_s == 'Hash' if path[0,4] == 'http' parsed = URI.parse(path) opts[:server_name] = parsed.host opts[:server_port] = parsed.port path = '/'+path.split('/', 4).last end env = Rack::MockRequest.env_for(path) env[:input] = opts[:post] if opts[:post] for k,v in opts env[k.to_s.upcase] = v end page = Lux::Page.prepare(env) page.session = in_opts[:session] if in_opts[:session] return page.instance_exec &block if block_given? response = page.render body = response[2].join('') body = JSON.parse body if response[1]['content-type'].index('/json') { status: response[0], headers: response[1], body: body }.h end require_relative 'config/config'