syntropy 0.12 → 0.13.1
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 +5 -0
- data/TODO.md +5 -0
- data/lib/syntropy/app.rb +10 -7
- data/lib/syntropy/module.rb +41 -78
- data/lib/syntropy/routing_tree.rb +72 -75
- data/lib/syntropy/utils.rb +41 -0
- data/lib/syntropy/version.rb +1 -1
- data/lib/syntropy.rb +3 -0
- data/test/app/_lib/callable.rb +1 -1
- data/test/app/_lib/env.rb +21 -0
- data/test/app/tmp.rb +1 -1
- data/test/app_multi_site/_site.rb +1 -1
- data/test/test_module.rb +15 -5
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dad58d19dc755d1a8ea6adb32cd7146b2228b5ace655a01b2e7932fd8abb7d23
|
4
|
+
data.tar.gz: 228678e0a76e67b012e52c89f5ed90c3d08e884a6424c0c51fcf9f840b2e6876
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5ea7c453ae3e32d17f4bc35204fcf4c29f4eae7d95e9232f56b6ff65dcfaab9f3f6e41fb5562817ab3d3bd10a3ee2e5c92c440045bbdc8a51bc88d155fac7ab4
|
7
|
+
data.tar.gz: fb28a9011ea58505b9923589b62f0010eb97dea9f1df81e4c0483682669715c455fff5a150888f06f117e127497a98e7c93535f683d924e86ffcfeb007cf9fc5
|
data/CHANGELOG.md
CHANGED
data/TODO.md
CHANGED
data/lib/syntropy/app.rb
CHANGED
@@ -23,10 +23,10 @@ module Syntropy
|
|
23
23
|
|
24
24
|
# for apps with a _site.rb file
|
25
25
|
def site_file_app(opts)
|
26
|
-
|
27
|
-
return nil if !File.file?(
|
26
|
+
fn = File.join(opts[:root_dir], '_site.rb')
|
27
|
+
return nil if !File.file?(fn)
|
28
28
|
|
29
|
-
loader = Syntropy::ModuleLoader.new(opts
|
29
|
+
loader = Syntropy::ModuleLoader.new(opts)
|
30
30
|
loader.load('_site')
|
31
31
|
end
|
32
32
|
|
@@ -37,13 +37,14 @@ module Syntropy
|
|
37
37
|
end
|
38
38
|
|
39
39
|
attr_reader :module_loader, :routing_tree, :root_dir, :mount_path, :opts
|
40
|
-
|
40
|
+
|
41
|
+
def initialize(**opts)
|
41
42
|
@machine = opts[:machine]
|
42
|
-
@root_dir = root_dir
|
43
|
-
@mount_path = mount_path
|
43
|
+
@root_dir = opts[:root_dir]
|
44
|
+
@mount_path = opts[:mount_path]
|
44
45
|
@opts = opts
|
45
46
|
|
46
|
-
@module_loader = Syntropy::ModuleLoader.new(
|
47
|
+
@module_loader = Syntropy::ModuleLoader.new(app: self, **opts)
|
47
48
|
setup_routing_tree
|
48
49
|
start_app
|
49
50
|
end
|
@@ -69,6 +70,8 @@ module Syntropy
|
|
69
70
|
proc = route[:proc] ||= compute_route_proc(route)
|
70
71
|
proc.(req)
|
71
72
|
rescue StandardError => e
|
73
|
+
# p e
|
74
|
+
# p e.backtrace
|
72
75
|
error_handler = get_error_handler(route)
|
73
76
|
error_handler.(req, e)
|
74
77
|
end
|
data/lib/syntropy/module.rb
CHANGED
@@ -4,8 +4,8 @@ require 'p2'
|
|
4
4
|
|
5
5
|
module Syntropy
|
6
6
|
class ModuleLoader
|
7
|
-
def initialize(
|
8
|
-
@
|
7
|
+
def initialize(env)
|
8
|
+
@root_dir = env[:root_dir]
|
9
9
|
@env = env
|
10
10
|
@loaded = {} # maps ref to code
|
11
11
|
@fn_map = {} # maps filename to ref
|
@@ -26,27 +26,20 @@ module Syntropy
|
|
26
26
|
private
|
27
27
|
|
28
28
|
def load_module(ref)
|
29
|
-
fn = File.expand_path(File.join(@
|
29
|
+
fn = File.expand_path(File.join(@root_dir, "#{ref}.rb"))
|
30
30
|
@fn_map[fn] = ref
|
31
|
-
raise "File not found #{fn}" if !File.file?(fn)
|
32
|
-
|
33
|
-
mod_body = IO.read(fn)
|
34
|
-
mod_ctx = Class.new(Syntropy::Module)
|
35
|
-
mod_ctx.prepare(loader: self, env: @env, ref: ref)
|
36
|
-
mod_ctx.module_eval(mod_body, fn, 1)
|
31
|
+
raise Syntropy::Error, "File not found #{fn}" if !File.file?(fn)
|
37
32
|
|
38
|
-
|
39
|
-
|
33
|
+
code = IO.read(fn)
|
34
|
+
env = @env.merge(module_loader: self, ref: ref)
|
35
|
+
export_value = Syntropy::Module.load(env, code)
|
36
|
+
transform_module_export_value(export_value)
|
40
37
|
end
|
41
38
|
|
42
|
-
def
|
39
|
+
def transform_module_export_value(export_value)
|
43
40
|
case export_value
|
44
41
|
when nil
|
45
|
-
raise 'No export found'
|
46
|
-
when Symbol
|
47
|
-
o = mod_ctx.new(@env)
|
48
|
-
# TODO: verify export_value denotes a valid method
|
49
|
-
->(req) { o.send(export_value, req) }
|
42
|
+
raise Syntropy::Error, 'No export found'
|
50
43
|
when String
|
51
44
|
->(req) { req.respond(export_value) }
|
52
45
|
when Class
|
@@ -58,74 +51,44 @@ module Syntropy
|
|
58
51
|
end
|
59
52
|
|
60
53
|
class Module
|
61
|
-
def
|
62
|
-
|
54
|
+
def self.load(env, code)
|
55
|
+
m = new(**env)
|
56
|
+
m.instance_eval(code)
|
57
|
+
m.__export_value__
|
63
58
|
end
|
64
59
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
def export(ref)
|
81
|
-
@__export_value__ = ref
|
82
|
-
end
|
60
|
+
attr_reader
|
61
|
+
def initialize(**env)
|
62
|
+
@env = env
|
63
|
+
@machine = env[:machine]
|
64
|
+
@module_loader = env[:module_loader]
|
65
|
+
@app = env[:app]
|
66
|
+
@ref = env[:ref]
|
67
|
+
singleton_class.const_set(:MODULE, self)
|
68
|
+
end
|
69
|
+
|
70
|
+
attr_reader :__export_value__
|
71
|
+
def export(v)
|
72
|
+
@__export_value__ = v
|
73
|
+
end
|
83
74
|
|
84
|
-
|
85
|
-
|
86
|
-
|
75
|
+
def import(ref)
|
76
|
+
@module_loader.load(ref)
|
77
|
+
end
|
87
78
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
def route_by_host(map = nil)
|
93
|
-
root = @env[:root_dir]
|
94
|
-
sites = Dir[File.join(root, '*')]
|
95
|
-
.reject { File.basename(it) =~ /^_/ }
|
96
|
-
.select { File.directory?(it) }
|
97
|
-
.each_with_object({}) { |fn, h|
|
98
|
-
name = File.basename(fn)
|
99
|
-
opts = @env.merge(root_dir: fn)
|
100
|
-
h[name] = Syntropy::App.new(**opts)
|
101
|
-
}
|
102
|
-
|
103
|
-
map&.each do |k, v|
|
104
|
-
sites[k] = sites[v]
|
105
|
-
end
|
106
|
-
|
107
|
-
lambda { |req|
|
108
|
-
site = sites[req.host]
|
109
|
-
site ? site.call(req) : req.respond(nil, ':status' => Status::BAD_REQUEST)
|
110
|
-
}
|
111
|
-
end
|
79
|
+
def template(proc = nil, &block)
|
80
|
+
proc ||= block
|
81
|
+
raise "No template block/proc given" if !proc
|
112
82
|
|
113
|
-
|
114
|
-
|
115
|
-
raise 'Not a directory' if !File.directory?(full_path)
|
83
|
+
P2::Template.new(proc)
|
84
|
+
end
|
116
85
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
}
|
121
|
-
end
|
86
|
+
def page_list(ref)
|
87
|
+
Syntropy.page_list(@env, ref)
|
88
|
+
end
|
122
89
|
|
123
|
-
|
124
|
-
|
125
|
-
mount_path ||= @env[:mount_path]
|
126
|
-
opts = @env.merge(root_dir:, mount_path:)
|
127
|
-
Syntropy::App.new(**opts)
|
128
|
-
end
|
90
|
+
def app(**env)
|
91
|
+
Syntropy::App.new(**(@env.merge(env)))
|
129
92
|
end
|
130
93
|
end
|
131
94
|
end
|
@@ -149,8 +149,13 @@ module Syntropy
|
|
149
149
|
#
|
150
150
|
# The routing tree is complemented with two maps:
|
151
151
|
#
|
152
|
-
# - `static_map` - maps URL paths to the corresponding static route entries
|
153
|
-
#
|
152
|
+
# - `static_map` - maps URL paths to the corresponding static route entries,
|
153
|
+
# which includes all non-parametric routes, as well as all static files.
|
154
|
+
# - `dynamic_map` - maps URL paths to the corresponding parametric route
|
155
|
+
# entries.
|
156
|
+
#
|
157
|
+
# The reason we use two separate maps is to prevent accidentally hitting a
|
158
|
+
# false lookup for a a URL with segments containing square brackets!
|
154
159
|
#
|
155
160
|
# @return [Hash] root entry
|
156
161
|
def compute_tree
|
@@ -165,9 +170,9 @@ module Syntropy
|
|
165
170
|
def compute_route_directory(dir:, rel_path:, parent: nil)
|
166
171
|
param = (m = File.basename(dir).match(/^\[(.+)\]$/)) ? m[1] : nil
|
167
172
|
entry = {
|
168
|
-
parent
|
173
|
+
parent:,
|
169
174
|
path: rel_path_to_abs_path(rel_path),
|
170
|
-
param
|
175
|
+
param:,
|
171
176
|
hook: find_aux_module_entry(dir, '_hook.rb'),
|
172
177
|
error: find_aux_module_entry(dir, '_error.rb')
|
173
178
|
}
|
@@ -185,7 +190,7 @@ module Syntropy
|
|
185
190
|
# @return [String, nil] file path if found
|
186
191
|
def find_aux_module_entry(dir, name)
|
187
192
|
fn = File.join(dir, name)
|
188
|
-
File.file?(fn) ? ({ kind: :module,
|
193
|
+
File.file?(fn) ? ({ kind: :module, fn: }) : nil
|
189
194
|
end
|
190
195
|
|
191
196
|
# Returns a hash mapping file/dir names to route entries.
|
@@ -223,76 +228,51 @@ module Syntropy
|
|
223
228
|
# @return [void]
|
224
229
|
def compute_route_file(fn:, rel_path:, parent:)
|
225
230
|
abs_path = rel_path_to_abs_path(rel_path)
|
226
|
-
|
231
|
+
|
227
232
|
# index.rb, index+.rb, index.md
|
233
|
+
case
|
228
234
|
when (m = fn.match(/\/index(\+)?(\.(?:rb|md))$/))
|
229
|
-
|
230
|
-
|
231
|
-
# handles requests to its subtree
|
232
|
-
plus, ext = m[1..2]
|
233
|
-
kind = FILE_TYPE[ext]
|
234
|
-
handle_subtree = (plus == '+') && (kind == :module)
|
235
|
-
set_index_route_target(parent:, path: abs_path, kind:, fn:, handle_subtree:)
|
236
|
-
|
235
|
+
make_index_module_route(m:, parent:, path: abs_path, fn:)
|
236
|
+
|
237
237
|
# index.html
|
238
238
|
when fn.match(/\/index\.html$/)
|
239
|
-
# HTML index files are applied as targets to the immediate containing
|
240
|
-
# directory. It is considered static and therefore not added to the
|
241
|
-
# routing tree.
|
242
239
|
set_index_route_target(parent:, path: abs_path, kind: :static, fn:)
|
243
240
|
|
244
241
|
# foo.rb, foo+.rb, foo.md, [foo].rb, [foo]+.rb
|
245
242
|
when (m = fn.match(/\/(\[)?([^\]\/\+]+)(\])?(\+)?(\.(?:rb|md))$/))
|
246
|
-
|
247
|
-
# also handles requests to the subtree. For example, `/foo/bar.rb` will
|
248
|
-
# handle requests to `/foo/bar`, but `/foo/bar+.rb` will also handle
|
249
|
-
# requests to `/foo/bar/baz/bug`.
|
250
|
-
#
|
251
|
-
# parametric, or wildcard, routes convert segments of the URL path into
|
252
|
-
# parameters that are added to the HTTP request. Parametric routes are
|
253
|
-
# denoted using square brackets around the file/directory name. For
|
254
|
-
# example, `/api/posts/[id].rb`` will handle requests to
|
255
|
-
# `/api/posts/42`, and will extract the parameter `posts => 42` to add
|
256
|
-
# to the incoming request.
|
257
|
-
#
|
258
|
-
# A + suffix indicates the module also handles the subtree, so e.g.
|
259
|
-
# `/api/posts/[id]+.rb` will also handle requests to
|
260
|
-
# `/api/posts/42/fans` etc.
|
261
|
-
ob, param, cb, plus, ext = m[1..5]
|
262
|
-
kind = FILE_TYPE[ext]
|
263
|
-
make_route_entry(
|
264
|
-
parent:,
|
265
|
-
path: abs_path,
|
266
|
-
param: ob && cb ? param : nil,
|
267
|
-
target: make_route_target(kind:, fn:),
|
268
|
-
handle_subtree: (plus == '+') && (kind == :module)
|
269
|
-
)
|
270
|
-
|
271
|
-
# foo.html
|
272
|
-
when (m = fn.match(/\/[^\/]+\.html$/))
|
273
|
-
# HTML files are routed by their clean URL, i.e. without the `.html`
|
274
|
-
# extension. Those are considered as static routes, and do not have
|
275
|
-
# entries in the routing tree. Instead they are stored in the static
|
276
|
-
# map.
|
277
|
-
make_route_entry(
|
278
|
-
parent: parent,
|
279
|
-
path: abs_path,
|
280
|
-
target: make_route_target(kind: :static, fn:)
|
281
|
-
)
|
243
|
+
make_module_route(m:, parent:, path: abs_path, fn:)
|
282
244
|
|
283
245
|
# everything else
|
284
246
|
else
|
285
247
|
# static files resolved using the static map, and are not added to the
|
286
|
-
# routing tree, which is used for resolving dynamic routes.
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
target: { kind: :static, fn: fn }
|
291
|
-
)
|
248
|
+
# routing tree, which is used for resolving dynamic routes. HTML files
|
249
|
+
# are routed by their clean URL, i.e. without the `.html` extension.
|
250
|
+
target = { kind: :static, fn: }
|
251
|
+
make_route_entry(parent:, path: abs_path, target:)
|
292
252
|
end
|
293
253
|
end
|
294
254
|
|
295
|
-
#
|
255
|
+
# Creates a route entry for an index module (ruby/markdown). Index files
|
256
|
+
# (modules or markdown) files) are applied as targets to the immediate
|
257
|
+
# containing directory. A + suffix indicates this route handles requests to
|
258
|
+
# its subtree
|
259
|
+
#
|
260
|
+
# @param m [MatchData] path match data
|
261
|
+
# @param parent [Hash] parent route entry
|
262
|
+
# @param path [String] route path
|
263
|
+
# @param fn [String] route target filename
|
264
|
+
# @return [nil] (prevents addition of an index route)
|
265
|
+
def make_index_module_route(m:, parent:, path:, fn:)
|
266
|
+
plus, ext = m[1..2]
|
267
|
+
kind = FILE_TYPE[ext]
|
268
|
+
handle_subtree = (plus == '+') && (kind == :module)
|
269
|
+
set_index_route_target(parent:, path:, kind:, fn:, handle_subtree:)
|
270
|
+
end
|
271
|
+
|
272
|
+
|
273
|
+
# Sets an index route target for the given parent entry. Index files are
|
274
|
+
# applied as targets to the immediate containing directory. HTML index files
|
275
|
+
# are considered static and therefore not added to the routing tree.
|
296
276
|
#
|
297
277
|
# @param parent [Hash] parent route entry
|
298
278
|
# @param path [String] route path
|
@@ -303,12 +283,12 @@ module Syntropy
|
|
303
283
|
def set_index_route_target(parent:, path:, kind:, fn:, handle_subtree: nil)
|
304
284
|
if is_parametric_route?(parent) || handle_subtree
|
305
285
|
@dynamic_map[path] = parent
|
306
|
-
parent[:target] =
|
286
|
+
parent[:target] = { kind:, fn: }
|
307
287
|
parent[:handle_subtree] = handle_subtree
|
308
288
|
else
|
309
289
|
@static_map[path] = {
|
310
290
|
parent: parent[:parent],
|
311
|
-
path
|
291
|
+
path:,
|
312
292
|
target: { kind:, fn: },
|
313
293
|
# In case we're at the tree root, we need to copy over the hook and
|
314
294
|
# error refs.
|
@@ -319,6 +299,36 @@ module Syntropy
|
|
319
299
|
nil
|
320
300
|
end
|
321
301
|
|
302
|
+
# Creates a route entry for normal module and markdown files. A + suffix
|
303
|
+
# indicates the module also handles requests to the subtree. For example,
|
304
|
+
# `/foo/bar.rb` will handle requests to `/foo/bar`, but `/foo/bar+.rb` will
|
305
|
+
# also handle requests to `/foo/bar/baz/bug`.
|
306
|
+
#
|
307
|
+
# parametric, or wildcard, routes convert segments of the URL path into
|
308
|
+
# parameters that are added to the HTTP request. Parametric routes are
|
309
|
+
# denoted using square brackets around the file/directory name. For example,
|
310
|
+
# `/api/posts/[id].rb`` will handle requests to `/api/posts/42`, and will
|
311
|
+
# extract the parameter `posts => 42` to add to the incoming request.
|
312
|
+
#
|
313
|
+
# A + suffix indicates the module also handles the subtree, so e.g.
|
314
|
+
# `/api/posts/[id]+.rb` will also handle requests to `/api/posts/42/fans`
|
315
|
+
# etc.
|
316
|
+
#
|
317
|
+
# @param m [MatchData] path match data
|
318
|
+
# @param parent [Hash] parent route entry
|
319
|
+
# @param path [String] route path
|
320
|
+
# @param fn [String] route target filename
|
321
|
+
# @return [Hash] route entry
|
322
|
+
def make_module_route(m:, parent:, path:, fn:)
|
323
|
+
ob, param, cb, plus, ext = m[1..5]
|
324
|
+
kind = FILE_TYPE[ext]
|
325
|
+
make_route_entry(
|
326
|
+
parent:, path:, param: ob && cb ? param : nil,
|
327
|
+
target: { kind:, fn: },
|
328
|
+
handle_subtree: (plus == '+') && (kind == :module)
|
329
|
+
)
|
330
|
+
end
|
331
|
+
|
322
332
|
# Creates a new route entry, registering it in the static or dynamic map,
|
323
333
|
# according to its type.
|
324
334
|
#
|
@@ -357,19 +367,6 @@ module Syntropy
|
|
357
367
|
entry[:param] ? '[]' : File.basename(entry[:path]).gsub(/\+$/, '')
|
358
368
|
end
|
359
369
|
|
360
|
-
# Returns a hash representing a route target for the given route target kind
|
361
|
-
# and file name.
|
362
|
-
#
|
363
|
-
# @param kind [Symbol] route target kind
|
364
|
-
# @param fn [String] filename
|
365
|
-
# @return [Hash] route target hash
|
366
|
-
def make_route_target(kind:, fn:)
|
367
|
-
{
|
368
|
-
kind: kind,
|
369
|
-
fn: fn
|
370
|
-
}
|
371
|
-
end
|
372
|
-
|
373
370
|
# Generates and returns a router proc based on the routing tree.
|
374
371
|
#
|
375
372
|
# @return [Proc] router proc
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Syntropy
|
4
|
+
# Utilities for use in modules
|
5
|
+
module Utilities
|
6
|
+
# Returns a request handler that routes request according to
|
7
|
+
def route_by_host(env, map = nil)
|
8
|
+
root = env[:root_dir]
|
9
|
+
sites = Dir[File.join(root, '*')]
|
10
|
+
.reject { File.basename(it) =~ /^_/ }
|
11
|
+
.select { File.directory?(it) }
|
12
|
+
.each_with_object({}) { |fn, h|
|
13
|
+
name = File.basename(fn)
|
14
|
+
h[name] = Syntropy::App.new(**env.merge(root_dir: fn))
|
15
|
+
}
|
16
|
+
|
17
|
+
# copy over map refs
|
18
|
+
map&.each { |k, v| sites[k] = sites[v] }
|
19
|
+
|
20
|
+
#
|
21
|
+
lambda { |req|
|
22
|
+
site = sites[req.host]
|
23
|
+
site ? site.call(req) : req.respond(nil, ':status' => Status::BAD_REQUEST)
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def page_list(env, ref)
|
28
|
+
full_path = File.join(env[:root_dir], ref)
|
29
|
+
raise 'Not a directory' if !File.directory?(full_path)
|
30
|
+
|
31
|
+
Dir[File.join(full_path, '*.md')].sort.map {
|
32
|
+
atts, markdown = Syntropy.parse_markdown_file(it, env)
|
33
|
+
{ atts:, markdown: }
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
def app(**env)
|
38
|
+
Syntropy::App.new(**env)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/syntropy/version.rb
CHANGED
data/lib/syntropy.rb
CHANGED
@@ -15,10 +15,13 @@ require 'syntropy/request_extensions'
|
|
15
15
|
require 'syntropy/routing_tree'
|
16
16
|
require 'syntropy/rpc_api'
|
17
17
|
require 'syntropy/side_run'
|
18
|
+
require 'syntropy/utils'
|
18
19
|
|
19
20
|
module Syntropy
|
20
21
|
Status = Qeweney::Status
|
21
22
|
|
23
|
+
extend Utilities
|
24
|
+
|
22
25
|
class << self
|
23
26
|
attr_accessor :machine
|
24
27
|
|
data/test/app/_lib/callable.rb
CHANGED
data/test/app/tmp.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
export route_by_host
|
1
|
+
export Syntropy.route_by_host(@env)
|
data/test/test_module.rb
CHANGED
@@ -6,8 +6,8 @@ class ModuleTest < Minitest::Test
|
|
6
6
|
def setup
|
7
7
|
@machine = UM.new
|
8
8
|
@root = File.join(__dir__, 'app')
|
9
|
-
@env = { baz: 42 }
|
10
|
-
@loader = Syntropy::ModuleLoader.new(@
|
9
|
+
@env = { root_dir: @root, baz: 42, machine: @machine, app: 42 }
|
10
|
+
@loader = Syntropy::ModuleLoader.new(@env)
|
11
11
|
end
|
12
12
|
|
13
13
|
def test_module_loading
|
@@ -15,11 +15,11 @@ class ModuleTest < Minitest::Test
|
|
15
15
|
assert_equal :bar, mod.foo
|
16
16
|
assert_equal 42, mod.bar
|
17
17
|
|
18
|
-
assert_raises(
|
19
|
-
assert_raises(
|
18
|
+
assert_raises(Syntropy::Error) { @loader.load('_lib/missing-module') }
|
19
|
+
assert_raises(Syntropy::Error) { @loader.load('_lib/missing-export') }
|
20
20
|
|
21
21
|
mod = @loader.load('_lib/callable')
|
22
|
-
assert_kind_of
|
22
|
+
assert_kind_of Syntropy::Module, mod
|
23
23
|
assert_equal 'barbarbar', mod.call(3)
|
24
24
|
assert_raises(NoMethodError) { mod.foo(2) }
|
25
25
|
|
@@ -34,4 +34,14 @@ class ModuleTest < Minitest::Test
|
|
34
34
|
assert_kind_of Syntropy::Module, mod
|
35
35
|
assert_equal :bar, mod.foo
|
36
36
|
end
|
37
|
+
|
38
|
+
def test_module_env
|
39
|
+
mod = @loader.load('_lib/env')
|
40
|
+
|
41
|
+
assert_equal mod, mod.module_const
|
42
|
+
assert_equal @env.merge(module_loader: @loader, ref: '_lib/env'), mod.env
|
43
|
+
assert_equal @machine, mod.machine
|
44
|
+
assert_equal @loader, mod.module_loader
|
45
|
+
assert_equal 42, mod.app
|
46
|
+
end
|
37
47
|
end
|
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:
|
4
|
+
version: 0.13.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sharon Rosner
|
@@ -215,11 +215,13 @@ files:
|
|
215
215
|
- lib/syntropy/routing_tree.rb
|
216
216
|
- lib/syntropy/rpc_api.rb
|
217
217
|
- lib/syntropy/side_run.rb
|
218
|
+
- lib/syntropy/utils.rb
|
218
219
|
- lib/syntropy/version.rb
|
219
220
|
- syntropy.gemspec
|
220
221
|
- test/app/_hook.rb
|
221
222
|
- test/app/_layout/default.rb
|
222
223
|
- test/app/_lib/callable.rb
|
224
|
+
- test/app/_lib/env.rb
|
223
225
|
- test/app/_lib/klass.rb
|
224
226
|
- test/app/_lib/missing-export.rb
|
225
227
|
- test/app/_lib/self.rb
|