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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/.version +1 -1
  3. data/lib/README.md +30 -0
  4. data/lib/lux/README.md +10 -0
  5. data/lib/lux/application/README.md +147 -0
  6. data/lib/lux/cache/README.md +47 -0
  7. data/lib/lux/config/README.md +63 -0
  8. data/lib/lux/controller/README.md +49 -0
  9. data/lib/lux/current/README.md +14 -0
  10. data/lib/lux/delayed_job/README.md +3 -0
  11. data/lib/lux/error/README.md +41 -0
  12. data/lib/lux/event_bus/README.md +36 -0
  13. data/lib/lux/mailer/README.md +73 -0
  14. data/lib/lux/response/README.md +1 -0
  15. data/lib/lux/view/README.md +85 -0
  16. data/misc/demo/Gemfile +4 -0
  17. data/misc/demo/Rakefile +3 -0
  18. data/misc/demo/app/assets/css/main/index.scss +1 -0
  19. data/misc/demo/app/cells/cell.scss +5 -0
  20. data/misc/demo/app/cells/demo.haml +1 -0
  21. data/misc/demo/app/views/layouts/main.haml +10 -0
  22. data/misc/demo/app/views/main/root/index.haml +9 -0
  23. data/misc/demo/config.ru +5 -0
  24. data/misc/demo/public/manifest.json +5 -0
  25. data/misc/demo/tmp/assets/d-app-assets-css-main-index.scss +1 -0
  26. data/misc/demo/tmp/assets/d-app-cells-cell.scss +5 -0
  27. data/misc/demo/yarn.lock +2656 -0
  28. data/misc/lux.png +0 -0
  29. data/misc/nginx.conf +60 -0
  30. data/misc/siege-and-puma.txt +3 -0
  31. data/plugins/api/README.md +49 -0
  32. data/plugins/db/README.md +29 -0
  33. data/plugins/db/auto_migrate/db.rake +15 -0
  34. data/plugins/exceptions/exceptions.rake +43 -0
  35. data/plugins/html/README.md +3 -0
  36. data/plugins/js_widgets/README.md +5 -0
  37. data/plugins/js_widgets/js/html_tag.coffee +42 -0
  38. data/plugins/js_widgets/js/widgets.coffee +161 -0
  39. data/tasks/nginx.rake +23 -0
  40. metadata +38 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 809c29122351db4ad4bd4de489f14f54c263b8911cc6d41b91d411beeaffe959
4
- data.tar.gz: f4912bd49fbe63229dbccab2582c13cdf308299e4194a001c150e5e54765e7ae
3
+ metadata.gz: 3d0b06d65d3e76de965f29a418513ce4f7cae994353e31d072cbeb5224057996
4
+ data.tar.gz: 42158b78a77c6bcbdd001804c57752f6e2d35fd809d6bdfe324193019d8aef8f
5
5
  SHA512:
6
- metadata.gz: d919b51494836f5e12af3fe372689ed721607205d92bc2668dc075f795b65cb867bd0b642b228bf98cdca30e071acaf4fbaf10c68dc5057a2ddfc43ef88ea660
7
- data.tar.gz: 2e514b0713c9d3dd9ad2e7c4ff91386a30fc839335a60ffa7c10d504eea8a2b1b8f76785c2568d2bd0ecc8f697d6ba5c6d674bf59fe45c502cf3b510b90490c4
6
+ metadata.gz: bb2144cef763d0bc2ee5532bd2be220f1deb232c9d9aaf21dfe4ededf13114f0007bb63f96deee4f7f2600e1d6e4740197929aa125988a7dd2fa526f499ea2a5
7
+ data.tar.gz: 40567507bed00de677822736bfa49efef2414ebe1c4751720eda24c27c694a990307fc4cabb834dd1249b6a0b43ea9b01ffbdd08106ff04b03c6d0dbee2fae46
data/.version CHANGED
@@ -1 +1 @@
1
- 0.5.32
1
+ 0.5.33
@@ -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
+
@@ -0,0 +1,10 @@
1
+ # Page render flow
2
+
3
+ ## Example config ru
4
+ ```
5
+ $lux_start_time = Time.now
6
+ require './config/application'
7
+ Lux.serve self
8
+ ```
9
+
10
+ * if you define `$lux_start_time` you will get speed load statistics
@@ -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,3 @@
1
+ ## Delayed job
2
+
3
+ to do
@@ -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
+