pakyow-core 0.8.0 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/pakyow-core/CHANGES +9 -1
- data/pakyow-core/lib/core/app.rb +79 -68
- data/pakyow-core/lib/core/base.rb +10 -17
- data/pakyow-core/lib/core/config/app.rb +65 -89
- data/pakyow-core/lib/core/config/cookies.rb +4 -21
- data/pakyow-core/lib/core/config/logger.rb +39 -37
- data/pakyow-core/lib/core/config/server.rb +11 -25
- data/pakyow-core/lib/core/config.rb +90 -0
- data/pakyow-core/lib/core/errors.rb +3 -0
- data/pakyow-core/lib/core/helpers.rb +1 -1
- data/pakyow-core/lib/core/loader.rb +2 -2
- data/pakyow-core/lib/core/middleware/logger.rb +1 -0
- data/pakyow-core/lib/core/middleware/static.rb +1 -1
- data/pakyow-core/lib/core/request.rb +4 -4
- data/pakyow-core/lib/core/route_eval.rb +7 -6
- data/pakyow-core/lib/core/route_merger.rb +2 -2
- data/pakyow-core/lib/core/route_set.rb +1 -1
- data/pakyow-core/lib/core/route_template_defaults.rb +1 -1
- data/pakyow-core/lib/core/router.rb +3 -3
- metadata +22 -10
- data/pakyow-core/lib/core/config/base.rb +0 -30
- data/pakyow-core/lib/utils/dir.rb +0 -40
- data/pakyow-core/lib/utils/hash.rb +0 -44
- data/pakyow-core/lib/utils/string.rb +0 -41
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8c95a638e0b963832783f28d930b2d3643d22d9a
|
4
|
+
data.tar.gz: 13933ac6f3e609509cbdd2114820a9dfbd9daf23
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e9de80789a1192803b8643ed2a66523d675a4bd5482f0baca76b4680334f322b7ee612752809383f272a325c6aba9dc378d410ea3ba836c71dfd5f64bcfe4b45
|
7
|
+
data.tar.gz: 9399398fa726206307b9de398575289d7c1e470ef21cbd6b05c30cdc714a70e67372158ce5ded1f32ca6ddf3bcb84b65631b501fc118aa9094980fd1775bbdd5
|
data/pakyow-core/CHANGES
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
= 0.9.0
|
2
|
+
|
3
|
+
* Renames restful "remove" action to "delete"
|
4
|
+
* Improves app generator bundle install by showing progress
|
5
|
+
* Complete refactor of config handling with a shiny DSL
|
6
|
+
* Includes pakyow-rake as a dependency, and updates the generated Rakefile
|
7
|
+
* Removes support for Ruby versions < 2.0.0
|
8
|
+
|
1
9
|
= 0.8.0 / 2014-03-02
|
2
10
|
|
3
11
|
* Major rewrite, including changes to app definition and routing
|
@@ -48,4 +56,4 @@
|
|
48
56
|
|
49
57
|
= 0.6.0 / 2011-08-20
|
50
58
|
|
51
|
-
* Initial gem release of 0.6.0 codebase
|
59
|
+
* Initial gem release of 0.6.0 codebase
|
data/pakyow-core/lib/core/app.rb
CHANGED
@@ -1,30 +1,61 @@
|
|
1
1
|
module Pakyow
|
2
2
|
class App
|
3
3
|
class << self
|
4
|
-
|
5
|
-
@@routes = {}
|
6
|
-
@@config = {}
|
7
|
-
@@middleware = []
|
4
|
+
attr_reader :path
|
8
5
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
6
|
+
# Prepares the app for being staged in one or more environments by
|
7
|
+
# loading config(s), middleware, and setting the load path.
|
8
|
+
#
|
9
|
+
def prepare(*env_or_envs)
|
10
|
+
return if prepared?
|
11
|
+
|
12
|
+
# load config for one or more environments
|
13
|
+
load_config(*env_or_envs)
|
14
|
+
|
15
|
+
# load each block from middleware stack
|
16
|
+
load_middleware
|
17
|
+
|
18
|
+
# include pwd in load path
|
19
|
+
$:.unshift(Dir.pwd) unless $:.include? Dir.pwd
|
20
|
+
|
21
|
+
@prepared = true
|
22
|
+
end
|
23
|
+
|
24
|
+
# Stages the app by preparing and returning an instance. This is
|
25
|
+
# essentially everything short of running it.
|
26
|
+
#
|
27
|
+
def stage(*env_or_envs)
|
28
|
+
unless staged?
|
29
|
+
prepare(*env_or_envs)
|
30
|
+
@staged = true
|
31
|
+
end
|
32
|
+
|
33
|
+
self.new
|
34
|
+
end
|
35
|
+
|
36
|
+
# Runs the staged app.
|
37
|
+
#
|
38
|
+
def run(*env_or_envs)
|
39
|
+
return if running?
|
40
|
+
|
41
|
+
@running = true
|
42
|
+
builder.run(stage(*env_or_envs))
|
43
|
+
detect_handler.run(builder, Host: config.server.host, Port: config.server.port) do |server|
|
44
|
+
trap(:INT) { stop(server) }
|
45
|
+
trap(:TERM) { stop(server) }
|
46
|
+
end
|
14
47
|
end
|
15
48
|
|
16
49
|
# Defines an app
|
17
50
|
#
|
18
51
|
def define(&block)
|
19
52
|
# sets the path to the app file so it can be reloaded later
|
20
|
-
|
21
|
-
|
53
|
+
@path = String.parse_path_from_caller(caller[0])
|
22
54
|
self.instance_eval(&block)
|
23
55
|
end
|
24
56
|
|
25
57
|
# Defines a route set.
|
26
58
|
#
|
27
|
-
#TODO default route set should be config option (also for bindings)
|
28
59
|
def routes(set_name = :main, &block)
|
29
60
|
if set_name && block
|
30
61
|
@@routes[set_name] = block
|
@@ -63,30 +94,6 @@ module Pakyow
|
|
63
94
|
@@stacks[:after][stack_name.to_sym] << block
|
64
95
|
end
|
65
96
|
|
66
|
-
# Runs the application. Accepts the environment(s) to run, for example:
|
67
|
-
# run(:development)
|
68
|
-
# run([:development, :staging])
|
69
|
-
#
|
70
|
-
def run(*args)
|
71
|
-
return if running?
|
72
|
-
|
73
|
-
@running = true
|
74
|
-
builder.run(prepare(args))
|
75
|
-
detect_handler.run(builder, :Host => config.server.host, :Port => config.server.port) do |server|
|
76
|
-
trap(:INT) { stop(server) }
|
77
|
-
trap(:TERM) { stop(server) }
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
# Stages the application. Everything is loaded but the application is
|
82
|
-
# not started. Accepts the same arguments as #run.
|
83
|
-
#
|
84
|
-
def stage(*args)
|
85
|
-
return if staged?
|
86
|
-
@staged = true
|
87
|
-
prepare(args)
|
88
|
-
end
|
89
|
-
|
90
97
|
def builder
|
91
98
|
@builder ||= Rack::Builder.new
|
92
99
|
end
|
@@ -110,51 +117,55 @@ module Pakyow
|
|
110
117
|
# Convenience method for base configuration class.
|
111
118
|
#
|
112
119
|
def config
|
113
|
-
Pakyow::Config
|
120
|
+
Pakyow::Config
|
121
|
+
end
|
122
|
+
|
123
|
+
def reset
|
124
|
+
@prepared = false
|
125
|
+
@staged = false
|
126
|
+
@running = false
|
127
|
+
|
128
|
+
@@routes = {}
|
129
|
+
@@config = {}
|
130
|
+
@@middleware = []
|
131
|
+
|
132
|
+
@@stacks = {:before => {}, :after => {}}
|
133
|
+
%w(init load process route match error).each {|name|
|
134
|
+
@@stacks[:before][name.to_sym] = []
|
135
|
+
@@stacks[:after][name.to_sym] = []
|
136
|
+
}
|
114
137
|
end
|
115
138
|
|
116
|
-
def load_config(
|
139
|
+
def load_config(*env_or_envs)
|
140
|
+
envs = Array.ensure(env_or_envs)
|
141
|
+
envs = envs.empty? || envs.first.nil? ? [config.app.default_environment] : envs
|
142
|
+
|
143
|
+
config.app.loaded_envs = envs
|
144
|
+
config.env = envs.first.to_sym
|
145
|
+
|
117
146
|
# run global config first
|
118
147
|
if global_proc = @@config[:global]
|
119
|
-
config.
|
148
|
+
config.app_config(&global_proc)
|
120
149
|
end
|
121
150
|
|
122
151
|
# then run other envs
|
123
|
-
|
124
152
|
envs.each do |env|
|
125
153
|
next unless config_proc = @@config[env.to_sym]
|
126
|
-
config.
|
154
|
+
config.app_config(&config_proc)
|
127
155
|
end
|
128
|
-
|
129
|
-
config.app.loaded_envs = envs
|
130
156
|
end
|
131
157
|
|
132
158
|
protected
|
133
159
|
|
134
|
-
|
135
|
-
|
136
|
-
def prepare(envs)
|
137
|
-
return if prepared?
|
138
|
-
|
139
|
-
# configure
|
140
|
-
envs = envs.empty? || envs.first.nil? ? [config.app.default_environment] : envs
|
141
|
-
load_config(envs)
|
142
|
-
|
143
|
-
# load each block from middleware stack
|
144
|
-
@@middleware.each {|mw|
|
160
|
+
def load_middleware
|
161
|
+
@@middleware.each do |mw|
|
145
162
|
self.instance_exec(builder, &mw)
|
146
|
-
|
163
|
+
end
|
147
164
|
|
148
165
|
builder.use(Rack::MethodOverride)
|
149
166
|
builder.use(Middleware::Static) if config.app.static
|
150
167
|
builder.use(Middleware::Logger) if config.app.log
|
151
168
|
builder.use(Middleware::Reloader) if config.app.auto_reload
|
152
|
-
|
153
|
-
@prepared = true
|
154
|
-
|
155
|
-
$:.unshift(Dir.pwd) unless $:.include? Dir.pwd
|
156
|
-
|
157
|
-
return self.new
|
158
169
|
end
|
159
170
|
|
160
171
|
def detect_handler
|
@@ -201,7 +212,7 @@ module Pakyow
|
|
201
212
|
# Returns the primary (first) loaded env.
|
202
213
|
#
|
203
214
|
def env
|
204
|
-
config.
|
215
|
+
config.env
|
205
216
|
end
|
206
217
|
|
207
218
|
def app
|
@@ -246,7 +257,7 @@ module Pakyow
|
|
246
257
|
view_file = File.join(File.expand_path('../../', __FILE__), 'views', 'errors', '404.html')
|
247
258
|
content = File.open(view_file).read
|
248
259
|
|
249
|
-
path =
|
260
|
+
path = String.normalize_path(request.path)
|
250
261
|
path = '/' if path.empty?
|
251
262
|
|
252
263
|
content.gsub!('{view_path}', path == '/' ? 'index.html' : "#{path}.html")
|
@@ -276,12 +287,12 @@ module Pakyow
|
|
276
287
|
view_file = File.join(File.expand_path('../../', __FILE__), 'views', 'errors', '500.html')
|
277
288
|
content = File.open(view_file).read
|
278
289
|
|
279
|
-
path =
|
290
|
+
path = String.normalize_path(request.path)
|
280
291
|
path = '/' if path.empty?
|
281
292
|
|
282
293
|
nice_source = error.backtrace[0].match(/^(.+?):(\d+)(|:in `(.+)')$/)
|
283
294
|
|
284
|
-
content.gsub!('{file}', nice_source[1].gsub(File.expand_path(Config
|
295
|
+
content.gsub!('{file}', nice_source[1].gsub(File.expand_path(Config.app.root) + '/', ''))
|
285
296
|
content.gsub!('{line}', nice_source[2])
|
286
297
|
|
287
298
|
content.gsub!('{msg}', CGI.escapeHTML(error.to_s))
|
@@ -307,10 +318,10 @@ module Pakyow
|
|
307
318
|
|
308
319
|
# reset config
|
309
320
|
envs = config.app.loaded_envs
|
310
|
-
config.reset
|
321
|
+
config.reset
|
311
322
|
|
312
323
|
# reload config
|
313
|
-
self.class.load_config(envs)
|
324
|
+
self.class.load_config(*envs)
|
314
325
|
|
315
326
|
load_app
|
316
327
|
end
|
@@ -345,7 +356,7 @@ module Pakyow
|
|
345
356
|
data = file_or_data.read
|
346
357
|
|
347
358
|
# auto set type based on file type
|
348
|
-
type = Rack::Mime.mime_type("." +
|
359
|
+
type = Rack::Mime.mime_type("." + String.split_at_last_dot(file_or_data.path)[1])
|
349
360
|
else
|
350
361
|
data = file_or_data
|
351
362
|
end
|
@@ -1,8 +1,3 @@
|
|
1
|
-
require 'core/config/base'
|
2
|
-
require 'core/config/app'
|
3
|
-
require 'core/config/server'
|
4
|
-
require 'core/config/cookies'
|
5
|
-
require 'core/config/logger'
|
6
1
|
require 'core/helpers'
|
7
2
|
require 'core/multilog'
|
8
3
|
require 'core/app_context'
|
@@ -18,31 +13,29 @@ require 'core/route_template_defaults'
|
|
18
13
|
require 'core/route_lookup'
|
19
14
|
require 'core/app'
|
20
15
|
require 'core/errors'
|
16
|
+
require 'core/config'
|
17
|
+
require 'core/config/app'
|
18
|
+
require 'core/config/server'
|
19
|
+
require 'core/config/cookies'
|
20
|
+
require 'core/config/logger'
|
21
21
|
|
22
22
|
# middlewares
|
23
23
|
require 'core/middleware/logger'
|
24
24
|
require 'core/middleware/static'
|
25
25
|
require 'core/middleware/reloader'
|
26
26
|
|
27
|
-
# utils
|
28
|
-
require 'utils/string'
|
29
|
-
require 'utils/hash'
|
30
|
-
require 'utils/dir'
|
31
|
-
|
32
27
|
module Pakyow
|
33
28
|
attr_accessor :app, :logger
|
34
29
|
|
35
30
|
def configure_logger
|
36
|
-
conf = Config::Base
|
37
|
-
|
38
31
|
logs = []
|
39
32
|
|
40
|
-
if File.directory?(
|
41
|
-
log_path = File.join(
|
33
|
+
if File.directory?(Config.logger.path)
|
34
|
+
log_path = File.join(Config.logger.path, Config.logger.filename)
|
42
35
|
|
43
36
|
begin
|
44
37
|
log = File.open(log_path, 'a')
|
45
|
-
log.sync if
|
38
|
+
log.sync if Config.logger.sync
|
46
39
|
|
47
40
|
logs << log
|
48
41
|
rescue StandardError => e
|
@@ -50,10 +43,10 @@ module Pakyow
|
|
50
43
|
end
|
51
44
|
end
|
52
45
|
|
53
|
-
logs << $stdout if
|
46
|
+
logs << $stdout if Config.app.log_output
|
54
47
|
|
55
48
|
io = logs.count > 1 ? MultiLog.new(*logs) : logs[0]
|
56
49
|
|
57
|
-
Pakyow.logger = Logger.new(io,
|
50
|
+
Pakyow.logger = Logger.new(io, Config.logger.level, Config.logger.colorize, Config.logger.auto_flush)
|
58
51
|
end
|
59
52
|
end
|
@@ -1,89 +1,65 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
@default_environment || :development
|
67
|
-
end
|
68
|
-
|
69
|
-
# The path to the application class
|
70
|
-
def path
|
71
|
-
@path
|
72
|
-
end
|
73
|
-
|
74
|
-
# Handle static files?
|
75
|
-
#
|
76
|
-
# For best performance, should be set to false if static files are
|
77
|
-
# handled by a web server (e.g. Nginx)
|
78
|
-
#
|
79
|
-
def static
|
80
|
-
@static || true
|
81
|
-
end
|
82
|
-
|
83
|
-
def loaded_envs
|
84
|
-
@loaded_envs
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
1
|
+
Pakyow::Config.register(:app) { |config|
|
2
|
+
|
3
|
+
# if true, the app will be reloaded on every request
|
4
|
+
config.opt :auto_reload
|
5
|
+
|
6
|
+
# if true, errors are displayed in the browser
|
7
|
+
config.opt :errors_in_browser
|
8
|
+
|
9
|
+
# the location of the app's root directory
|
10
|
+
config.opt :root, File.dirname('')
|
11
|
+
|
12
|
+
# the location of the app's resources
|
13
|
+
config.opt :resources, lambda { { default: File.join(root, 'public') } }
|
14
|
+
|
15
|
+
# the location of the app's source code
|
16
|
+
config.opt :src_dir, lambda { File.join(root, 'app', 'lib') }
|
17
|
+
|
18
|
+
# the environment to run in, if one isn't provided
|
19
|
+
config.opt :default_environment, :development
|
20
|
+
|
21
|
+
# the default action to use for routing
|
22
|
+
config.opt :default_action, :index
|
23
|
+
|
24
|
+
# if true, all routes are ignored
|
25
|
+
config.opt :ignore_routes, false
|
26
|
+
|
27
|
+
# if true, views are visible without a route defined
|
28
|
+
config.opt :all_views_visible, true
|
29
|
+
|
30
|
+
# whether or not pakyow should log to stdout
|
31
|
+
config.opt :log_output, true
|
32
|
+
|
33
|
+
# whether or not pakyow should write to a log
|
34
|
+
config.opt :log, true
|
35
|
+
|
36
|
+
# whether or not pakyow should serve static files
|
37
|
+
config.opt :static
|
38
|
+
|
39
|
+
# stores the path to the app definition
|
40
|
+
config.opt :path, lambda { Pakyow::App.path }
|
41
|
+
|
42
|
+
# stores the envs an app is run in
|
43
|
+
config.opt :loaded_envs
|
44
|
+
|
45
|
+
}.env(:development) { |opts|
|
46
|
+
|
47
|
+
opts.auto_reload = true
|
48
|
+
opts.errors_in_browser = true
|
49
|
+
opts.static = true
|
50
|
+
|
51
|
+
}.env(:staging) { |opts|
|
52
|
+
|
53
|
+
opts.auto_reload = false
|
54
|
+
opts.errors_in_browser = true
|
55
|
+
opts.log_output = false
|
56
|
+
opts.static = false
|
57
|
+
|
58
|
+
}.env(:production) { |opts|
|
59
|
+
|
60
|
+
opts.auto_reload = false
|
61
|
+
opts.errors_in_browser = false
|
62
|
+
opts.log_output = false
|
63
|
+
opts.static = false
|
64
|
+
|
65
|
+
}
|
@@ -1,21 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
class << self
|
7
|
-
attr_accessor :path, :expiration
|
8
|
-
|
9
|
-
# What path should the cookie be created for?
|
10
|
-
def path
|
11
|
-
@path || '/'
|
12
|
-
end
|
13
|
-
|
14
|
-
# When does the cookie expire?
|
15
|
-
def expiration
|
16
|
-
@expiration || Time.now + 60 * 60 * 24 * 7 # one week
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
1
|
+
Pakyow::Config.register(:cookies) { |config|
|
2
|
+
config.opt :path, '/'
|
3
|
+
config.opt :expiration, lambda { Time.now + 60 * 60 * 24 * 7 }
|
4
|
+
}
|
@@ -1,37 +1,39 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
1
|
+
Pakyow::Config.register(:logger) { |config|
|
2
|
+
|
3
|
+
# the default level to log at
|
4
|
+
config.opt :level, :debug
|
5
|
+
|
6
|
+
# where the log file should be placed
|
7
|
+
config.opt :path, lambda { File.join(Pakyow::Config.app.root, 'log') }
|
8
|
+
|
9
|
+
# the name of the log file
|
10
|
+
config.opt :filename, 'pakyow.log'
|
11
|
+
|
12
|
+
# whether or not the log file should be synced
|
13
|
+
config.opt :sync
|
14
|
+
|
15
|
+
# whether or not the log file should be flushed automatically
|
16
|
+
config.opt :auto_flush
|
17
|
+
|
18
|
+
# whether or not the log file should be colorized
|
19
|
+
config.opt :colorize
|
20
|
+
|
21
|
+
}.env(:development) { |opts|
|
22
|
+
|
23
|
+
opts.sync = true
|
24
|
+
opts.auto_flush = true
|
25
|
+
opts.colorize = true
|
26
|
+
|
27
|
+
}.env(:staging) { |opts|
|
28
|
+
|
29
|
+
opts.sync = false
|
30
|
+
opts.auto_flush = false
|
31
|
+
opts.colorize = false
|
32
|
+
|
33
|
+
}.env(:production) { |opts|
|
34
|
+
|
35
|
+
opts.sync = false
|
36
|
+
opts.auto_flush = false
|
37
|
+
opts.colorize = false
|
38
|
+
|
39
|
+
}
|
@@ -1,26 +1,12 @@
|
|
1
|
-
|
2
|
-
module Config
|
3
|
-
class Server
|
4
|
-
Config::Base.register_config(:server, self)
|
1
|
+
Pakyow::Config.register(:server) { |config|
|
5
2
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
@host || '0.0.0.0'
|
17
|
-
end
|
18
|
-
|
19
|
-
# If set, adds a handler to try (e.g. puma)
|
20
|
-
def handler
|
21
|
-
@handler || nil
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
3
|
+
# the port to start `pakyow server`
|
4
|
+
config.opt :port, 3000
|
5
|
+
|
6
|
+
# the host to start `pakyow server`
|
7
|
+
config.opt :host, '0.0.0.0'
|
8
|
+
|
9
|
+
# explicitly set a handler to try (e.g. puma)
|
10
|
+
config.opt :handler
|
11
|
+
|
12
|
+
}
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module Pakyow
|
2
|
+
class Config
|
3
|
+
class << self
|
4
|
+
attr_accessor :env
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.register(name)
|
8
|
+
config = Pakyow::Config.new(name)
|
9
|
+
yield(config.defaults)
|
10
|
+
|
11
|
+
@config ||= {}
|
12
|
+
@config[name] = config
|
13
|
+
|
14
|
+
self.class.instance_eval do
|
15
|
+
define_method(name) { @config[name] }
|
16
|
+
end
|
17
|
+
|
18
|
+
config
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.deregister(name)
|
22
|
+
@config.delete(name)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.reset
|
26
|
+
@config.values.each(&:reset)
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.app_config(&block)
|
30
|
+
instance_eval(&block)
|
31
|
+
end
|
32
|
+
|
33
|
+
attr_reader :config_name
|
34
|
+
|
35
|
+
def initialize(name)
|
36
|
+
@config_name = name
|
37
|
+
@opts = {}
|
38
|
+
@envs = {}
|
39
|
+
end
|
40
|
+
|
41
|
+
def defaults
|
42
|
+
@defaults ||= Pakyow::Config.new("#{@config_name}.defaults")
|
43
|
+
end
|
44
|
+
|
45
|
+
def env(name)
|
46
|
+
config = Pakyow::Config.new("#{@config_name}.#{name}")
|
47
|
+
yield(config)
|
48
|
+
|
49
|
+
@envs[name] = config
|
50
|
+
self
|
51
|
+
end
|
52
|
+
|
53
|
+
def clear_env(name)
|
54
|
+
@envs.delete(name)
|
55
|
+
end
|
56
|
+
|
57
|
+
def value(name, *args)
|
58
|
+
value = @opts.fetch(name) { raise(ConfigError.new("No config option available for `#{@config_name}.#{name}`")) }
|
59
|
+
value = instance_exec(*args, &value) if value.is_a?(Proc)
|
60
|
+
value
|
61
|
+
end
|
62
|
+
|
63
|
+
def opt(name, default = nil)
|
64
|
+
@opts[name] = default
|
65
|
+
end
|
66
|
+
|
67
|
+
def reset
|
68
|
+
@opts = {}
|
69
|
+
end
|
70
|
+
|
71
|
+
def method_missing(method, *args)
|
72
|
+
if /^(\w+)=$/ =~ method
|
73
|
+
@opts[$1.to_sym] = args[0]
|
74
|
+
else
|
75
|
+
configs = [self]
|
76
|
+
configs << @envs[Config.env] if @envs.key?(Config.env)
|
77
|
+
configs << @defaults unless @defaults.nil?
|
78
|
+
|
79
|
+
configs.each do |config|
|
80
|
+
begin
|
81
|
+
return config.value(method, *args)
|
82
|
+
rescue ConfigError
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
raise(ConfigError.new("No config option available for `#{@config_name}.#{method}`"))
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -2,6 +2,9 @@ module Pakyow
|
|
2
2
|
# Raised when no app context is available
|
3
3
|
class NoContextError < StandardError; end
|
4
4
|
|
5
|
+
# Raised when no config object is available
|
6
|
+
class ConfigError < StandardError; end
|
7
|
+
|
5
8
|
# Raised when route is looked up that doesn't exist
|
6
9
|
class MissingRoute < StandardError; end
|
7
10
|
|
@@ -13,11 +13,11 @@ module Pakyow
|
|
13
13
|
def require_recursively(dir)
|
14
14
|
@times ||= {}
|
15
15
|
if File.exists?(dir)
|
16
|
-
|
16
|
+
Dir.walk(dir) do |path|
|
17
17
|
next if FileTest.directory?(path)
|
18
18
|
next if path.split('.')[-1] != 'rb'
|
19
19
|
|
20
|
-
if Config
|
20
|
+
if Config.app.auto_reload
|
21
21
|
if !@times[path] || (@times[path] && File.mtime(path) - @times[path] > 0)
|
22
22
|
load(path)
|
23
23
|
@times[path] = File.mtime(path)
|
@@ -34,6 +34,7 @@ module Pakyow
|
|
34
34
|
BOLD_SEQ = "\033[1m"
|
35
35
|
|
36
36
|
def initialize(log = $stdout, level = 0, format = false, auto_flush = false)
|
37
|
+
level = LEVELS[level] if level.is_a?(Symbol)
|
37
38
|
@log, @level, @format, @auto_flush = log, level, format, auto_flush
|
38
39
|
@mutex = Mutex.new
|
39
40
|
end
|
@@ -26,7 +26,7 @@ module Pakyow
|
|
26
26
|
def is_static?(env)
|
27
27
|
return false unless env['PATH_INFO'] =~ /\.(.*)$/
|
28
28
|
|
29
|
-
Config
|
29
|
+
Config.app.resources.each_pair do |name, path|
|
30
30
|
resource_path = File.join(path, env['PATH_INFO'])
|
31
31
|
next unless File.exists?(resource_path)
|
32
32
|
return true, resource_path
|
@@ -51,12 +51,12 @@ module Pakyow
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def cookies
|
54
|
-
@cookies ||=
|
54
|
+
@cookies ||= Hash.strhash(super)
|
55
55
|
end
|
56
56
|
|
57
57
|
# Returns indifferent params (see {HashUtils.strhash} for more info on indifferent hashes).
|
58
58
|
def params
|
59
|
-
@params ||=
|
59
|
+
@params ||= Hash.strhash(super)
|
60
60
|
end
|
61
61
|
|
62
62
|
# Returns array of url components.
|
@@ -97,14 +97,14 @@ module Pakyow
|
|
97
97
|
protected
|
98
98
|
|
99
99
|
def set_working_path_from_path(path, method)
|
100
|
-
base_route, ignore_format =
|
100
|
+
base_route, ignore_format = String.split_at_last_dot(path)
|
101
101
|
|
102
102
|
self.path = base_route
|
103
103
|
self.method = method || self.method
|
104
104
|
end
|
105
105
|
|
106
106
|
def set_request_format_from_path(path)
|
107
|
-
path, format =
|
107
|
+
path, format = String.split_at_last_dot(path)
|
108
108
|
self.format = ((format && (format[format.length - 1, 1] == '/')) ? format[0, format.length - 1] : format)
|
109
109
|
end
|
110
110
|
end
|
@@ -73,7 +73,7 @@ module Pakyow
|
|
73
73
|
# build the final list of fns
|
74
74
|
fns = build_fns(fns, hooks)
|
75
75
|
|
76
|
-
@handlers
|
76
|
+
@handlers.unshift([name, code, fns])
|
77
77
|
end
|
78
78
|
|
79
79
|
def group(*args, &block)
|
@@ -108,7 +108,7 @@ module Pakyow
|
|
108
108
|
|
109
109
|
evaluator = RouteExpansionEval.from_scope(self, path: File.join(descendent_path, path), group: g_name, hooks: hooks)
|
110
110
|
evaluator.direct_path = path
|
111
|
-
evaluator.
|
111
|
+
evaluator.set_template(g_name, template)
|
112
112
|
evaluator.eval(&block)
|
113
113
|
|
114
114
|
merge(evaluator)
|
@@ -159,7 +159,7 @@ module Pakyow
|
|
159
159
|
else
|
160
160
|
# prepend scope path if we're in a scope
|
161
161
|
path = File.join(@path, path)
|
162
|
-
path =
|
162
|
+
path = String.normalize_path(path)
|
163
163
|
|
164
164
|
# get regex and vars for path
|
165
165
|
regex, vars = build_route_matcher(path)
|
@@ -316,7 +316,8 @@ module Pakyow
|
|
316
316
|
super
|
317
317
|
end
|
318
318
|
|
319
|
-
def
|
319
|
+
def set_template(expansion_name, template)
|
320
|
+
@expansion_name = expansion_name
|
320
321
|
@template_block = template[1]
|
321
322
|
|
322
323
|
@hooks = merge_hooks(@hooks, template[0])
|
@@ -343,7 +344,7 @@ module Pakyow
|
|
343
344
|
group = @template_eval.group_named(name)
|
344
345
|
|
345
346
|
hooks = merge_hooks(hooks, group[0])
|
346
|
-
group(
|
347
|
+
group(@expansion_name, hooks, &block)
|
347
348
|
end
|
348
349
|
|
349
350
|
def action_namespace(*args, &block)
|
@@ -351,7 +352,7 @@ module Pakyow
|
|
351
352
|
namespace = @template_eval.namespace_named(name)
|
352
353
|
|
353
354
|
hooks = merge_hooks(hooks, namespace[1])
|
354
|
-
namespace(
|
355
|
+
namespace(@expansion_name, namespace[0], hooks, &block)
|
355
356
|
end
|
356
357
|
|
357
358
|
def method_missing(method, *args, &block)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Pakyow
|
2
2
|
module RouteMerger
|
3
|
-
private
|
3
|
+
private
|
4
4
|
|
5
5
|
def merge(route_eval)
|
6
6
|
merge_fns(route_eval.fns)
|
@@ -28,7 +28,7 @@ module Pakyow
|
|
28
28
|
|
29
29
|
def merge_lookup(lookup)
|
30
30
|
@lookup[:routes].merge!(lookup[:routes])
|
31
|
-
@lookup[:grouped].
|
31
|
+
@lookup[:grouped].deep_merge!(lookup[:grouped])
|
32
32
|
end
|
33
33
|
|
34
34
|
def merge_templates(templates)
|
@@ -22,7 +22,7 @@ module Pakyow
|
|
22
22
|
# [regex, vars, name, fns, path]
|
23
23
|
#
|
24
24
|
def match(path, method)
|
25
|
-
path =
|
25
|
+
path = String.normalize_path(path)
|
26
26
|
|
27
27
|
# want the request to still knows it's a head, but match as get
|
28
28
|
method = method.to_sym
|
@@ -88,7 +88,7 @@ module Pakyow
|
|
88
88
|
else
|
89
89
|
app.instance_exec(&fn)
|
90
90
|
end
|
91
|
-
|
91
|
+
|
92
92
|
break
|
93
93
|
end
|
94
94
|
}
|
@@ -106,7 +106,7 @@ module Pakyow
|
|
106
106
|
# returns the list of route functions for that route.
|
107
107
|
#
|
108
108
|
def match(request)
|
109
|
-
path =
|
109
|
+
path = String.normalize_path(request.path)
|
110
110
|
method = request.method
|
111
111
|
|
112
112
|
match, data = nil
|
@@ -121,7 +121,7 @@ module Pakyow
|
|
121
121
|
|
122
122
|
# handle route params
|
123
123
|
#TODO where to do this?
|
124
|
-
request.params.merge!(
|
124
|
+
request.params.merge!(Hash.strhash(self.data_from_path(path, data, match[1])))
|
125
125
|
|
126
126
|
#TODO where to do this?
|
127
127
|
request.route_path = match[4]
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pakyow-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bryan Powell
|
@@ -9,8 +9,22 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-11-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: pakyow-support
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - '='
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: 0.9.0
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - '='
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: 0.9.0
|
14
28
|
- !ruby/object:Gem::Dependency
|
15
29
|
name: rack
|
16
30
|
requirement: !ruby/object:Gem::Requirement
|
@@ -39,7 +53,7 @@ dependencies:
|
|
39
53
|
- - "~>"
|
40
54
|
- !ruby/object:Gem::Version
|
41
55
|
version: '5.0'
|
42
|
-
description: Core functionality for Pakyow
|
56
|
+
description: Core functionality for Pakyow apps, including routing and middleware.
|
43
57
|
email: bryan@metabahn.com
|
44
58
|
executables: []
|
45
59
|
extensions: []
|
@@ -51,8 +65,8 @@ files:
|
|
51
65
|
- pakyow-core/lib/core/app.rb
|
52
66
|
- pakyow-core/lib/core/app_context.rb
|
53
67
|
- pakyow-core/lib/core/base.rb
|
68
|
+
- pakyow-core/lib/core/config.rb
|
54
69
|
- pakyow-core/lib/core/config/app.rb
|
55
|
-
- pakyow-core/lib/core/config/base.rb
|
56
70
|
- pakyow-core/lib/core/config/cookies.rb
|
57
71
|
- pakyow-core/lib/core/config/logger.rb
|
58
72
|
- pakyow-core/lib/core/config/server.rb
|
@@ -73,9 +87,6 @@ files:
|
|
73
87
|
- pakyow-core/lib/core/route_template_defaults.rb
|
74
88
|
- pakyow-core/lib/core/router.rb
|
75
89
|
- pakyow-core/lib/pakyow-core.rb
|
76
|
-
- pakyow-core/lib/utils/dir.rb
|
77
|
-
- pakyow-core/lib/utils/hash.rb
|
78
|
-
- pakyow-core/lib/utils/string.rb
|
79
90
|
- pakyow-core/lib/views/errors/404.html
|
80
91
|
- pakyow-core/lib/views/errors/500.html
|
81
92
|
homepage: http://pakyow.com
|
@@ -90,7 +101,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
90
101
|
requirements:
|
91
102
|
- - ">="
|
92
103
|
- !ruby/object:Gem::Version
|
93
|
-
version:
|
104
|
+
version: 2.0.0
|
94
105
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
106
|
requirements:
|
96
107
|
- - ">="
|
@@ -98,8 +109,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
98
109
|
version: '0'
|
99
110
|
requirements: []
|
100
111
|
rubyforge_project: pakyow-core
|
101
|
-
rubygems_version: 2.2.
|
112
|
+
rubygems_version: 2.2.2
|
102
113
|
signing_key:
|
103
114
|
specification_version: 4
|
104
|
-
summary: Core functionality for Pakyow
|
115
|
+
summary: Core functionality for Pakyow apps.
|
105
116
|
test_files: []
|
117
|
+
has_rdoc:
|
@@ -1,30 +0,0 @@
|
|
1
|
-
module Pakyow
|
2
|
-
module Config
|
3
|
-
class Base
|
4
|
-
@@configs = {}
|
5
|
-
def self.register_config(name, klass)
|
6
|
-
@@configs[name] = klass
|
7
|
-
|
8
|
-
define_singleton_method name do
|
9
|
-
@@configs[name]
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
# Resets all config
|
14
|
-
def self.reset!
|
15
|
-
@@configs.keys.each do |type|
|
16
|
-
klass = self.send(type.to_sym)
|
17
|
-
klass.instance_variables.each do |var|
|
18
|
-
# Assumes path shouldn't be reset, since it's only set
|
19
|
-
# once when Pakyow::Application is inherited.
|
20
|
-
next if var.to_sym == :'@path'
|
21
|
-
begin
|
22
|
-
klass.send("#{var.to_s.gsub('@', '')}=", nil)
|
23
|
-
rescue
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
@@ -1,40 +0,0 @@
|
|
1
|
-
module Pakyow
|
2
|
-
module Utils
|
3
|
-
|
4
|
-
# Utility methods for directories and files.
|
5
|
-
class Dir
|
6
|
-
|
7
|
-
# visit dir, then all files in dir, then walk_dir each directory in dir
|
8
|
-
def self.walk_dir(dir, &block)
|
9
|
-
yield dir
|
10
|
-
all = ::Dir.entries(dir)
|
11
|
-
partition = all.partition{|e| File.file?("#{dir}/#{e}")}
|
12
|
-
files = partition[0]
|
13
|
-
dirs = partition[1]
|
14
|
-
files.each{|f| yield "#{dir}/#{f}" unless f.start_with?(".")}
|
15
|
-
dirs.each{|d| walk_dir("#{dir}/#{d}", &block) unless d.start_with?(".")}
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.print_dir(dir)
|
19
|
-
puts "/#{dir}"
|
20
|
-
Utils::Dir.walk_dir(dir) {|full_path|
|
21
|
-
path = full_path.gsub(Regexp.new("#{dir}\/?"), '')
|
22
|
-
next if path.empty?
|
23
|
-
|
24
|
-
prefix = "|"
|
25
|
-
path.scan(/\//).size.times do
|
26
|
-
prefix += " |"
|
27
|
-
end
|
28
|
-
|
29
|
-
path.gsub!(/^.*\//, '')
|
30
|
-
puts "#{prefix}-- #{path}"
|
31
|
-
}
|
32
|
-
end
|
33
|
-
|
34
|
-
def self.dir_within_dir?(dir1, dir2)
|
35
|
-
(dir1.split('/') - dir2.split('/')).empty?
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
end
|
40
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
module Pakyow
|
2
|
-
module Utils
|
3
|
-
|
4
|
-
# Utility methods for hashes.
|
5
|
-
class Hash
|
6
|
-
# Creates an indifferent hash. This means that when indifferentized, this hash:
|
7
|
-
# { 'foo' => 'bar' }
|
8
|
-
#
|
9
|
-
# Can be accessed like this:
|
10
|
-
# { :foo => 'bar' }
|
11
|
-
#
|
12
|
-
def self.strhash(hash)
|
13
|
-
indifferentize(hash)
|
14
|
-
end
|
15
|
-
|
16
|
-
# Converts keys to symbols.
|
17
|
-
def self.symbolize_keys(hash)
|
18
|
-
::Hash[hash.map{|(k,v)| [k.to_sym,v]}]
|
19
|
-
end
|
20
|
-
|
21
|
-
# Converts keys/values to symbols.
|
22
|
-
def self.symbolize(hash)
|
23
|
-
::Hash[hash.map{|(k,v)| [k.to_sym,v.to_sym]}]
|
24
|
-
end
|
25
|
-
|
26
|
-
protected
|
27
|
-
|
28
|
-
# (see {strhash})
|
29
|
-
def self.indifferentize(hash)
|
30
|
-
hash.each_pair do |key, value|
|
31
|
-
hash[key] = indifferentize(value) if value.is_a? ::Hash
|
32
|
-
end
|
33
|
-
|
34
|
-
indifferent_hash.merge(hash)
|
35
|
-
end
|
36
|
-
|
37
|
-
# (see {strhash})
|
38
|
-
def self.indifferent_hash
|
39
|
-
::Hash.new { |hash,key| hash[key.to_s] if Symbol === key }
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
end
|
44
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
module Pakyow
|
2
|
-
module Utils
|
3
|
-
|
4
|
-
# Utility methods for strings.
|
5
|
-
class String
|
6
|
-
|
7
|
-
# split . seperated string at the last .
|
8
|
-
def self.split_at_last_dot(s)
|
9
|
-
split_index = s.rindex('.')
|
10
|
-
return s,nil unless split_index
|
11
|
-
left = s[0,split_index]
|
12
|
-
right = s[split_index+1,s.length-(split_index+1)]
|
13
|
-
return left,right
|
14
|
-
end
|
15
|
-
|
16
|
-
def self.remove_route_vars(route_spec)
|
17
|
-
return unless route_spec
|
18
|
-
arr = route_spec.split('/')
|
19
|
-
new_arr = []
|
20
|
-
arr.each {|e| new_arr << e unless e[0,1] == ':'}
|
21
|
-
ret = new_arr.join('/')
|
22
|
-
return '/' if ret == ''
|
23
|
-
return ret
|
24
|
-
end
|
25
|
-
|
26
|
-
def self.parse_path_from_caller(caller)
|
27
|
-
caller.match(/^(.+)(:?:\d+(:?:in `.+')?$)/)[1]
|
28
|
-
end
|
29
|
-
|
30
|
-
def self.normalize_path(path)
|
31
|
-
return path if path.is_a?(Regexp)
|
32
|
-
|
33
|
-
path = path[1, path.length - 1] if path[0, 1] == '/'
|
34
|
-
path = path[0, path.length - 1] if path[path.length - 1, 1] == '/'
|
35
|
-
path
|
36
|
-
end
|
37
|
-
|
38
|
-
end
|
39
|
-
|
40
|
-
end
|
41
|
-
end
|