syntropy 0.25 → 0.27
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/CHANGELOG.md +17 -0
- data/examples/index.md +1 -1
- data/lib/syntropy/app.rb +21 -10
- data/lib/syntropy/applets/builtin/default_error_handler/style.css +18 -0
- data/lib/syntropy/applets/builtin/default_error_handler.rb +58 -0
- data/lib/syntropy/applets/builtin/json_api.js +1 -1
- data/lib/syntropy/applets/builtin/req.rb +7 -0
- data/lib/syntropy/errors.rb +4 -4
- data/lib/syntropy/module.rb +33 -23
- data/lib/syntropy/request_extensions.rb +47 -1
- data/lib/syntropy/version.rb +1 -1
- data/syntropy.gemspec +1 -1
- data/test/app/_lib/callable.rb +1 -1
- data/test/app/_lib/dep.rb +1 -1
- data/test/app/_lib/missing-export.rb +1 -1
- data/test/app/mod/path/a.rb +3 -0
- data/test/app/mod/path/b.rb +8 -0
- data/test/test_module.rb +18 -7
- data/test/test_routing_tree.rb +1 -1
- metadata +8 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b84251781cfce3688f58c6f25a754b0699d97fe4a7c51f390b63635b45007960
|
|
4
|
+
data.tar.gz: 69e85137dcee6b399d3198303f9de4227b5276521a6c964eca5ac4954a9fb10f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dd871276c35cd2a9c216f37ec1361794e34f489af71580a1da5cebef244830daf0e2bc4e418abe28623607e8da5693ead8074dd1f397ba9ea61afb0e4bcf7d96
|
|
7
|
+
data.tar.gz: 2b3ae1c3c4691d247357a8ec3d9f7e3da778c0fcdd7a94de84b2d83c94ffe75c7beb7ec7883976c2ca09b5c45225391b9322e28a32be9cc3a55acfc6d8c5ac9e
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
# 0.27 2025-10-21
|
|
2
|
+
|
|
3
|
+
- Use accept header (instead of user-agent) for rendering error page
|
|
4
|
+
- Add `Request#accept?` method
|
|
5
|
+
- Fix import path normalization, module method visibility
|
|
6
|
+
- Fix instantiation of Syntropy::Error
|
|
7
|
+
- Improve default error handler response
|
|
8
|
+
- Fix and enhance `Request#html_response`, `Request#json_response` methods
|
|
9
|
+
|
|
10
|
+
# 0.26 2025-10-21
|
|
11
|
+
|
|
12
|
+
- Add /.syntropy/req route for testing request headers
|
|
13
|
+
- Add default builtin error page / response
|
|
14
|
+
- Add `Request#browser?` method for detecting browser
|
|
15
|
+
- Change behaviour of import to support relative paths
|
|
16
|
+
- Update Papercraft
|
|
17
|
+
|
|
1
18
|
# 0.25 2025-10-19
|
|
2
19
|
|
|
3
20
|
- Upgrade Papercraft to version 3.0
|
data/examples/index.md
CHANGED
data/lib/syntropy/app.rb
CHANGED
|
@@ -168,7 +168,7 @@ module Syntropy
|
|
|
168
168
|
end
|
|
169
169
|
|
|
170
170
|
# Serves a static file from the given target hash with cache validation.
|
|
171
|
-
#
|
|
171
|
+
#
|
|
172
172
|
# @param req [Qeweney::Request] request
|
|
173
173
|
# @param target [Hash] route target hash
|
|
174
174
|
# @return [void]
|
|
@@ -190,7 +190,7 @@ module Syntropy
|
|
|
190
190
|
|
|
191
191
|
# Validates and conditionally updates the file information for the given
|
|
192
192
|
# target.
|
|
193
|
-
#
|
|
193
|
+
#
|
|
194
194
|
# @param target [Hash] route target hash
|
|
195
195
|
# @return [void]
|
|
196
196
|
def validate_static_file_info(target)
|
|
@@ -203,7 +203,7 @@ module Syntropy
|
|
|
203
203
|
STATX_MASK = UM::STATX_MTIME | UM::STATX_SIZE
|
|
204
204
|
|
|
205
205
|
# Updates the static file information for the given target
|
|
206
|
-
#
|
|
206
|
+
#
|
|
207
207
|
# @param target [Hash] route target hash
|
|
208
208
|
# @param now [Time] current time
|
|
209
209
|
# @return [void]
|
|
@@ -373,12 +373,6 @@ module Syntropy
|
|
|
373
373
|
@module_loader.load(ref)
|
|
374
374
|
end
|
|
375
375
|
|
|
376
|
-
DEFAULT_ERROR_HANDLER = ->(req, err) {
|
|
377
|
-
msg = err.message
|
|
378
|
-
msg = nil if msg.empty? || (req.method == 'head')
|
|
379
|
-
req.respond(msg, ':status' => Syntropy::Error.http_status(err)) rescue nil
|
|
380
|
-
}
|
|
381
|
-
|
|
382
376
|
# Returns an error handler for the given route. If route is nil, looks up
|
|
383
377
|
# the error handler for the routing tree root. If no handler is found,
|
|
384
378
|
# returns the default error handler.
|
|
@@ -386,7 +380,7 @@ module Syntropy
|
|
|
386
380
|
# @param route [Hash] route entry
|
|
387
381
|
# @return [Proc] error handler proc
|
|
388
382
|
def get_error_handler(route)
|
|
389
|
-
route_error_handler(route || @routing_tree.root) ||
|
|
383
|
+
route_error_handler(route || @routing_tree.root) || default_error_handler
|
|
390
384
|
end
|
|
391
385
|
|
|
392
386
|
# Returns the given route's error handler, caching the result.
|
|
@@ -420,6 +414,23 @@ module Syntropy
|
|
|
420
414
|
route[:parent] && find_error_handler(route[:parent])
|
|
421
415
|
end
|
|
422
416
|
|
|
417
|
+
RAW_DEFAULT_ERROR_HANDLER = ->(req, err) {
|
|
418
|
+
msg = err.message
|
|
419
|
+
msg = nil if msg.empty? || (req.method == 'head')
|
|
420
|
+
req.respond(msg, ':status' => Syntropy::Error.http_status(err)) rescue nil
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
def default_error_handler
|
|
424
|
+
|
|
425
|
+
@default_error_handler ||= begin
|
|
426
|
+
if @builtin_applet
|
|
427
|
+
@builtin_applet.module_loader.load('/default_error_handler')
|
|
428
|
+
else
|
|
429
|
+
RAW_DEFAULT_ERROR_HANDLER
|
|
430
|
+
end
|
|
431
|
+
end
|
|
432
|
+
end
|
|
433
|
+
|
|
423
434
|
# Performs app start up, creating a log message and starting the file
|
|
424
435
|
# watcher according to app options.
|
|
425
436
|
#
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
body {
|
|
2
|
+
max-width: 800px;
|
|
3
|
+
margin: 4em auto;
|
|
4
|
+
|
|
5
|
+
font-family: Seravek, 'Gill Sans Nova', Ubuntu, Calibri, 'DejaVu Sans', source-sans-pro, sans-serif;
|
|
6
|
+
|
|
7
|
+
big {
|
|
8
|
+
display: block;
|
|
9
|
+
font-weight: bold;
|
|
10
|
+
font-size: 10em;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
@media (max-width: 768px) {
|
|
15
|
+
body {
|
|
16
|
+
margin-inline: 1em;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
ErrorPage = ->(error:, status:, backtrace:) {
|
|
4
|
+
html {
|
|
5
|
+
head {
|
|
6
|
+
title "Syntropy error: #{error.message}"
|
|
7
|
+
meta charset: 'utf-8'
|
|
8
|
+
meta name: 'viewport', content: 'width=device-width, initial-scale=1.0'
|
|
9
|
+
link rel: 'stylesheet', type: 'text/css', href: '/.syntropy/default_error_handler/style.css'
|
|
10
|
+
}
|
|
11
|
+
body {
|
|
12
|
+
div {
|
|
13
|
+
big status
|
|
14
|
+
h2 error.message
|
|
15
|
+
if backtrace
|
|
16
|
+
p "Backtrace:"
|
|
17
|
+
ul {
|
|
18
|
+
backtrace.each {
|
|
19
|
+
li {
|
|
20
|
+
a(it[:entry], href: it[:url])
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
end
|
|
25
|
+
}
|
|
26
|
+
auto_refresh_watch!
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
def transform_backtrace(backtrace)
|
|
32
|
+
backtrace.map do
|
|
33
|
+
location = it.match(/^(.+:\d+):/)[1]
|
|
34
|
+
{ entry: it, url: "vscode://file/#{location}" }
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def error_response_html(req, error)
|
|
39
|
+
status = Syntropy::Error.http_status(error)
|
|
40
|
+
backtrace = transform_backtrace(error.backtrace)
|
|
41
|
+
html = Papercraft.html(ErrorPage, error:, status:, backtrace:)
|
|
42
|
+
req.html_response(html, ':status' => status)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def error_response_raw(req, error)
|
|
46
|
+
status = Syntropy::Error.http_status(error)
|
|
47
|
+
response = {
|
|
48
|
+
class: error.class.to_s,
|
|
49
|
+
message: error.message,
|
|
50
|
+
backtrace: error.backtrace
|
|
51
|
+
}
|
|
52
|
+
req.json_pretty_response(response, ':status' => status)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
export ->(req, error) {
|
|
56
|
+
req.accept?('text/html') ?
|
|
57
|
+
error_response_html(req, error) : error_response_raw(req, error)
|
|
58
|
+
}
|
data/lib/syntropy/errors.rb
CHANGED
|
@@ -21,17 +21,17 @@ module Syntropy
|
|
|
21
21
|
# Creates an error with status 404 Not Found
|
|
22
22
|
#
|
|
23
23
|
# @return [Syntropy::Error]
|
|
24
|
-
def self.not_found(msg = '') = new(Status::NOT_FOUND
|
|
24
|
+
def self.not_found(msg = 'Not found') = new(msg, Status::NOT_FOUND)
|
|
25
25
|
|
|
26
26
|
# Creates an error with status 405 Method Not Allowed
|
|
27
27
|
#
|
|
28
28
|
# @return [Syntropy::Error]
|
|
29
|
-
def self.method_not_allowed(msg = '') = new(Status::METHOD_NOT_ALLOWED
|
|
29
|
+
def self.method_not_allowed(msg = 'Method not allowed') = new(msg, Status::METHOD_NOT_ALLOWED)
|
|
30
30
|
|
|
31
31
|
# Creates an error with status 418 I'm a teapot
|
|
32
32
|
#
|
|
33
33
|
# @return [Syntropy::Error]
|
|
34
|
-
def self.teapot(msg = '') = new(Status::TEAPOT
|
|
34
|
+
def self.teapot(msg = 'I\'m a teapot') = new(msg, Status::TEAPOT)
|
|
35
35
|
|
|
36
36
|
attr_reader :http_status
|
|
37
37
|
|
|
@@ -40,7 +40,7 @@ module Syntropy
|
|
|
40
40
|
# @param http_status [Integer, String] HTTP status
|
|
41
41
|
# @param msg [String] error message
|
|
42
42
|
# @return [void]
|
|
43
|
-
def initialize(
|
|
43
|
+
def initialize(msg = 'Internal server error', http_status = DEFAULT_STATUS)
|
|
44
44
|
super(msg)
|
|
45
45
|
@http_status = http_status
|
|
46
46
|
end
|
data/lib/syntropy/module.rb
CHANGED
|
@@ -38,6 +38,8 @@ module Syntropy
|
|
|
38
38
|
# @param ref [String] module reference
|
|
39
39
|
# @return [any] export value
|
|
40
40
|
def load(ref)
|
|
41
|
+
ref = "/#{ref}" if ref !~ /^\//
|
|
42
|
+
|
|
41
43
|
entry = (@modules[ref] ||= load_module(ref))
|
|
42
44
|
entry[:export_value]
|
|
43
45
|
end
|
|
@@ -93,6 +95,7 @@ module Syntropy
|
|
|
93
95
|
# @param ref [String] module reference
|
|
94
96
|
# @return [Hash] module entry
|
|
95
97
|
def load_module(ref)
|
|
98
|
+
ref = "/#{ref}" if ref !~ /^\//
|
|
96
99
|
fn = File.expand_path(File.join(@root_dir, "#{ref}.rb"))
|
|
97
100
|
raise Syntropy::Error, "File not found #{fn}" if !File.file?(fn)
|
|
98
101
|
|
|
@@ -112,8 +115,9 @@ module Syntropy
|
|
|
112
115
|
|
|
113
116
|
def clean_ref(ref)
|
|
114
117
|
return '/' if ref =~ /^index(\+)?$/
|
|
115
|
-
|
|
116
|
-
ref.gsub(/\/index(?:\+)?$/, '')
|
|
118
|
+
|
|
119
|
+
clean = ref.gsub(/\/index(?:\+)?$/, '')
|
|
120
|
+
clean == '' ? '/' : clean
|
|
117
121
|
end
|
|
118
122
|
|
|
119
123
|
# Transforms the given export value. If the value is nil, an exception is
|
|
@@ -177,10 +181,21 @@ module Syntropy
|
|
|
177
181
|
@app = env[:app]
|
|
178
182
|
@ref = env[:ref]
|
|
179
183
|
@logger = env[:logger]
|
|
184
|
+
@__dependencies__ = []
|
|
180
185
|
singleton_class.const_set(:MODULE, self)
|
|
181
186
|
end
|
|
182
187
|
|
|
183
|
-
attr_reader :__export_value__
|
|
188
|
+
attr_reader :__export_value__, :__dependencies__
|
|
189
|
+
|
|
190
|
+
# Returns a list of pages found at the given ref.
|
|
191
|
+
#
|
|
192
|
+
# @param ref [String] directory reference
|
|
193
|
+
# @return [Array] array of pages found in directory
|
|
194
|
+
def page_list(ref)
|
|
195
|
+
Syntropy.page_list(@env, ref)
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
private
|
|
184
199
|
|
|
185
200
|
# Exports the given value. This value will be used as the module's
|
|
186
201
|
# entrypoint. It can be any Ruby value, but for a route module would
|
|
@@ -192,22 +207,23 @@ module Syntropy
|
|
|
192
207
|
@__export_value__ = v
|
|
193
208
|
end
|
|
194
209
|
|
|
195
|
-
# Returns the list of module references imported by the module.
|
|
196
|
-
#
|
|
197
|
-
# @return [Array] array of module references
|
|
198
|
-
def __dependencies__
|
|
199
|
-
@__dependencies__ ||= []
|
|
200
|
-
end
|
|
201
|
-
|
|
202
210
|
# Imports the module corresponding to the given reference. The return value
|
|
203
211
|
# is the module's export value.
|
|
204
212
|
#
|
|
205
213
|
# @param ref [String] module reference
|
|
206
214
|
# @return [any] loaded dependency's export value
|
|
207
215
|
def import(ref)
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
216
|
+
ref = normalize_import_ref(ref)
|
|
217
|
+
@module_loader.load(ref).tap { __dependencies__ << ref }
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def normalize_import_ref(ref)
|
|
221
|
+
base = @ref == '' ? '/' : @ref
|
|
222
|
+
if ref =~ /^\//
|
|
223
|
+
ref
|
|
224
|
+
else
|
|
225
|
+
File.expand_path(File.join(File.dirname(base), ref))
|
|
226
|
+
end
|
|
211
227
|
end
|
|
212
228
|
|
|
213
229
|
# Creates and returns a Papercraft template created with the given block.
|
|
@@ -238,19 +254,13 @@ module Syntropy
|
|
|
238
254
|
raise
|
|
239
255
|
end
|
|
240
256
|
|
|
241
|
-
#
|
|
242
|
-
#
|
|
243
|
-
# @param ref [String] directory reference
|
|
244
|
-
# @return [Array] array of pages found in directory
|
|
245
|
-
def page_list(ref)
|
|
246
|
-
Syntropy.page_list(@env, ref)
|
|
247
|
-
end
|
|
248
|
-
|
|
249
|
-
# Creates and returns a Syntropy app for the given environment.
|
|
257
|
+
# Creates and returns a Syntropy app for the given environment. The app's
|
|
258
|
+
# environment is based on the module's env merged with the given parameters.
|
|
250
259
|
#
|
|
251
260
|
# @param env [Hash] environment
|
|
252
261
|
def app(**env)
|
|
253
|
-
|
|
262
|
+
env = @env.merge(env)
|
|
263
|
+
Syntropy::App.new(**env)
|
|
254
264
|
end
|
|
255
265
|
end
|
|
256
266
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'qeweney'
|
|
4
|
+
require 'json'
|
|
4
5
|
|
|
5
6
|
module Syntropy
|
|
6
7
|
# Extensions for the Qeweney::Request class
|
|
@@ -144,7 +145,7 @@ module Syntropy
|
|
|
144
145
|
# matches the given etag or last_modified values, responds with a 304 Not
|
|
145
146
|
# Modified status. Otherwise, yields to the given block for a normal
|
|
146
147
|
# response, and sets cache control headers according to the given arguments.
|
|
147
|
-
#
|
|
148
|
+
#
|
|
148
149
|
# @param cache_control [String] value for Cache-Control header
|
|
149
150
|
# @param etag [String, nil] Etag header value
|
|
150
151
|
# @param last_modified [String, nil] Last-Modified header value
|
|
@@ -184,8 +185,53 @@ module Syntropy
|
|
|
184
185
|
raise Syntropy::Error.new(Qeweney::Status::BAD_REQUEST, 'Invalid form data')
|
|
185
186
|
end
|
|
186
187
|
|
|
188
|
+
def html_response(html, **headers)
|
|
189
|
+
respond(
|
|
190
|
+
html,
|
|
191
|
+
'Content-Type' => 'text/html; charset=utf-8',
|
|
192
|
+
**headers
|
|
193
|
+
)
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def json_response(obj, **headers)
|
|
197
|
+
respond(
|
|
198
|
+
JSON.dump(obj),
|
|
199
|
+
'Content-Type' => 'application/json; charset=utf-8',
|
|
200
|
+
**headers
|
|
201
|
+
)
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def json_pretty_response(obj, **headers)
|
|
205
|
+
respond(
|
|
206
|
+
JSON.pretty_generate(obj),
|
|
207
|
+
'Content-Type' => 'application/json; charset=utf-8',
|
|
208
|
+
**headers
|
|
209
|
+
)
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def browser?
|
|
213
|
+
user_agent = headers['user-agent']
|
|
214
|
+
user_agent && user_agent =~ /^Mozilla\//
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
# Returns true if the accept header includes the given MIME type
|
|
218
|
+
#
|
|
219
|
+
# @param mime_type [String] MIME type
|
|
220
|
+
# @return [bool]
|
|
221
|
+
def accept?(mime_type)
|
|
222
|
+
accept = headers['accept']
|
|
223
|
+
return nil if !accept
|
|
224
|
+
|
|
225
|
+
@accept_parts ||= parse_accept_parts(accept)
|
|
226
|
+
@accept_parts.include?(mime_type)
|
|
227
|
+
end
|
|
228
|
+
|
|
187
229
|
private
|
|
188
230
|
|
|
231
|
+
def parse_accept_parts(accept)
|
|
232
|
+
accept.split(',').map { it.match(/^\s*([^\s;]+)/)[1] }
|
|
233
|
+
end
|
|
234
|
+
|
|
189
235
|
BOOL_REGEXP = /^(t|f|true|false|on|off|1|0|yes|no)$/
|
|
190
236
|
BOOL_TRUE_REGEXP = /^(t|true|on|1|yes)$/
|
|
191
237
|
INTEGER_REGEXP = /^[+-]?[0-9]+$/
|
data/lib/syntropy/version.rb
CHANGED
data/syntropy.gemspec
CHANGED
|
@@ -23,7 +23,7 @@ Gem::Specification.new do |s|
|
|
|
23
23
|
|
|
24
24
|
s.add_dependency 'extralite', '2.13'
|
|
25
25
|
s.add_dependency 'json', '2.13.2'
|
|
26
|
-
s.add_dependency 'papercraft', '3.0'
|
|
26
|
+
s.add_dependency 'papercraft', '3.0.1'
|
|
27
27
|
s.add_dependency 'qeweney', '0.24'
|
|
28
28
|
s.add_dependency 'tp2', '0.19'
|
|
29
29
|
s.add_dependency 'uringmachine', '0.18'
|
data/test/app/_lib/callable.rb
CHANGED
data/test/app/_lib/dep.rb
CHANGED
data/test/test_module.rb
CHANGED
|
@@ -29,6 +29,17 @@ class ModuleTest < Minitest::Test
|
|
|
29
29
|
assert_equal 43, mod.bar
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
+
def test_import_paths
|
|
33
|
+
mod = @loader.load('/mod/path/b')
|
|
34
|
+
assert_kind_of Hash, mod
|
|
35
|
+
assert_equal [:a1, :a2, :foo, :callable], mod.keys
|
|
36
|
+
|
|
37
|
+
assert_equal :foo, mod[:a1]
|
|
38
|
+
assert_equal :foo, mod[:a2]
|
|
39
|
+
assert_kind_of Syntropy::Module, mod[:foo]
|
|
40
|
+
assert_equal 'barbarbar', mod[:callable].(3)
|
|
41
|
+
end
|
|
42
|
+
|
|
32
43
|
def test_export_self
|
|
33
44
|
mod = @loader.load('_lib/self')
|
|
34
45
|
assert_kind_of Syntropy::Module, mod
|
|
@@ -39,23 +50,23 @@ class ModuleTest < Minitest::Test
|
|
|
39
50
|
mod = @loader.load('_lib/env')
|
|
40
51
|
|
|
41
52
|
assert_equal mod, mod.module_const
|
|
42
|
-
assert_equal @env.merge(module_loader: @loader, ref: '_lib/env'), mod.env
|
|
53
|
+
assert_equal @env.merge(module_loader: @loader, ref: '/_lib/env'), mod.env
|
|
43
54
|
assert_equal @machine, mod.machine
|
|
44
55
|
assert_equal @loader, mod.module_loader
|
|
45
56
|
assert_equal 42, mod.app
|
|
46
57
|
|
|
47
58
|
assert_equal mod, mod.module_const
|
|
48
|
-
assert_equal @env.merge(module_loader: @loader, ref: '_lib/env'), mod.env
|
|
59
|
+
assert_equal @env.merge(module_loader: @loader, ref: '/_lib/env'), mod.env
|
|
49
60
|
assert_equal @machine, mod.machine
|
|
50
61
|
assert_equal @loader, mod.module_loader
|
|
51
62
|
assert_equal 42, mod.app
|
|
52
63
|
end
|
|
53
64
|
|
|
54
65
|
def test_dependency_invalidation
|
|
55
|
-
|
|
56
|
-
assert_equal ['_lib/self', '_lib/dep'], @loader.modules.keys
|
|
66
|
+
_mod = @loader.load('_lib/dep')
|
|
67
|
+
assert_equal ['/_lib/self', '/_lib/dep'], @loader.modules.keys
|
|
57
68
|
|
|
58
|
-
self_fn = @loader.modules['_lib/self'][:fn]
|
|
69
|
+
self_fn = @loader.modules['/_lib/self'][:fn]
|
|
59
70
|
@loader.invalidate_fn(self_fn)
|
|
60
71
|
|
|
61
72
|
assert_equal [], @loader.modules.keys
|
|
@@ -63,9 +74,9 @@ class ModuleTest < Minitest::Test
|
|
|
63
74
|
|
|
64
75
|
def test_index_module_env
|
|
65
76
|
mod = @loader.load('mod/bar/index+')
|
|
66
|
-
assert_equal 'mod/bar', mod.env[:ref]
|
|
77
|
+
assert_equal '/mod/bar', mod.env[:ref]
|
|
67
78
|
|
|
68
79
|
mod = @loader.load('mod/foo/index')
|
|
69
|
-
assert_equal 'mod/foo', mod.env[:ref]
|
|
80
|
+
assert_equal '/mod/foo', mod.env[:ref]
|
|
70
81
|
end
|
|
71
82
|
end
|
data/test/test_routing_tree.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: syntropy
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: '0.
|
|
4
|
+
version: '0.27'
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sharon Rosner
|
|
@@ -43,14 +43,14 @@ dependencies:
|
|
|
43
43
|
requirements:
|
|
44
44
|
- - '='
|
|
45
45
|
- !ruby/object:Gem::Version
|
|
46
|
-
version:
|
|
46
|
+
version: 3.0.1
|
|
47
47
|
type: :runtime
|
|
48
48
|
prerelease: false
|
|
49
49
|
version_requirements: !ruby/object:Gem::Requirement
|
|
50
50
|
requirements:
|
|
51
51
|
- - '='
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
|
-
version:
|
|
53
|
+
version: 3.0.1
|
|
54
54
|
- !ruby/object:Gem::Dependency
|
|
55
55
|
name: qeweney
|
|
56
56
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -203,8 +203,11 @@ files:
|
|
|
203
203
|
- lib/syntropy/applets/builtin/auto_refresh/watch.sse.rb
|
|
204
204
|
- lib/syntropy/applets/builtin/debug/debug.css
|
|
205
205
|
- lib/syntropy/applets/builtin/debug/debug.js
|
|
206
|
+
- lib/syntropy/applets/builtin/default_error_handler.rb
|
|
207
|
+
- lib/syntropy/applets/builtin/default_error_handler/style.css
|
|
206
208
|
- lib/syntropy/applets/builtin/json_api.js
|
|
207
209
|
- lib/syntropy/applets/builtin/ping.rb
|
|
210
|
+
- lib/syntropy/applets/builtin/req.rb
|
|
208
211
|
- lib/syntropy/connection_pool.rb
|
|
209
212
|
- lib/syntropy/dev_mode.rb
|
|
210
213
|
- lib/syntropy/errors.rb
|
|
@@ -238,6 +241,8 @@ files:
|
|
|
238
241
|
- test/app/index.html
|
|
239
242
|
- test/app/mod/bar/index+.rb
|
|
240
243
|
- test/app/mod/foo/index.rb
|
|
244
|
+
- test/app/mod/path/a.rb
|
|
245
|
+
- test/app/mod/path/b.rb
|
|
241
246
|
- test/app/params/[foo].rb
|
|
242
247
|
- test/app/rss.rb
|
|
243
248
|
- test/app/tmp.rb
|