lux-fw 0.2.3 → 0.5.32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.version +1 -1
- data/bin/README.md +33 -0
- data/bin/build_gem +76 -0
- data/bin/cli/config.rb +44 -0
- data/bin/cli/console.rb +61 -0
- data/bin/cli/dbconsole.rb +8 -0
- data/bin/cli/eval.rb +32 -0
- data/bin/cli/generate.rb +88 -0
- data/bin/cli/get.rb +12 -0
- data/bin/cli/new.rb +22 -0
- data/bin/cli/routes.rb +90 -0
- data/bin/cli/secrets.rb +40 -0
- data/bin/cli/server.rb +24 -0
- data/bin/cli/stats.rb +133 -0
- data/bin/lux +24 -65
- data/lib/common/class_attributes.rb +40 -64
- data/lib/common/class_callbacks.rb +34 -51
- data/lib/common/crypt.rb +10 -8
- data/lib/common/free_struct.rb +42 -0
- data/lib/common/hash_with_indifferent_access.rb +1 -1
- data/lib/common/html_tag_builder.rb +26 -2
- data/lib/common/url.rb +58 -40
- data/lib/lux/application/application.rb +290 -117
- data/lib/lux/application/lib/nav.rb +64 -38
- data/lib/lux/application/lib/render.rb +2 -1
- data/lib/lux/cache/cache.rb +87 -62
- data/lib/lux/cache/lib/{ram.rb → memory.rb} +5 -7
- data/lib/lux/cache/lib/null.rb +6 -8
- data/lib/lux/config/config.rb +109 -52
- data/lib/lux/config/lib/plugin.rb +65 -0
- data/lib/lux/config/lib/secrets.rb +48 -0
- data/lib/lux/controller/controller.rb +241 -0
- data/lib/lux/current/current.rb +33 -47
- data/lib/lux/current/lib/session.rb +72 -0
- data/lib/lux/delayed_job/delayed_job.rb +14 -7
- data/lib/lux/delayed_job/lib/memory.rb +7 -5
- data/lib/lux/delayed_job/lib/redis.rb +1 -1
- data/lib/lux/error/error.rb +164 -62
- data/lib/lux/event_bus/event_bus.rb +27 -0
- data/lib/lux/lux.rb +103 -66
- data/lib/lux/mailer/mailer.rb +23 -25
- data/lib/lux/response/lib/file.rb +81 -0
- data/lib/lux/response/lib/header.rb +14 -1
- data/lib/lux/response/response.rb +64 -56
- data/lib/lux/view/cell.rb +102 -0
- data/lib/lux/{helper → view}/helper.rb +39 -23
- data/lib/lux/view/lib/cell_helpers.rb +29 -0
- data/lib/lux/{helper/helpers/mailer_helper.rb → view/lib/helper_modules.rb} +7 -1
- data/lib/lux/{template/template.rb → view/view.rb} +21 -24
- data/lib/lux-fw.rb +4 -2
- data/lib/overload/array.rb +12 -6
- data/lib/overload/blank.rb +0 -1
- data/lib/overload/dir.rb +18 -0
- data/lib/overload/file.rb +1 -6
- data/lib/overload/hash.rb +56 -13
- data/lib/overload/integer.rb +2 -2
- data/lib/overload/it.rb +4 -4
- data/lib/overload/object.rb +37 -8
- data/lib/overload/{r.rb → raise_variants.rb} +23 -4
- data/lib/overload/string.rb +22 -6
- data/misc/demo/app/cells/demo_cell.rb +12 -0
- data/misc/demo/app/controllers/application_controller.rb +7 -0
- data/misc/demo/app/controllers/main/root_controller.rb +9 -0
- data/misc/demo/app/routes.rb +5 -0
- data/misc/demo/config/application.rb +14 -0
- data/misc/demo/config/assets.rb +6 -0
- data/misc/demo/config/environment.rb +7 -0
- data/misc/puma_auto_tune.rb +43 -0
- data/misc/unicorn.rb +37 -0
- data/{lib/lux → plugins}/api/api.rb +46 -29
- data/plugins/api/lib/attr.rb +31 -0
- data/{lib/lux → plugins}/api/lib/dsl.rb +3 -6
- data/{lib/lux → plugins}/api/lib/error.rb +0 -0
- data/{lib/lux → plugins}/api/lib/model_api.rb +51 -12
- data/{lib/lux → plugins}/api/lib/response.rb +31 -17
- data/{bin/cli/am → plugins/db/auto_migrate/auto_migrate.rb} +18 -35
- data/plugins/db/helpers/array_search.rb +27 -0
- data/plugins/db/helpers/before_save_filters.rb +32 -0
- data/plugins/db/helpers/composite_primary_keys.rb +36 -0
- data/plugins/db/helpers/core.rb +94 -0
- data/plugins/db/helpers/dataset_methods.rb +138 -0
- data/plugins/db/helpers/enums_plugin.rb +52 -0
- data/plugins/db/helpers/find_precache.rb +31 -0
- data/plugins/db/helpers/link_objects.rb +84 -0
- data/plugins/db/helpers/schema_checks.rb +83 -0
- data/plugins/db/helpers/typero_adapter.rb +71 -0
- data/plugins/db/logger/config.rb +22 -0
- data/plugins/db/logger/lux_response_adapter.rb +10 -0
- data/plugins/db/paginate/helper.rb +32 -0
- data/plugins/db/paginate/sequel_adapter.rb +23 -0
- data/plugins/exceptions/simple_exception.rb +64 -0
- data/plugins/favicon/favicon.rb +10 -0
- data/plugins/html/html_form.rb +118 -0
- data/plugins/html/html_input.rb +98 -0
- data/plugins/html/html_menu.rb +79 -0
- data/plugins/html/input_types.rb +346 -0
- data/plugins/js_widgets/js_widgets.rb +15 -0
- data/plugins/oauth/lib/facebook.rb +35 -0
- data/plugins/oauth/lib/github.rb +38 -0
- data/plugins/oauth/lib/google.rb +41 -0
- data/plugins/oauth/lib/linkedin.rb +41 -0
- data/plugins/oauth/lib/stackexchange.rb +41 -0
- data/plugins/oauth/lib/twitter.rb +38 -0
- data/plugins/oauth/oauth.rb +42 -0
- data/{lib/common → plugins/policy}/policy.rb +6 -7
- data/tasks/loader.rb +49 -0
- metadata +151 -49
- data/bin/cli/assets +0 -41
- data/bin/cli/console +0 -51
- data/bin/cli/dev +0 -1
- data/bin/cli/eval +0 -24
- data/bin/cli/exceptions +0 -62
- data/bin/cli/generate +0 -86
- data/bin/cli/get +0 -5
- data/bin/cli/nginx +0 -34
- data/bin/cli/production +0 -1
- data/bin/cli/render +0 -18
- data/bin/cli/routes +0 -14
- data/bin/cli/server +0 -4
- data/bin/cli/stat +0 -1
- data/bin/cli/systemd +0 -36
- data/bin/txt/nginx.conf +0 -46
- data/bin/txt/siege-and-puma.txt +0 -3
- data/lib/common/base32.rb +0 -47
- data/lib/common/dynamic_class.rb +0 -28
- data/lib/common/folder_model.rb +0 -50
- data/lib/common/generic_model.rb +0 -62
- data/lib/lux/application/lib/plugs.rb +0 -10
- data/lib/lux/application/lib/route_test.rb +0 -64
- data/lib/lux/cache/lib/memcached.rb +0 -3
- data/lib/lux/cell/cell.rb +0 -261
- data/lib/lux/current/lib/static_file.rb +0 -103
- data/lib/lux/helper/helpers/application_helper.rb +0 -3
- data/lib/lux/helper/helpers/html_helper.rb +0 -3
- data/lib/overload/auto_loader.rb +0 -27
- data/lib/overload/module.rb +0 -10
- data/lib/overload/string_inflections.rb +0 -8
data/lib/lux/error/error.rb
CHANGED
@@ -1,91 +1,193 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
#
|
4
|
-
|
3
|
+
# https://en.wikipedia.org/wiki/List_of_HTTP_status_codes
|
4
|
+
|
5
|
+
# default error handler for lux
|
6
|
+
# e = Lux::Error.new 404
|
7
|
+
# e.code => 404
|
8
|
+
# e.message => 'Not Found'
|
9
|
+
#
|
10
|
+
# e = Lux::Error.not_found('foo')
|
11
|
+
# e.code => 404
|
12
|
+
# e.message => foo
|
13
|
+
|
14
|
+
class Lux::Error < StandardError
|
15
|
+
class AutoRaise < Lux::Error
|
16
|
+
end
|
5
17
|
|
6
|
-
#
|
7
|
-
|
18
|
+
# https://httpstatuses.com/
|
19
|
+
CODE_LIST ||= {
|
20
|
+
# 1×× Informational
|
21
|
+
100 => { name: 'Continue' },
|
22
|
+
101 => { name: 'Switching Protocols' },
|
23
|
+
102 => { name: 'Processing' },
|
24
|
+
|
25
|
+
# 2×× Success
|
26
|
+
200 => { name: 'OK' },
|
27
|
+
201 => { name: 'Created' },
|
28
|
+
202 => { name: 'Accepted' },
|
29
|
+
203 => { name: 'Non-authoritative Information' },
|
30
|
+
204 => { name: 'No Content' },
|
31
|
+
205 => { name: 'Reset Content' },
|
32
|
+
206 => { name: 'Partial Content' },
|
33
|
+
207 => { name: 'Multi-Status' },
|
34
|
+
208 => { name: 'Already Reported' },
|
35
|
+
226 => { name: 'IM Used' },
|
36
|
+
|
37
|
+
# 3×× Redirection
|
38
|
+
300 => { name: 'Multiple Choices' },
|
39
|
+
301 => { name: 'Moved Permanently' },
|
40
|
+
302 => { name: 'Found' },
|
41
|
+
303 => { name: 'See Other' },
|
42
|
+
304 => { name: 'Not Modified' },
|
43
|
+
305 => { name: 'Use Proxy' },
|
44
|
+
307 => { name: 'Temporary Redirect' },
|
45
|
+
308 => { name: 'Permanent Redirect' },
|
46
|
+
|
47
|
+
# 4×× Client Error
|
48
|
+
400 => { name: 'Bad Request', code: :bad_request },
|
49
|
+
401 => { name: 'Unauthorized', code: :unauthorized },
|
50
|
+
402 => { name: 'Payment Required', code: :payment_required },
|
51
|
+
403 => { name: 'Forbidden', code: :forbidden },
|
52
|
+
404 => { name: 'Document Not Found', code: :not_found },
|
53
|
+
405 => { name: 'Method Not Allowed', code: :method_not_allowed },
|
54
|
+
406 => { name: 'Not Acceptable', code: :not_acceptable },
|
55
|
+
407 => { name: 'Proxy Authentication Required' },
|
56
|
+
408 => { name: 'Request Timeout' },
|
57
|
+
409 => { name: 'Conflict' },
|
58
|
+
410 => { name: 'Gone' },
|
59
|
+
411 => { name: 'Length Required' },
|
60
|
+
412 => { name: 'Precondition Failed' },
|
61
|
+
413 => { name: 'Payload Too Large' },
|
62
|
+
414 => { name: 'Request-URI Too Long' },
|
63
|
+
415 => { name: 'Unsupported Media Type' },
|
64
|
+
416 => { name: 'Requested Range Not Satisfiable' },
|
65
|
+
417 => { name: 'Expectation Failed' },
|
66
|
+
418 => { name: 'I\'m a teapot' },
|
67
|
+
421 => { name: 'Misdirected Request' },
|
68
|
+
422 => { name: 'Unprocessable Entity' },
|
69
|
+
423 => { name: 'Locked' },
|
70
|
+
424 => { name: 'Failed Dependency' },
|
71
|
+
426 => { name: 'Upgrade Required' },
|
72
|
+
428 => { name: 'Precondition Required' },
|
73
|
+
429 => { name: 'Too Many Requests' },
|
74
|
+
431 => { name: 'Request Header Fields Too Large' },
|
75
|
+
444 => { name: 'Connection Closed Without Response' },
|
76
|
+
451 => { name: 'Unavailable For Legal Reasons' },
|
77
|
+
499 => { name: 'Client Closed Request' },
|
78
|
+
|
79
|
+
# 5×× Server Error
|
80
|
+
500 => { name: 'Internal Server Error', code: :internal_server_error },
|
81
|
+
501 => { name: 'Not Implemented', code: :not_implemented },
|
82
|
+
502 => { name: 'Bad Gateway' },
|
83
|
+
503 => { name: 'Service Unavailable' },
|
84
|
+
504 => { name: 'Gateway Timeout' },
|
85
|
+
505 => { name: 'HTTP Version Not Supported' },
|
86
|
+
506 => { name: 'Variant Also Negotiates' },
|
87
|
+
507 => { name: 'Insufficient Storage' },
|
88
|
+
508 => { name: 'Loop Detected' },
|
89
|
+
510 => { name: 'Not Extended' },
|
90
|
+
511 => { name: 'Network Authentication Required' },
|
91
|
+
599 => { name: 'Network Connect Timeout Error' },
|
92
|
+
}
|
93
|
+
|
94
|
+
# e = Lux::Error.not_found('foo')
|
95
|
+
CODE_LIST.each do |status, data|
|
96
|
+
if data[:code]
|
97
|
+
define_singleton_method(data[:code]) do |message=nil|
|
98
|
+
error = new status, message
|
99
|
+
raise error if Lux::Error::AutoRaise === error
|
100
|
+
error
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
8
104
|
|
9
|
-
|
10
|
-
|
105
|
+
class << self
|
106
|
+
# template to show full error page
|
107
|
+
def render text, status=500
|
108
|
+
Lux.current.response.status status
|
109
|
+
Lux.current.response.body Lux.config.server_error_template.call(text)
|
110
|
+
throw :done
|
111
|
+
end
|
11
112
|
|
12
|
-
#
|
13
|
-
|
113
|
+
# render error inline or break in production
|
114
|
+
def inline name, error=nil
|
115
|
+
error ||= $!
|
14
116
|
|
15
|
-
|
16
|
-
|
117
|
+
unless Lux.config(:dump_errors)
|
118
|
+
key = log error
|
119
|
+
render "Lux inline error: %s\n\nkey: %s" % [error.message, key]
|
120
|
+
end
|
17
121
|
|
18
|
-
|
19
|
-
|
122
|
+
name ||= 'Undefined name'
|
123
|
+
msg = error.message.to_s.gsub('","',%[",\n "]).gsub('<','<')
|
20
124
|
|
21
|
-
|
22
|
-
begin
|
23
|
-
yield
|
24
|
-
rescue Exception => e
|
25
|
-
Lux.current.response.status 500
|
125
|
+
dmp = split_backtrace error
|
26
126
|
|
27
|
-
|
127
|
+
dmp[0] = dmp[0].map { |_| _ = _.split(':', 3); '<b>%s</b> - %s - %s' % _ }
|
28
128
|
|
29
|
-
|
30
|
-
inline name
|
31
|
-
else
|
32
|
-
name ||= 'Server error occured'
|
33
|
-
name += "\n\nkey: %s" % key
|
129
|
+
log error
|
34
130
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
end
|
131
|
+
<<~TEXT
|
132
|
+
<pre style="color:red; background:#eee; padding:10px; font-family:'Lucida Console'; line-height:15pt; font-size:11pt;">
|
133
|
+
<b style="font-size:110%;">#{name}</b>
|
39
134
|
|
40
|
-
|
41
|
-
%[<html><head><title>Server error (#{Lux.current.response.status})</title></head><body style="background:#fdd;"><pre style="color:red; padding:10px; font-size:14pt;">#{data.gsub('<','<')}</pre></body></html>]
|
42
|
-
end
|
135
|
+
<b>#{error}: #{msg}</b>
|
43
136
|
|
44
|
-
|
45
|
-
Lux.current.response.status 500
|
46
|
-
data = "Lux #{Lux.current.response.status} error\n\n#{desc}"
|
47
|
-
Lux.current.response.body! render(data)
|
48
|
-
end
|
137
|
+
#{dmp[0].join("\n")}
|
49
138
|
|
50
|
-
|
51
|
-
|
139
|
+
#{dmp[1].join("\n")}
|
140
|
+
</pre>
|
141
|
+
TEXT
|
142
|
+
end
|
52
143
|
|
53
|
-
|
144
|
+
def report code, msg=nil
|
145
|
+
e = Integer === code ? Lux::Error.new(code) : Lux::Error.send(code)
|
146
|
+
e.message = msg if msg
|
147
|
+
raise e
|
148
|
+
end
|
54
149
|
|
55
|
-
|
56
|
-
|
57
|
-
dmp[line.include?('/app/') ? 0 : 1].push line
|
150
|
+
def log error
|
151
|
+
Lux.config.error_logger.call error
|
58
152
|
end
|
59
153
|
|
60
|
-
|
154
|
+
def split_backtrace error
|
155
|
+
# split app log rest of the log
|
156
|
+
dmp = [[], []]
|
61
157
|
|
62
|
-
|
63
|
-
msg = $!.to_s.gsub('","',%[",\n "]).gsub('<','<')
|
158
|
+
root = Lux.root.to_s
|
64
159
|
|
65
|
-
|
160
|
+
error.backtrace.each do |line|
|
161
|
+
line = line.sub(root, '.')
|
162
|
+
dmp[line[0,1] == '.' ? 0 : 1].push line
|
163
|
+
end
|
164
|
+
|
165
|
+
dmp
|
166
|
+
end
|
66
167
|
end
|
67
168
|
|
68
|
-
|
69
|
-
return if Lux.env == 'test'
|
70
|
-
return if exception.class == LocalRaiseError
|
71
|
-
return unless Lux.current
|
169
|
+
###
|
72
170
|
|
73
|
-
|
74
|
-
history = exception.backtrace
|
75
|
-
.map{ |el| el.sub(Lux.root.to_s, '') }
|
76
|
-
.join("\n")
|
171
|
+
attr_accessor :message
|
77
172
|
|
78
|
-
|
79
|
-
|
80
|
-
|
173
|
+
def initialize code_num, message=nil
|
174
|
+
self.code = code_num
|
175
|
+
@message = message || CODE_LIST[code_num][:name]
|
176
|
+
end
|
81
177
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
178
|
+
def code
|
179
|
+
# 400 is a default
|
180
|
+
@code || 400
|
181
|
+
end
|
86
182
|
|
87
|
-
|
183
|
+
def code= num
|
184
|
+
@code = num.to_i
|
88
185
|
|
89
|
-
|
186
|
+
raise 'Status code %s not found' % @code unless CODE_LIST[@code]
|
187
|
+
end
|
188
|
+
|
189
|
+
def render
|
190
|
+
self.class.render message, code
|
90
191
|
end
|
91
192
|
end
|
193
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# EventBus.on('test') { |arg| puts 'jedan: %s' % arg }
|
2
|
+
# EventBus.on('test') { |arg| puts 'dva: %s' % arg }
|
3
|
+
# EventBus.on('test') { |arg| raise 'abc' }
|
4
|
+
# EventBus.call 'test', 'xxx'
|
5
|
+
|
6
|
+
module Lux::EventBus
|
7
|
+
extend self
|
8
|
+
|
9
|
+
EVENTS = {}
|
10
|
+
|
11
|
+
def on name, key=nil, &proc
|
12
|
+
key ||= caller[0].split(':in ').first.gsub(/[^\w]/,'')
|
13
|
+
|
14
|
+
EVENTS[name] ||= {}
|
15
|
+
EVENTS[name][key] ||= proc
|
16
|
+
end
|
17
|
+
|
18
|
+
def call name, opts=nil
|
19
|
+
for func in EVENTS[name].values
|
20
|
+
begin
|
21
|
+
func.call opts
|
22
|
+
rescue => error
|
23
|
+
Lux.config.on_event_bus_error.call error, name
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/lux/lux.rb
CHANGED
@@ -1,50 +1,68 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../common/class_callbacks
|
3
|
+
require_relative '../common/class_callbacks'
|
4
|
+
require_relative 'cache/cache'
|
4
5
|
|
5
|
-
module Lux
|
6
|
+
module ::Lux
|
6
7
|
extend self
|
7
8
|
|
8
|
-
ENV_PROD
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
9
|
+
ENV_PROD = ENV['RACK_ENV'] == 'production' unless defined?(ENV_PROD)
|
10
|
+
CACHE_SERVER ||= Lux::Cache.new
|
11
|
+
VERSION ||= File.read File.expand_path('../../../.version', __FILE__).chomp
|
12
|
+
CONFIG ||= Hashie::Mash.new
|
13
|
+
APP_ROOT ||= Pathname.new(Dir.pwd).freeze
|
14
|
+
FW_ROOT ||= Pathname.new(File.expand_path('../../', File.dirname(__FILE__))).freeze
|
15
|
+
EVENTS ||= {}
|
16
|
+
MCACHE ||= {}
|
16
17
|
|
17
18
|
BACKGROUND_THREADS ||= []
|
18
|
-
Kernel.at_exit { BACKGROUND_THREADS.each { |t| t.join } }
|
19
|
-
|
20
|
-
define_method(:
|
21
|
-
define_method(:
|
22
|
-
define_method(:
|
23
|
-
define_method(:
|
24
|
-
define_method(:
|
25
|
-
define_method(:
|
19
|
+
# Kernel.at_exit { BACKGROUND_THREADS.each { |t| t.join } }
|
20
|
+
|
21
|
+
define_method(:cli?) { !@rackup_start }
|
22
|
+
define_method(:test?) { ENV['RACK_ENV'] == 'test' }
|
23
|
+
define_method(:prod?) { ENV_PROD }
|
24
|
+
define_method(:production?) { ENV_PROD }
|
25
|
+
define_method(:dev?) { !ENV_PROD }
|
26
|
+
define_method(:development?) { !ENV_PROD }
|
27
|
+
define_method(:cache) { CACHE_SERVER }
|
28
|
+
define_method(:secrets) { @secrets ||= Lux::Config::Secrets.new.load }
|
29
|
+
define_method(:root) { APP_ROOT }
|
30
|
+
define_method(:fw_root) { FW_ROOT }
|
31
|
+
define_method(:event) { Lux::EventBus }
|
32
|
+
define_method(:require_all) { |folder| Lux::Config.require_all folder }
|
26
33
|
|
27
34
|
# main rack response
|
28
35
|
def call env=nil
|
29
36
|
state = Lux::Current.new env
|
30
37
|
app = Lux::Application.new state
|
31
38
|
app.render
|
32
|
-
rescue =>
|
33
|
-
|
34
|
-
|
35
|
-
|
39
|
+
rescue => error
|
40
|
+
if Lux.config(:dump_errors)
|
41
|
+
raise error
|
42
|
+
else
|
43
|
+
log error.backtrace
|
44
|
+
[500, {}, ['Server error: %s' % error.message]]
|
45
|
+
end
|
36
46
|
end
|
37
47
|
|
38
48
|
def env key=nil
|
39
|
-
|
40
|
-
|
41
|
-
|
49
|
+
if key
|
50
|
+
value = ENV[key]
|
51
|
+
die "ENV['#{key}'] not found" if value.nil?
|
52
|
+
value
|
53
|
+
else
|
54
|
+
ENV['RACK_ENV']
|
55
|
+
end
|
42
56
|
end
|
43
57
|
|
44
58
|
def config key=nil
|
45
|
-
|
46
|
-
|
47
|
-
|
59
|
+
if key
|
60
|
+
value = CONFIG[key]
|
61
|
+
die 'Lux.config.%s not found' % key if value.nil?
|
62
|
+
value.kind_of?(Proc) ? value.call() : value
|
63
|
+
else
|
64
|
+
CONFIG
|
65
|
+
end
|
48
66
|
end
|
49
67
|
|
50
68
|
def current
|
@@ -59,43 +77,39 @@ module Lux
|
|
59
77
|
block ? Lux::Application.class_eval(&block) : Lux::Application
|
60
78
|
end
|
61
79
|
|
62
|
-
def
|
63
|
-
|
64
|
-
end
|
65
|
-
|
66
|
-
def fw_root
|
67
|
-
@@lux_fw_root ||= Pathname.new(File.expand_path('../../', File.dirname(__FILE__))).freeze
|
80
|
+
def error data=nil
|
81
|
+
data ? Lux::Error.render(data) : Lux::Error
|
68
82
|
end
|
69
83
|
|
70
|
-
|
71
|
-
|
72
|
-
Lux::Error.show(data)
|
73
|
-
end
|
74
|
-
|
75
|
-
def log what
|
84
|
+
# simple log to stdout
|
85
|
+
def log what=nil
|
76
86
|
return unless Lux.config(:log_to_stdout)
|
77
|
-
puts what
|
87
|
+
puts what || yield
|
78
88
|
end
|
79
89
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
EVENTS[name].push(proc)
|
86
|
-
else
|
87
|
-
for func in EVENTS[name]
|
88
|
-
ref.instance_eval(&func)
|
89
|
-
end
|
90
|
-
end
|
90
|
+
# simple interface to plugins
|
91
|
+
# Lux.plugin :foo
|
92
|
+
# Lux.plugin
|
93
|
+
def plugin *args
|
94
|
+
args.first ? Lux::Config::Plugin.load(*args) : Lux::Config::Plugin
|
91
95
|
end
|
92
96
|
|
93
97
|
# if block given, simple new thread bg job
|
94
98
|
# if string given, eval it in bg
|
95
99
|
# if object given, instance it and run it
|
96
|
-
def delay *args
|
100
|
+
def delay *args, &block
|
97
101
|
if block_given?
|
98
|
-
|
102
|
+
puts 'add'
|
103
|
+
|
104
|
+
t = Thread.new do
|
105
|
+
begin
|
106
|
+
block.call
|
107
|
+
rescue => e
|
108
|
+
Lux.logger(:delay_errors).error [e.message, e.backtrace]
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
BACKGROUND_THREADS.push t
|
99
113
|
elsif args[0]
|
100
114
|
# Lux.delay(mail_object, :deliver)
|
101
115
|
Lux::DelayedJob.push(*args)
|
@@ -104,23 +118,46 @@ module Lux
|
|
104
118
|
end
|
105
119
|
end
|
106
120
|
|
107
|
-
|
121
|
+
# load rake tasks + including ones in plugins
|
122
|
+
def load_tasks
|
123
|
+
require_relative '../../tasks/loader.rb'
|
124
|
+
end
|
125
|
+
|
126
|
+
# in memory cache, used on app init, no need for Mutex
|
127
|
+
def ram_cache key
|
128
|
+
MCACHE[key] = nil if Lux.config(:compile_assets)
|
129
|
+
MCACHE[key] ||= yield
|
130
|
+
end
|
131
|
+
|
132
|
+
# initialize the Lux application
|
133
|
+
def start
|
134
|
+
Lux.config.lux_config_loaded = true
|
135
|
+
|
136
|
+
Config.start!
|
137
|
+
end
|
138
|
+
|
139
|
+
# must be called when serving web pages from rackup
|
140
|
+
def serve rack_handler
|
141
|
+
@rackup_start = true
|
142
|
+
Object.class_callback :web_boot, Lux::Application, rack_handler
|
143
|
+
rack_handler.run self
|
144
|
+
end
|
145
|
+
|
146
|
+
# simple block to calc block execution speed
|
147
|
+
def speed
|
108
148
|
render_start = Time.monotonic
|
109
|
-
|
149
|
+
yield
|
110
150
|
num = (Time.monotonic - render_start) * 1000
|
111
|
-
|
112
|
-
loops == 1 ? num : "Done #{loops.to_s.sub(/(\d)(\d{3})$/,'\1s \2')} loops in #{num}"
|
151
|
+
'%s ms' % num.round(1)
|
113
152
|
end
|
114
153
|
|
115
|
-
#
|
116
|
-
def
|
117
|
-
|
118
|
-
base = '%s/base.rb' % dir
|
154
|
+
# Lux.logger(:foo).warn 'bar'
|
155
|
+
def logger name=nil
|
156
|
+
name ||= ENV.fetch('RACK_ENV').downcase
|
119
157
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
Lux::Config.require_all('%s/*' % dir)
|
158
|
+
MCACHE['lux-logger-%s' % name] ||=
|
159
|
+
Logger.new('./log/%s.log' % name).tap do |it|
|
160
|
+
it.formatter = Lux.config.logger_formater
|
124
161
|
end
|
125
162
|
end
|
126
163
|
end
|
data/lib/lux/mailer/mailer.rb
CHANGED
@@ -1,31 +1,32 @@
|
|
1
1
|
# sugessted usage
|
2
|
-
# Mailer.deliver(:
|
3
|
-
# Mailer.render(:
|
2
|
+
# Mailer.deliver(:email_login, 'foo@bar.baz')
|
3
|
+
# Mailer.render(:email_login, 'foo@bar.baz')
|
4
4
|
|
5
5
|
# natively works like
|
6
|
-
# Mailer.prepare(:
|
7
|
-
# Mailer.prepare(:
|
6
|
+
# Mailer.prepare(:email_login, 'foo@bar.baz').deliver
|
7
|
+
# Mailer.prepare(:email_login, 'foo@bar.baz').body
|
8
8
|
|
9
9
|
# Rails mode via method missing is suported
|
10
|
-
# Mailer.
|
11
|
-
# Mailer.
|
10
|
+
# Mailer.email_login('foo@bar.baz').deliver
|
11
|
+
# Mailer.email_login('foo@bar.baz').body
|
12
12
|
|
13
13
|
class Lux::Mailer
|
14
|
-
|
14
|
+
class_callback :before
|
15
|
+
class_callback :after
|
16
|
+
|
15
17
|
class_attribute :helper
|
18
|
+
class_attribute :layout, 'mailer'
|
16
19
|
|
17
20
|
attr_reader :mail
|
18
21
|
|
19
22
|
class << self
|
20
|
-
# Mailer.prepare(:
|
23
|
+
# Mailer.prepare(:email_login, 'foo@bar.baz')
|
21
24
|
def prepare template, *args
|
22
25
|
obj = new
|
23
26
|
obj.instance_variable_set :@_template, template
|
24
|
-
|
25
|
-
ClassCallbacks.execute obj, :before
|
27
|
+
Object.class_callback :before, obj
|
26
28
|
obj.send template, *args
|
27
|
-
|
28
|
-
|
29
|
+
Object.class_callback :after, obj
|
29
30
|
obj
|
30
31
|
end
|
31
32
|
|
@@ -45,7 +46,7 @@ class Lux::Mailer
|
|
45
46
|
###
|
46
47
|
|
47
48
|
def initialize
|
48
|
-
@mail =
|
49
|
+
@mail = FreeStruct.new subject: nil, body: nil, to: nil, cc: nil, from: nil
|
49
50
|
end
|
50
51
|
|
51
52
|
def deliver
|
@@ -53,30 +54,27 @@ class Lux::Mailer
|
|
53
54
|
raise "To in mailer not defined" unless @mail.to
|
54
55
|
raise "Subject in mailer not defined" unless @mail.subject
|
55
56
|
|
56
|
-
require 'mail'
|
57
|
-
|
58
|
-
Mail.defaults { delivery_method Lux.config(:mail).delivery, Lux.config(:mail).opts }
|
59
|
-
|
60
57
|
m = Mail.new
|
61
58
|
m[:from] = @mail.from
|
62
59
|
m[:to] = @mail.to
|
63
60
|
m[:subject] = @mail.subject
|
64
|
-
m[:body] =
|
61
|
+
m[:body] = body
|
65
62
|
m[:content_type] = 'text/html; charset=UTF-8'
|
66
63
|
|
67
|
-
|
68
|
-
end
|
64
|
+
Lux.delay { m.deliver! }
|
69
65
|
|
70
|
-
|
71
|
-
Lux.delay self, :deliver
|
66
|
+
instance_exec m, &Lux.config.on_mail
|
72
67
|
end
|
73
68
|
|
74
69
|
def body
|
75
|
-
|
70
|
+
data = @mail.body
|
76
71
|
|
77
|
-
|
72
|
+
unless data
|
73
|
+
helper = Lux::View::Helper.new self, self.class.helper
|
74
|
+
data = Lux::View.render_with_layout "layouts/#{self.class.layout}", "mailer/#{@_template}", helper
|
75
|
+
end
|
78
76
|
|
79
|
-
|
77
|
+
data.gsub(%r{\shref=(['"])/}) { %[ href=#{$1}#{Lux.config.host}/] }
|
80
78
|
end
|
81
79
|
|
82
80
|
def subject
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Lux::Response::File
|
4
|
+
MIMME_TYPES = {
|
5
|
+
txt: 'text/plain',
|
6
|
+
html: 'text/html',
|
7
|
+
gif: 'image/gif',
|
8
|
+
jpg: 'image/jpeg',
|
9
|
+
jpeg: 'image/jpeg',
|
10
|
+
png: 'image/png',
|
11
|
+
ico: 'image/png', # image/x-icon
|
12
|
+
css: 'text/css',
|
13
|
+
map: 'application/json',
|
14
|
+
js: 'application/javascript',
|
15
|
+
gz: 'application/x-gzip',
|
16
|
+
zip: 'application/x-gzip',
|
17
|
+
svg: 'image/svg+xml',
|
18
|
+
mp3: 'application/mp3',
|
19
|
+
woff: 'application/x-font-woff',
|
20
|
+
woff2: 'application/x-font-woff',
|
21
|
+
ttf: 'application/font-ttf',
|
22
|
+
eot: 'application/vnd.ms-fontobject',
|
23
|
+
otf: 'application/font-otf',
|
24
|
+
doc: 'application/msword'
|
25
|
+
}
|
26
|
+
|
27
|
+
###
|
28
|
+
# all parametars are optional
|
29
|
+
# :name - file name
|
30
|
+
# :cache - client cache in seconds
|
31
|
+
# :content_type - string type
|
32
|
+
# :inline - sets disposition to inline if true
|
33
|
+
# :disposition - inline or attachment
|
34
|
+
# :content - raw file data
|
35
|
+
def initialize file, in_opts={}
|
36
|
+
opts = in_opts.to_opts :name, :cache, :content_type, :inline, :disposition, :content
|
37
|
+
opts.disposition ||= opts.inline.class == TrueClass ? 'inline' : 'attachment'
|
38
|
+
opts.cache = true if opts.cache.nil?
|
39
|
+
|
40
|
+
file = 'public/%s' % file unless file[0, 1] == '/'
|
41
|
+
|
42
|
+
@ext = file.include?('.') ? file.split('.').last.to_sym : nil
|
43
|
+
@file = file
|
44
|
+
@opts = opts
|
45
|
+
end
|
46
|
+
|
47
|
+
define_method(:request) { Lux.current.request }
|
48
|
+
define_method(:response) { Lux.current.response }
|
49
|
+
|
50
|
+
def is_static_file?
|
51
|
+
return false unless @ext
|
52
|
+
File.exist?(@file)
|
53
|
+
end
|
54
|
+
|
55
|
+
def send
|
56
|
+
file = File.exist?(@file) ? @file : Lux.root.join("public#{@file}").to_s
|
57
|
+
|
58
|
+
raise Lux::Error.not_found('Static file not found') unless File.exists?(file)
|
59
|
+
|
60
|
+
response.content_type(@opts.content_type || MIMME_TYPES[@ext || '_'] || 'application/octet-stream')
|
61
|
+
|
62
|
+
file_mtime = File.mtime(file).utc.to_s
|
63
|
+
key = Crypt.sha1(file + (@opts.content || file_mtime.to_s))
|
64
|
+
|
65
|
+
if @opts.disposition == 'attachment'
|
66
|
+
@opts.name ||= @file.split('/').last
|
67
|
+
response.headers['content-disposition'] = 'attachment; filename=%s' % @opts.name
|
68
|
+
end
|
69
|
+
|
70
|
+
response.headers['cache-control'] = 'max-age=%d, public' % (@opts.cache ? 31536000 : 0)
|
71
|
+
response.headers['etag'] = '"%s"' % key
|
72
|
+
response.headers['last-modified'] = file_mtime
|
73
|
+
|
74
|
+
# IF etags match, returnfrom cache
|
75
|
+
if request.env['HTTP_IF_NONE_MATCH'] == key
|
76
|
+
response.body('not-modified', 304)
|
77
|
+
else
|
78
|
+
response.body @opts.content || File.read(file)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|