lux-fw 0.5.32 → 0.5.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+

|
|
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
|
+
|