torikago 0.0.1 → 0.1.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.
@@ -1,23 +1,21 @@
1
1
  require_relative "../test_helper"
2
- require "fileutils"
3
- require "tmpdir"
4
2
 
5
3
  class TorikagoGatewayTest < Minitest::Test
6
- FakeContainer = Struct.new(:calls) do
7
- def call(public_api_class_name, *args, **kwargs)
8
- calls << [public_api_class_name, args, kwargs]
9
- "result for #{public_api_class_name}"
4
+ FakeContainer = Struct.new(:invocations) do
5
+ def invoke(public_api_class_name, method_name, **arguments)
6
+ invocations << [public_api_class_name, method_name, arguments]
7
+ "result for #{public_api_class_name}##{method_name}"
10
8
  end
11
9
  end
12
10
 
13
11
  class FakeRegistry
12
+ attr_reader :resolved
13
+
14
14
  def initialize(containers)
15
15
  @containers = containers
16
- @resolved = []
16
+ @resolved = Array.new
17
17
  end
18
18
 
19
- attr_reader :resolved
20
-
21
19
  def resolve(name)
22
20
  normalized_name = name.to_sym
23
21
  resolved << normalized_name
@@ -25,131 +23,179 @@ class TorikagoGatewayTest < Minitest::Test
25
23
  end
26
24
  end
27
25
 
28
- def test_class_level_call_delegates_to_the_shared_gateway
26
+ def test_class_level_build_and_invoke_delegate_to_the_shared_gateway
29
27
  original_gateway = Torikago.instance_variable_get(:@gateway)
30
28
  fake_gateway = Object.new
31
- called_with = nil
32
-
33
- fake_gateway.define_singleton_method(:call) do |*args, **kwargs|
34
- called_with = [args, kwargs]
35
- "ok"
36
- end
37
-
29
+ calls = Array.new
30
+ fake_gateway.define_singleton_method(:build) { |*args, **kwargs| calls << [:build, args, kwargs]; "build" }
31
+ fake_gateway.define_singleton_method(:invoke) { |*args, **kwargs| calls << [:invoke, args, kwargs]; "invoke" }
38
32
  Torikago.instance_variable_set(:@gateway, fake_gateway)
39
33
 
40
- result = Torikago::Gateway.call("Foo::ListProductsQuery", page: 1)
41
-
42
- assert_equal "ok", result
43
- assert_equal [["Foo::ListProductsQuery"], { page: 1 }], called_with
34
+ assert_equal "build", Torikago::Gateway.build("Foo::Query", 1, page: 2)
35
+ assert_equal "invoke", Torikago::Gateway.invoke("Foo::Query", :execute!, 3, force: true)
36
+ assert_equal(
37
+ [
38
+ [:build, ["Foo::Query", 1], { page: 2 }],
39
+ [:invoke, ["Foo::Query", :execute!, 3], { force: true }]
40
+ ],
41
+ calls
42
+ )
44
43
  ensure
45
44
  Torikago.instance_variable_set(:@gateway, original_gateway)
46
45
  end
47
46
 
48
- def test_call_delegates_to_the_target_module_container
49
- configuration = Torikago::Configuration.new
50
- configuration.register(:foo, root: "/modules/foo")
51
- write_package_api_manifest("/modules/foo", "Foo::ListProductsQuery" => { "allowed_callers" => [] })
47
+ def test_build_holds_constructor_arguments_until_invoke
48
+ gateway, registry, container = build_gateway
52
49
 
53
- container = FakeContainer.new([])
54
- registry = FakeRegistry.new(foo: container)
55
- gateway = Torikago::Gateway.new(
56
- registry: registry,
57
- configuration: configuration,
58
- manifest_loader: ->(_definition) { { "exports" => { "Foo::ListProductsQuery" => { "allowed_callers" => [] } } } }
50
+ invocation = gateway.build("Foo::ProductQuery", 10, page: 2)
51
+
52
+ assert_empty registry.resolved
53
+ result = invocation.invoke(:execute!, 20, force: true)
54
+
55
+ assert_equal "result for Foo::ProductQuery#execute!", result
56
+ assert_equal [:foo], registry.resolved
57
+ assert_equal(
58
+ [
59
+ [
60
+ "Foo::ProductQuery",
61
+ :execute!,
62
+ {
63
+ constructor_args: [10],
64
+ constructor_kwargs: { page: 2 },
65
+ method_args: [20],
66
+ method_kwargs: { force: true }
67
+ }
68
+ ]
69
+ ],
70
+ container.invocations
59
71
  )
72
+ end
73
+
74
+ def test_invoke_dispatches_with_an_argumentless_constructor
75
+ gateway, registry, container = build_gateway
60
76
 
61
- result = gateway.call("Foo::ListProductsQuery", page: 1)
77
+ gateway.invoke("Foo::ProductQuery", :execute!, 20, force: true)
62
78
 
63
- assert_equal "result for Foo::ListProductsQuery", result
64
79
  assert_equal [:foo], registry.resolved
65
- assert_equal [["Foo::ListProductsQuery", [], { page: 1 }]], container.calls
80
+ assert_equal [], container.invocations.first[2].fetch(:constructor_args)
81
+ assert_equal({}, container.invocations.first[2].fetch(:constructor_kwargs))
82
+ assert_equal [20], container.invocations.first[2].fetch(:method_args)
83
+ assert_equal({ force: true }, container.invocations.first[2].fetch(:method_kwargs))
66
84
  end
67
85
 
68
- def test_call_rejects_public_api_not_declared_in_package_api_manifest
69
- configuration = Torikago::Configuration.new
70
- configuration.register(:foo, root: "/modules/foo")
71
- registry = FakeRegistry.new(foo: FakeContainer.new([]))
72
- gateway = Torikago::Gateway.new(
73
- registry: registry,
74
- configuration: configuration,
75
- manifest_loader: ->(_definition) { { "exports" => {} } }
76
- )
86
+ def test_gateway_does_not_expose_call
87
+ gateway, = build_gateway
88
+
89
+ refute_respond_to Torikago::Gateway, :call
90
+ refute_respond_to gateway, :call
91
+ end
92
+
93
+ def test_invoke_rejects_a_class_not_declared_in_the_manifest_before_resolving
94
+ gateway, registry = build_gateway(exports: Hash.new)
77
95
 
78
96
  error = assert_raises(Torikago::PublicApiError) do
79
- gateway.call("Foo::MissingCommand")
97
+ gateway.invoke("Foo::MissingCommand", :execute!)
80
98
  end
81
99
 
82
- assert_match(/Foo::MissingCommand/, error.message)
100
+ assert_match(/Foo::MissingCommand#execute!/, error.message)
101
+ assert_empty registry.resolved
83
102
  end
84
103
 
85
- def test_call_allows_host_app_invocation_without_allowed_callers
86
- configuration = Torikago::Configuration.new
87
- configuration.register(:foo, root: "/modules/foo")
88
- container = FakeContainer.new([])
89
- registry = FakeRegistry.new(foo: container)
90
- gateway = Torikago::Gateway.new(
91
- registry: registry,
92
- configuration: configuration,
93
- manifest_loader: ->(_definition) { { "exports" => { "Foo::ListProductsQuery" => { "allowed_callers" => [] } } } }
94
- )
104
+ def test_invoke_rejects_a_method_not_declared_in_the_manifest_before_resolving
105
+ gateway, registry = build_gateway
95
106
 
96
- gateway.call("Foo::ListProductsQuery")
107
+ error = assert_raises(Torikago::PublicApiError) do
108
+ gateway.invoke("Foo::ProductQuery", :delete_all!)
109
+ end
97
110
 
98
- assert_equal [["Foo::ListProductsQuery", [], {}]], container.calls
111
+ assert_equal "package api method is not exported: Foo::ProductQuery#delete_all!", error.message
112
+ assert_empty registry.resolved
99
113
  end
100
114
 
101
- def test_call_allows_box_dependency_declared_in_package_api_manifest
102
- configuration = Torikago::Configuration.new
103
- configuration.register(:foo, root: "/modules/foo")
104
- configuration.register(:bar, root: "/modules/bar")
105
- bar_container = FakeContainer.new([])
106
- registry = FakeRegistry.new(foo: FakeContainer.new([]), bar: bar_container)
115
+ def test_invoke_rejects_manifest_entries_without_methods
116
+ gateway, registry = build_gateway(
117
+ exports: { "Foo::ProductQuery" => { "allowed_callers" => [] } }
118
+ )
107
119
 
108
- gateway = Torikago::Gateway.new(
109
- registry: registry,
110
- configuration: configuration,
111
- manifest_loader: lambda do |definition|
112
- if definition.name == :bar
113
- { "exports" => { "Bar::SubmitOrderCommand" => { "allowed_callers" => ["foo"] } } }
114
- else
115
- { "exports" => {} }
116
- end
117
- end
120
+ error = assert_raises(Torikago::PublicApiError) do
121
+ gateway.invoke("Foo::ProductQuery", :execute!)
122
+ end
123
+
124
+ assert_match(/methods are not configured/, error.message)
125
+ assert_empty registry.resolved
126
+ end
127
+
128
+ def test_invoke_rejects_manifest_entries_with_empty_methods
129
+ gateway, registry = build_gateway(
130
+ exports: { "Foo::ProductQuery" => { "methods" => [], "allowed_callers" => [] } }
118
131
  )
119
132
 
120
- Torikago::CurrentExecution.with_box(:foo) do
121
- result = gateway.call("Bar::SubmitOrderCommand", order_id: 1)
133
+ assert_raises(Torikago::PublicApiError) do
134
+ gateway.invoke("Foo::ProductQuery", :execute!)
135
+ end
136
+ assert_empty registry.resolved
137
+ end
138
+
139
+ def test_invoke_allows_the_host_app_without_allowed_callers
140
+ gateway, _, container = build_gateway
141
+
142
+ gateway.invoke("Foo::ProductQuery", :execute!)
143
+
144
+ assert_equal 1, container.invocations.size
145
+ end
146
+
147
+ def test_invoke_allows_the_target_module_to_call_itself
148
+ gateway, _, container = build_gateway
122
149
 
123
- assert_equal "result for Bar::SubmitOrderCommand", result
150
+ Torikago::CurrentExecution.with_box(:foo) do
151
+ gateway.invoke("Foo::ProductQuery", :execute!)
124
152
  end
125
153
 
126
- assert_equal [["Bar::SubmitOrderCommand", [], { order_id: 1 }]], bar_container.calls
154
+ assert_equal 1, container.invocations.size
127
155
  end
128
156
 
129
- def test_call_rejects_box_dependency_not_declared_in_package_api_manifest
130
- configuration = Torikago::Configuration.new
131
- configuration.register(:foo, root: "/modules/foo")
132
- configuration.register(:bar, root: "/modules/bar")
133
- registry = FakeRegistry.new(foo: FakeContainer.new([]), bar: FakeContainer.new([]))
157
+ def test_invoke_allows_a_declared_cross_module_caller
158
+ gateway, _, container = build_gateway(allowed_callers: ["bar"])
134
159
 
135
- gateway = Torikago::Gateway.new(
136
- registry: registry,
137
- configuration: configuration,
138
- manifest_loader: ->(_definition) { { "exports" => { "Bar::SubmitOrderCommand" => { "allowed_callers" => ["admin"] } } } }
139
- )
160
+ Torikago::CurrentExecution.with_box(:bar) do
161
+ gateway.invoke("Foo::ProductQuery", :execute!)
162
+ end
163
+
164
+ assert_equal 1, container.invocations.size
165
+ end
166
+
167
+ def test_invoke_rejects_an_undeclared_cross_module_caller_before_resolving
168
+ gateway, registry = build_gateway(allowed_callers: ["admin"])
140
169
 
141
170
  error = assert_raises(Torikago::DependencyError) do
142
- Torikago::CurrentExecution.with_box(:foo) do
143
- gateway.call("Bar::SubmitOrderCommand")
171
+ Torikago::CurrentExecution.with_box(:bar) do
172
+ gateway.invoke("Foo::ProductQuery", :execute!)
144
173
  end
145
174
  end
146
175
 
147
- assert_match(/foo/, error.message)
148
- assert_match(/bar/i, error.message)
176
+ assert_match(/bar -> foo#Foo::ProductQuery#execute!/, error.message)
177
+ assert_empty registry.resolved
149
178
  end
150
179
 
151
180
  private
152
181
 
153
- def write_package_api_manifest(_root, _entries)
182
+ def build_gateway(allowed_callers: [], exports: nil)
183
+ configuration = Torikago::Configuration.new
184
+ configuration.register(:foo, root: "/modules/foo")
185
+ container = FakeContainer.new(Array.new)
186
+ registry = FakeRegistry.new(foo: container)
187
+ exports ||= {
188
+ "Foo::ProductQuery" => {
189
+ "methods" => ["execute!"],
190
+ "allowed_callers" => allowed_callers
191
+ }
192
+ }
193
+ gateway = Torikago::Gateway.new(
194
+ registry: registry,
195
+ configuration: configuration,
196
+ manifest_loader: ->(_definition) { { "exports" => exports } }
197
+ )
198
+
199
+ [gateway, registry, container]
154
200
  end
155
201
  end
@@ -22,8 +22,8 @@ class TorikagoPackageApiUpdaterTest < Minitest::Test
22
22
  assert_equal(
23
23
  {
24
24
  "exports" => {
25
- "Foo::UserCreateCommand" => { "allowed_callers" => [] },
26
- "Foo::UserFindQuery" => { "allowed_callers" => [] }
25
+ "Foo::UserCreateCommand" => { "methods" => [], "allowed_callers" => [] },
26
+ "Foo::UserFindQuery" => { "methods" => [], "allowed_callers" => [] }
27
27
  }
28
28
  },
29
29
  manifest
@@ -42,6 +42,8 @@ class TorikagoPackageApiUpdaterTest < Minitest::Test
42
42
  <<~YAML
43
43
  exports:
44
44
  Foo::UserCreateCommand:
45
+ methods:
46
+ - execute!
45
47
  allowed_callers:
46
48
  - bar
47
49
  YAML
@@ -54,6 +56,7 @@ class TorikagoPackageApiUpdaterTest < Minitest::Test
54
56
  manifest = YAML.safe_load(File.read(File.join(module_root, "package_api.yml")))
55
57
 
56
58
  assert_equal ["bar"], manifest.dig("exports", "Foo::UserCreateCommand", "allowed_callers")
59
+ assert_equal ["execute!"], manifest.dig("exports", "Foo::UserCreateCommand", "methods")
57
60
  end
58
61
  end
59
62
 
@@ -71,7 +74,7 @@ class TorikagoPackageApiUpdaterTest < Minitest::Test
71
74
  manifest = YAML.safe_load(File.read(File.join(module_root, "package_api.yml")))
72
75
 
73
76
  assert_equal(
74
- { "allowed_callers" => [] },
77
+ { "methods" => [], "allowed_callers" => [] },
75
78
  manifest.dig("exports", "Foo::UserCreateCommand")
76
79
  )
77
80
  end
@@ -0,0 +1,25 @@
1
+ require_relative "../test_helper"
2
+
3
+ class TorikagoRackEndpointTest < Minitest::Test
4
+ def test_call_resolves_and_dispatches_to_the_registered_module
5
+ received_env = nil
6
+ container = Object.new
7
+ container.define_singleton_method(:call) do |env|
8
+ received_env = env
9
+ [204, {}, []]
10
+ end
11
+
12
+ registry = Object.new
13
+ registry.define_singleton_method(:resolve) do |name|
14
+ raise "unexpected module: #{name}" unless name == :foo
15
+
16
+ container
17
+ end
18
+
19
+ endpoint = Torikago::RackEndpoint.new("foo", registry: registry)
20
+ env = { "PATH_INFO" => "/widgets" }
21
+
22
+ assert_equal [204, {}, []], endpoint.call(env)
23
+ assert_same env, received_env
24
+ end
25
+ end
@@ -7,6 +7,7 @@ class TorikagoRegistryTest < Minitest::Test
7
7
  :foo,
8
8
  root: "/modules/foo",
9
9
  entrypoint: "lib/foo/box_runtime.rb",
10
+ rails_engine: true,
10
11
  setup: "config/box_setup.rb",
11
12
  gemfile: "Gemfile"
12
13
  )
@@ -18,6 +19,7 @@ class TorikagoRegistryTest < Minitest::Test
18
19
  name: definition.name,
19
20
  root: definition.root.to_s,
20
21
  entrypoint: definition.entrypoint,
22
+ rails_engine: definition.rails_engine,
21
23
  setup: definition.setup,
22
24
  gemfile: definition.gemfile
23
25
  }
@@ -28,6 +30,7 @@ class TorikagoRegistryTest < Minitest::Test
28
30
  assert_equal :foo, container[:name]
29
31
  assert_equal "/modules/foo", container[:root]
30
32
  assert_equal "lib/foo/box_runtime.rb", container[:entrypoint]
33
+ assert_equal true, container[:rails_engine]
31
34
  assert_equal "config/box_setup.rb", container[:setup]
32
35
  assert_equal "Gemfile", container[:gemfile]
33
36
  end
@@ -80,4 +83,16 @@ class TorikagoRegistryTest < Minitest::Test
80
83
 
81
84
  assert_instance_of Torikago::EngineContainer, container
82
85
  end
86
+
87
+ def test_default_container_receives_every_registered_root
88
+ @configuration.register(:bar, root: "/components/bar")
89
+ registry = Torikago::Registry.new(configuration: @configuration)
90
+
91
+ container = registry.resolve(:foo)
92
+
93
+ assert_equal(
94
+ [Pathname("/modules/foo"), Pathname("/components/bar")],
95
+ container.send(:registered_roots)
96
+ )
97
+ end
83
98
  end
@@ -0,0 +1,114 @@
1
+ require_relative "../test_helper"
2
+ require "fileutils"
3
+ require "tmpdir"
4
+
5
+ class TorikagoRootConstantResolverTest < Minitest::Test
6
+ def teardown
7
+ Object.send(:remove_const, :RootResolverVisibleConstant) if Object.const_defined?(:RootResolverVisibleConstant, false)
8
+ Object.send(:remove_const, :RootResolverRegisteredConstant) if Object.const_defined?(:RootResolverRegisteredConstant, false)
9
+ Object.send(:remove_const, :RootResolverRegisteredAutoload) if Object.const_defined?(:RootResolverRegisteredAutoload, false)
10
+ Object.send(:remove_const, :RootResolverSharedNamespace) if Object.const_defined?(:RootResolverSharedNamespace, false)
11
+ end
12
+
13
+ def test_resolve_returns_main_constant_defined_outside_registered_roots
14
+ Dir.mktmpdir("torikago-root-resolver") do |application_root|
15
+ registered_root = File.join(application_root, "modules/foo")
16
+ FileUtils.mkdir_p(registered_root)
17
+ root_file = File.join(application_root, "app_root_constant.rb")
18
+ File.write(root_file, "class RootResolverVisibleConstant; end\n")
19
+ load root_file
20
+
21
+ resolver = Torikago::RootConstantResolver.new(
22
+ registered_roots: [registered_root],
23
+ main_box: Object
24
+ )
25
+
26
+ assert_same RootResolverVisibleConstant, resolver.resolve(:RootResolverVisibleConstant)
27
+ end
28
+ end
29
+
30
+ def test_resolve_rejects_constants_defined_below_any_registered_root
31
+ Dir.mktmpdir("torikago-root-resolver") do |application_root|
32
+ registered_root = File.join(application_root, "packs/foo")
33
+ FileUtils.mkdir_p(registered_root)
34
+ registered_file = File.join(registered_root, "registered_constant.rb")
35
+ File.write(registered_file, "class RootResolverRegisteredConstant; end\n")
36
+ load registered_file
37
+
38
+ resolver = Torikago::RootConstantResolver.new(
39
+ registered_roots: [registered_root],
40
+ main_box: Object
41
+ )
42
+
43
+ assert_same resolver.unresolved, resolver.resolve(:RootResolverRegisteredConstant)
44
+ end
45
+ end
46
+
47
+ def test_resolve_returns_unresolved_for_an_unknown_constant
48
+ resolver = Torikago::RootConstantResolver.new(
49
+ registered_roots: [],
50
+ main_box: Object
51
+ )
52
+
53
+ assert_same resolver.unresolved, resolver.resolve(:RootResolverMissingConstant)
54
+ end
55
+
56
+ def test_resolve_rejects_a_top_level_autoload_from_a_registered_root
57
+ Dir.mktmpdir("torikago-root-resolver") do |application_root|
58
+ registered_root = File.join(application_root, "modules/foo")
59
+ FileUtils.mkdir_p(registered_root)
60
+ registered_file = File.join(registered_root, "registered_autoload.rb")
61
+ File.write(registered_file, "class RootResolverRegisteredAutoload; end\n")
62
+ Object.autoload(:RootResolverRegisteredAutoload, registered_file)
63
+
64
+ resolver = Torikago::RootConstantResolver.new(
65
+ registered_roots: [registered_root],
66
+ main_box: Object
67
+ )
68
+
69
+ assert_same resolver.unresolved, resolver.resolve(:RootResolverRegisteredAutoload)
70
+ assert_equal registered_file, Object.autoload?(:RootResolverRegisteredAutoload, false)
71
+ end
72
+ end
73
+
74
+ def test_resolve_rejects_a_root_namespace_with_a_registered_descendant
75
+ Dir.mktmpdir("torikago-root-resolver") do |application_root|
76
+ registered_root = File.join(application_root, "components/bar")
77
+ FileUtils.mkdir_p(registered_root)
78
+ root_file = File.join(application_root, "shared_namespace.rb")
79
+ registered_file = File.join(registered_root, "internal.rb")
80
+ File.write(root_file, "module RootResolverSharedNamespace; end\n")
81
+ File.write(registered_file, "class RootResolverSharedNamespace::Internal; end\n")
82
+ load root_file
83
+ load registered_file
84
+
85
+ resolver = Torikago::RootConstantResolver.new(
86
+ registered_roots: [registered_root],
87
+ main_box: Object
88
+ )
89
+
90
+ assert_same resolver.unresolved, resolver.resolve(:RootResolverSharedNamespace)
91
+ end
92
+ end
93
+
94
+ def test_resolve_rejects_a_root_namespace_with_a_registered_autoload
95
+ Dir.mktmpdir("torikago-root-resolver") do |application_root|
96
+ registered_root = File.join(application_root, "components/bar")
97
+ FileUtils.mkdir_p(registered_root)
98
+ root_file = File.join(application_root, "shared_namespace.rb")
99
+ registered_file = File.join(registered_root, "autoloaded_internal.rb")
100
+ File.write(root_file, "module RootResolverSharedNamespace; end\n")
101
+ File.write(registered_file, "class RootResolverSharedNamespace::AutoloadedInternal; end\n")
102
+ load root_file
103
+ RootResolverSharedNamespace.autoload(:AutoloadedInternal, registered_file)
104
+
105
+ resolver = Torikago::RootConstantResolver.new(
106
+ registered_roots: [registered_root],
107
+ main_box: Object
108
+ )
109
+
110
+ assert_same resolver.unresolved, resolver.resolve(:RootResolverSharedNamespace)
111
+ assert_equal registered_file, RootResolverSharedNamespace.autoload?(:AutoloadedInternal, false)
112
+ end
113
+ end
114
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: torikago
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - se4weed
@@ -29,22 +29,30 @@ files:
29
29
  - lib/torikago/checker.rb
30
30
  - lib/torikago/cli.rb
31
31
  - lib/torikago/configuration.rb
32
+ - lib/torikago/controller_endpoint.rb
32
33
  - lib/torikago/current_execution.rb
33
34
  - lib/torikago/engine_container.rb
34
35
  - lib/torikago/errors.rb
35
36
  - lib/torikago/gateway.rb
37
+ - lib/torikago/invocation.rb
36
38
  - lib/torikago/package_api_updater.rb
39
+ - lib/torikago/rack_endpoint.rb
37
40
  - lib/torikago/registry.rb
41
+ - lib/torikago/root_constant_resolver.rb
38
42
  - lib/torikago/version.rb
43
+ - sig/torikago.rbs
39
44
  - test/test_helper.rb
40
45
  - test/torikago.rb
41
46
  - test/torikago/checker.rb
42
47
  - test/torikago/cli.rb
43
48
  - test/torikago/configuration.rb
49
+ - test/torikago/controller_endpoint.rb
44
50
  - test/torikago/engine_container.rb
45
51
  - test/torikago/gateway.rb
46
52
  - test/torikago/package_api_updater.rb
53
+ - test/torikago/rack_endpoint.rb
47
54
  - test/torikago/registry.rb
55
+ - test/torikago/root_constant_resolver.rb
48
56
  - test/torikago/version.rb
49
57
  homepage: "https://github.com/se4weed/torikago"
50
58
  licenses: