pakyow-core 0.8.0 → 0.9.0
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/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
|