lux-fw 0.5.32 → 0.5.33
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/lib/README.md +30 -0
- data/lib/lux/README.md +10 -0
- data/lib/lux/application/README.md +147 -0
- data/lib/lux/cache/README.md +47 -0
- data/lib/lux/config/README.md +63 -0
- data/lib/lux/controller/README.md +49 -0
- data/lib/lux/current/README.md +14 -0
- data/lib/lux/delayed_job/README.md +3 -0
- data/lib/lux/error/README.md +41 -0
- data/lib/lux/event_bus/README.md +36 -0
- data/lib/lux/mailer/README.md +73 -0
- data/lib/lux/response/README.md +1 -0
- data/lib/lux/view/README.md +85 -0
- data/misc/demo/Gemfile +4 -0
- data/misc/demo/Rakefile +3 -0
- data/misc/demo/app/assets/css/main/index.scss +1 -0
- data/misc/demo/app/cells/cell.scss +5 -0
- data/misc/demo/app/cells/demo.haml +1 -0
- data/misc/demo/app/views/layouts/main.haml +10 -0
- data/misc/demo/app/views/main/root/index.haml +9 -0
- data/misc/demo/config.ru +5 -0
- data/misc/demo/public/manifest.json +5 -0
- data/misc/demo/tmp/assets/d-app-assets-css-main-index.scss +1 -0
- data/misc/demo/tmp/assets/d-app-cells-cell.scss +5 -0
- data/misc/demo/yarn.lock +2656 -0
- data/misc/lux.png +0 -0
- data/misc/nginx.conf +60 -0
- data/misc/siege-and-puma.txt +3 -0
- data/plugins/api/README.md +49 -0
- data/plugins/db/README.md +29 -0
- data/plugins/db/auto_migrate/db.rake +15 -0
- data/plugins/exceptions/exceptions.rake +43 -0
- data/plugins/html/README.md +3 -0
- data/plugins/js_widgets/README.md +5 -0
- data/plugins/js_widgets/js/html_tag.coffee +42 -0
- data/plugins/js_widgets/js/widgets.coffee +161 -0
- data/tasks/nginx.rake +23 -0
- metadata +38 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3d0b06d65d3e76de965f29a418513ce4f7cae994353e31d072cbeb5224057996
|
4
|
+
data.tar.gz: 42158b78a77c6bcbdd001804c57752f6e2d35fd809d6bdfe324193019d8aef8f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bb2144cef763d0bc2ee5532bd2be220f1deb232c9d9aaf21dfe4ededf13114f0007bb63f96deee4f7f2600e1d6e4740197929aa125988a7dd2fa526f499ea2a5
|
7
|
+
data.tar.gz: 40567507bed00de677822736bfa49efef2414ebe1c4751720eda24c27c694a990307fc4cabb834dd1249b6a0b43ea9b01ffbdd08106ff04b03c6d0dbee2fae46
|
data/.version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.5.
|
1
|
+
0.5.33
|
data/lib/README.md
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# LUX - ruby web framework
|
2
|
+
|
3
|
+
![Lux logo](https://i.imgur.com/Zy7DLXU.png)
|
4
|
+
|
5
|
+
* rack based
|
6
|
+
* explicit, avoid magic when possible
|
7
|
+
|
8
|
+
created by @dux in 2017
|
9
|
+
|
10
|
+
## How to start
|
11
|
+
|
12
|
+
First, make sure you have `ruby 2.x+`, `npm 6.x+` and `yarn 1.x+` installed.
|
13
|
+
|
14
|
+
Install Lux framework.
|
15
|
+
|
16
|
+
`gem install lux-fw`
|
17
|
+
|
18
|
+
Create new template for lux app
|
19
|
+
|
20
|
+
`lux new my-app`
|
21
|
+
|
22
|
+
Start the app
|
23
|
+
|
24
|
+
`lux s`
|
25
|
+
|
26
|
+
Look at the generated code and play with it.
|
27
|
+
|
28
|
+
## Lux components
|
29
|
+
|
30
|
+
|
data/lib/lux/README.md
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
## Lux::Application - main application controller and router
|
2
|
+
|
3
|
+
* can capture errors with `on_error` instance method
|
4
|
+
* calls `before`, `routes` and `after` class filters on every request
|
5
|
+
* routes requests to controllers via `map`, `root` and `call` methods
|
6
|
+
|
7
|
+
### Instance methods
|
8
|
+
|
9
|
+
#### root
|
10
|
+
|
11
|
+
executes if nav.root is empty
|
12
|
+
|
13
|
+
#### map
|
14
|
+
|
15
|
+
map specific nav root to Controller and calls if root mathes
|
16
|
+
|
17
|
+
for example if path is /blogs
|
18
|
+
|
19
|
+
`map blogs: Main::BlogController`
|
20
|
+
|
21
|
+
will call instance method call with @path expanded
|
22
|
+
|
23
|
+
`Main::BlogController.new.call(*@path)`
|
24
|
+
|
25
|
+
more examples
|
26
|
+
|
27
|
+
* `map blog: BlogController` will call `BlogController.action(:blog)`
|
28
|
+
* `map blog: 'blog#single'` will call `BlogController.action(:single)`
|
29
|
+
* `map blog: -> { BlogController.custom(:whatever) }`
|
30
|
+
|
31
|
+
### call
|
32
|
+
|
33
|
+
Calls specific controller action inside call.
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
call 'main/links#index'
|
37
|
+
call [Main::LinksController, :index]
|
38
|
+
call -> { [200, {}, ['OK']]}
|
39
|
+
```
|
40
|
+
|
41
|
+
### Router example
|
42
|
+
|
43
|
+
For Lux routing you need to know only few things
|
44
|
+
|
45
|
+
* taget can be 5 object variants, look at root example
|
46
|
+
* "root" method calls object if nav.root is blank?
|
47
|
+
* "map" method calls object if nav.first == match
|
48
|
+
* "namespace" method accepts block that wraps map calls.
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
Lux.app do
|
52
|
+
|
53
|
+
def api_router
|
54
|
+
error :forbiden, 'Only POST requests are allowed' if Lux.prod? && !post?
|
55
|
+
Lux::Api.call nav.path
|
56
|
+
end
|
57
|
+
|
58
|
+
before do
|
59
|
+
check_subdomain
|
60
|
+
end
|
61
|
+
|
62
|
+
after do
|
63
|
+
error 404
|
64
|
+
end
|
65
|
+
|
66
|
+
###
|
67
|
+
|
68
|
+
routes do
|
69
|
+
# we show on root method, that target can be multiple object types, 5 variants
|
70
|
+
root [RootController, :index] # calls RootController#index
|
71
|
+
root 'root#call' # calls RootController#call
|
72
|
+
root :call_root # calls "call_root" method in current scope
|
73
|
+
root 'root' # calls RootController#index
|
74
|
+
root 'root#foo' # calls RootController#foo
|
75
|
+
|
76
|
+
# we can route based on the user status
|
77
|
+
root User.current ? 'main/root' : 'guest'
|
78
|
+
|
79
|
+
# map "/api" to "api_router" method
|
80
|
+
map api: :api_router
|
81
|
+
|
82
|
+
# with MainController
|
83
|
+
# map MainController do
|
84
|
+
map 'main' do
|
85
|
+
map :search # map "/search" to MainController#search
|
86
|
+
map '/login' # map "/login" to MainController#login
|
87
|
+
end
|
88
|
+
|
89
|
+
# map "/foo/dux/baz" route to MainController#foo with params[:bar] == 'dux'
|
90
|
+
map '/foo/:bar/baz' => 'main#foo'
|
91
|
+
|
92
|
+
# if method "city" in current scope returns true
|
93
|
+
namespace :city do
|
94
|
+
# call MainController#city if request.method == 'GET'
|
95
|
+
map 'main#city' if get?
|
96
|
+
end
|
97
|
+
|
98
|
+
# if we match '/foo' route
|
99
|
+
namespace 'foo' do
|
100
|
+
# call MainController#foo with params[:bar] == '...'
|
101
|
+
map '/baz/:bar' => 'main#foo'
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
```
|
106
|
+
|
107
|
+
### Router rescues example
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
Lux.app do
|
111
|
+
def on_error error
|
112
|
+
|
113
|
+
message = case error
|
114
|
+
when PG::ConnectionBad
|
115
|
+
msg = error.message || 'DB connection error, please refresh page.'
|
116
|
+
msg = "PG: #{msg}"
|
117
|
+
Lux.logger(:db_error).error msg
|
118
|
+
msg
|
119
|
+
|
120
|
+
when Lux::Error
|
121
|
+
# for handled errors
|
122
|
+
# show HTTP errors in a browser without a log
|
123
|
+
Main::RootController.action(:error, error)
|
124
|
+
|
125
|
+
else
|
126
|
+
# raise errors in developmet
|
127
|
+
raise error if Lux.dev?
|
128
|
+
|
129
|
+
key = Lux.error.log error
|
130
|
+
"#{error.class}: #{error.message} \n\nkey: #{key}"
|
131
|
+
end
|
132
|
+
|
133
|
+
# use default error formater
|
134
|
+
Lux.error message
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
if Lux.prod?
|
139
|
+
Lux.config.error_logger = proc do |error|
|
140
|
+
# log and show error page in a production
|
141
|
+
key = SimpleException.log error
|
142
|
+
Lux.cache.fetch('error-mail-%s' % key) { Mailer.error(error, key).deliver }
|
143
|
+
Lux.logger(:exceptions).error [key, User.current.try(:email).or('guest'), error.message].join(' - ')
|
144
|
+
key
|
145
|
+
end
|
146
|
+
end
|
147
|
+
```
|
@@ -0,0 +1,47 @@
|
|
1
|
+
## Lux::Cache - Mimics Rails.cache interface
|
2
|
+
|
3
|
+
Alias - `Lux.cache`
|
4
|
+
|
5
|
+
### Define
|
6
|
+
|
7
|
+
use RAM cache in development, as default
|
8
|
+
|
9
|
+
```
|
10
|
+
Lux::Cache.server = :memcached
|
11
|
+
```
|
12
|
+
|
13
|
+
You can use memcached or redis in production
|
14
|
+
|
15
|
+
```
|
16
|
+
Lux::Cache.server = Dalli::Client.new('localhost:11211', { :namespace=>Digest::MD5.hexdigest(__FILE__)[0,4], :compress => true, :expires_in => 1.hour })
|
17
|
+
```
|
18
|
+
|
19
|
+
### Lux::Cache instance methods
|
20
|
+
|
21
|
+
Mimics Rails cache methods
|
22
|
+
|
23
|
+
```
|
24
|
+
Lux.cache.read(key)
|
25
|
+
Lux.cache.get(key)
|
26
|
+
|
27
|
+
Lux.cache.read_multi(*args)
|
28
|
+
Lux.cache.get_multi(*args)
|
29
|
+
|
30
|
+
Lux.cache.write(key, data, ttl=nil)
|
31
|
+
Lux.cache.set(key, data, ttl=nil)
|
32
|
+
|
33
|
+
Lux.cache.delete(key, data=nil)
|
34
|
+
|
35
|
+
Lux.cache.fetch(key, ttl=nil, &block)
|
36
|
+
|
37
|
+
Lux.cache.is_available?
|
38
|
+
```
|
39
|
+
|
40
|
+
Has method to generate cache key
|
41
|
+
|
42
|
+
```
|
43
|
+
# generates unique cache key based on set of data
|
44
|
+
# Lux.cache.generate_key([User, Product.find(3), 'data', @product.updated_at])
|
45
|
+
|
46
|
+
Lux.cache.generate_key(*data)
|
47
|
+
```
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# Lux::Config - Config loader helpers
|
2
|
+
|
3
|
+
Methods for config and pluin loading.
|
4
|
+
|
5
|
+
## Lux::Config::Plugins
|
6
|
+
|
7
|
+
* loads plugins in selected namespace, default namespace :main
|
8
|
+
* gets plugins in selected namespace
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
Lux.plugin name_or_folder
|
12
|
+
Lux.plugin name: :foo, folder: '/.../...', namespace: [:main, :admin]
|
13
|
+
Lux.plugin name: :bar
|
14
|
+
|
15
|
+
Luxp.lugin.folders :admin # => [:foo]
|
16
|
+
Luxp.lugin.folders # => [:foo, :bar]
|
17
|
+
```
|
18
|
+
|
19
|
+
## Lux::Config::Secrets
|
20
|
+
|
21
|
+
Similar to rails 5.1+, we can encode secrets for easy config.
|
22
|
+
|
23
|
+
* using JWT HS512
|
24
|
+
* create and write sectes in YAML format in `./tmp/secrets.yaml`
|
25
|
+
* run `lux secrets` to compile secretes to `./config/secrets.txt`
|
26
|
+
* use "shared" hash for shared secrets
|
27
|
+
* sectets are available in app via `Lux.secrets`, as struct object
|
28
|
+
|
29
|
+
### lux secrets
|
30
|
+
|
31
|
+
* compiles unencoded sectes from `./tmp/secrets.yaml` to `./config/secrets.txt`
|
32
|
+
* creates editable file `./tmp/secrets.yaml` from `./config/secrets.txt` if one exists
|
33
|
+
* shows available secrets for current environment
|
34
|
+
|
35
|
+
### Example
|
36
|
+
|
37
|
+
Env development
|
38
|
+
|
39
|
+
Secrets file `./tmp/secrets.yaml`
|
40
|
+
|
41
|
+
```
|
42
|
+
shared:
|
43
|
+
x: s
|
44
|
+
b:
|
45
|
+
c: nested
|
46
|
+
|
47
|
+
production:
|
48
|
+
a: p
|
49
|
+
|
50
|
+
development:
|
51
|
+
a: d
|
52
|
+
```
|
53
|
+
|
54
|
+
`lux secrets` - will compile secrets or create template if needed
|
55
|
+
|
56
|
+
`lux c` - console
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
Lux.secrets.a == "d"
|
60
|
+
Lux.secrets.x == "s"
|
61
|
+
Lux.secrets.b.c == "nested"
|
62
|
+
```
|
63
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
## Lux::Controller - Simplified Rails like view controllers
|
2
|
+
|
3
|
+
Controllers are Lux view models
|
4
|
+
|
5
|
+
* all cells shoud inherit from Lux::Controller
|
6
|
+
* `before`, `before_action` and `after` class methods supportd
|
7
|
+
* instance_method `on_error` is supported
|
8
|
+
* calls templates as default action, behaves as Rails controller.
|
9
|
+
|
10
|
+
### Example code
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
require 'lux-fw'
|
14
|
+
|
15
|
+
class Main::RootController < Lux::Controller
|
16
|
+
# action to perform before
|
17
|
+
before do
|
18
|
+
@org = Org.find @org_id if @org_id
|
19
|
+
# ...
|
20
|
+
end
|
21
|
+
# action to perform before
|
22
|
+
|
23
|
+
before_action do |action_name|
|
24
|
+
next if action_name == :index
|
25
|
+
# ...
|
26
|
+
end
|
27
|
+
|
28
|
+
###
|
29
|
+
|
30
|
+
mock :show # mock `show` action
|
31
|
+
|
32
|
+
def index
|
33
|
+
render text: 'Hello world'
|
34
|
+
end
|
35
|
+
|
36
|
+
def foo
|
37
|
+
# renders ./app/views/main/root/foo.(haml, erb)
|
38
|
+
end
|
39
|
+
|
40
|
+
def baz
|
41
|
+
send_file local_file, file_name: 'local.txt'
|
42
|
+
end
|
43
|
+
|
44
|
+
def bar
|
45
|
+
render json: { data: 'Bar text' }
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
```
|
@@ -0,0 +1,14 @@
|
|
1
|
+
## Lux::Current - Main state object
|
2
|
+
|
3
|
+
Current application state as single object. Defined in Thread.current, available everywhere.
|
4
|
+
|
5
|
+
`Lux.current` - current response state
|
6
|
+
|
7
|
+
* `session` - session, encoded in cookie
|
8
|
+
* `locale` - locale, default nil
|
9
|
+
* `request` - Rack request
|
10
|
+
* `response` - Lux response object
|
11
|
+
* `nav` - lux nav object
|
12
|
+
* `cookies` - Rack cookies
|
13
|
+
* `can_clear_cache` - set to true if user can force refresh cache
|
14
|
+
|
@@ -0,0 +1,41 @@
|
|
1
|
+
## Lux::Errors - In case of error
|
2
|
+
|
3
|
+
### module Lux::Error
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
# try to execute part of the code, log exeception if fails
|
7
|
+
def try(name, &block)
|
8
|
+
|
9
|
+
# HTML render style for default Lux error
|
10
|
+
def render(desc)
|
11
|
+
|
12
|
+
# show error page
|
13
|
+
def show(desc)
|
14
|
+
|
15
|
+
# show inline error
|
16
|
+
def inline(name=nil, o=nil)
|
17
|
+
|
18
|
+
# log exeption
|
19
|
+
def log(exp_object)
|
20
|
+
```
|
21
|
+
|
22
|
+
|
23
|
+
### defines standard Lux errors and erro generating helpers
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
# 400: for bad parameter request or similar
|
27
|
+
Lux::Error.forbidden foo
|
28
|
+
|
29
|
+
# 401: for unauthorized access
|
30
|
+
Lux::Error.forbidden foo
|
31
|
+
|
32
|
+
# 403: for unalloed access
|
33
|
+
Lux::Error.forbidden foo
|
34
|
+
|
35
|
+
# 404: for not found pages
|
36
|
+
Lux::Error.not_found foo
|
37
|
+
|
38
|
+
# 503: for too many requests at the same time
|
39
|
+
Lux::Error.forbidden foo
|
40
|
+
|
41
|
+
```
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# Super simple event pub/sub
|
2
|
+
|
3
|
+
## to add events
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
Lux::EventBus.on('test') { |arg| puts 'foo: %s' % arg }
|
7
|
+
Lux.event.on('test', :foo) { |arg| puts 'bar: %s' % arg }
|
8
|
+
Lux.event.on('test', :foo) { |arg| puts 'baz: %s' % arg }
|
9
|
+
Lux.event.on('test') { |arg| raise 'abc' }
|
10
|
+
|
11
|
+
###
|
12
|
+
# foo: xxx
|
13
|
+
# baz: xxx
|
14
|
+
# error logged
|
15
|
+
```
|
16
|
+
|
17
|
+
|
18
|
+
## to call
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
Lux.event.call 'test', 'xxx'
|
22
|
+
```
|
23
|
+
|
24
|
+
|
25
|
+
## Error handler
|
26
|
+
|
27
|
+
Default event bus error handle.
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
Lux.config.on_event_bus_error = proc do |error, name|
|
31
|
+
Lux.logger(:event_bus).error '[%s] %s' % [name, error.message]
|
32
|
+
end
|
33
|
+
```
|
34
|
+
|
35
|
+
|
36
|
+
|