ree 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +13 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +41 -0
- data/LICENSE.txt +21 -0
- data/README.md +474 -0
- data/Rakefile +8 -0
- data/bin/console +8 -0
- data/bin/setup +8 -0
- data/exe/ree +264 -0
- data/lib/ree/args.rb +34 -0
- data/lib/ree/bean_dsl.rb +24 -0
- data/lib/ree/cli/generate_package.rb +18 -0
- data/lib/ree/cli/generate_package_schema.rb +54 -0
- data/lib/ree/cli/generate_packages_schema.rb +17 -0
- data/lib/ree/cli/generate_template.rb +20 -0
- data/lib/ree/cli/init.rb +22 -0
- data/lib/ree/cli/spec_runner.rb +184 -0
- data/lib/ree/cli.rb +12 -0
- data/lib/ree/container.rb +67 -0
- data/lib/ree/contracts/arg_contracts/any.rb +15 -0
- data/lib/ree/contracts/arg_contracts/array_of.rb +52 -0
- data/lib/ree/contracts/arg_contracts/block.rb +15 -0
- data/lib/ree/contracts/arg_contracts/bool.rb +21 -0
- data/lib/ree/contracts/arg_contracts/eq.rb +28 -0
- data/lib/ree/contracts/arg_contracts/exactly.rb +28 -0
- data/lib/ree/contracts/arg_contracts/hash_of.rb +59 -0
- data/lib/ree/contracts/arg_contracts/ksplat.rb +141 -0
- data/lib/ree/contracts/arg_contracts/kwargs.rb +22 -0
- data/lib/ree/contracts/arg_contracts/nilor.rb +16 -0
- data/lib/ree/contracts/arg_contracts/none.rb +15 -0
- data/lib/ree/contracts/arg_contracts/optblock.rb +11 -0
- data/lib/ree/contracts/arg_contracts/or.rb +30 -0
- data/lib/ree/contracts/arg_contracts/range_of.rb +51 -0
- data/lib/ree/contracts/arg_contracts/set_of.rb +54 -0
- data/lib/ree/contracts/arg_contracts/splat.rb +297 -0
- data/lib/ree/contracts/arg_contracts/splat_of.rb +64 -0
- data/lib/ree/contracts/arg_contracts/squarable.rb +11 -0
- data/lib/ree/contracts/arg_contracts/subclass_of.rb +28 -0
- data/lib/ree/contracts/arg_contracts.rb +29 -0
- data/lib/ree/contracts/called_args_validator.rb +291 -0
- data/lib/ree/contracts/contract_definition.rb +142 -0
- data/lib/ree/contracts/contractable.rb +34 -0
- data/lib/ree/contracts/core.rb +17 -0
- data/lib/ree/contracts/engine.rb +71 -0
- data/lib/ree/contracts/engine_proxy.rb +13 -0
- data/lib/ree/contracts/errors/bad_contract_error.rb +4 -0
- data/lib/ree/contracts/errors/contract_error.rb +4 -0
- data/lib/ree/contracts/errors/error.rb +4 -0
- data/lib/ree/contracts/errors/return_contract_error.rb +4 -0
- data/lib/ree/contracts/method_decorator.rb +158 -0
- data/lib/ree/contracts/truncatable.rb +9 -0
- data/lib/ree/contracts/utils.rb +9 -0
- data/lib/ree/contracts/validators/array_validator.rb +51 -0
- data/lib/ree/contracts/validators/base_validator.rb +27 -0
- data/lib/ree/contracts/validators/class_validator.rb +17 -0
- data/lib/ree/contracts/validators/default_validator.rb +20 -0
- data/lib/ree/contracts/validators/hash_validator.rb +100 -0
- data/lib/ree/contracts/validators/proc_validator.rb +17 -0
- data/lib/ree/contracts/validators/range_validator.rb +17 -0
- data/lib/ree/contracts/validators/regexp_validator.rb +17 -0
- data/lib/ree/contracts/validators/valid_validator.rb +28 -0
- data/lib/ree/contracts/validators.rb +42 -0
- data/lib/ree/contracts.rb +45 -0
- data/lib/ree/core/link_validator.rb +42 -0
- data/lib/ree/core/object.rb +132 -0
- data/lib/ree/core/object_error.rb +9 -0
- data/lib/ree/core/object_link.rb +21 -0
- data/lib/ree/core/object_schema.rb +47 -0
- data/lib/ree/core/object_schema_builder.rb +110 -0
- data/lib/ree/core/package.rb +177 -0
- data/lib/ree/core/package_dep.rb +9 -0
- data/lib/ree/core/package_env_var.rb +12 -0
- data/lib/ree/core/package_loader.rb +95 -0
- data/lib/ree/core/package_schema.rb +27 -0
- data/lib/ree/core/package_schema_builder.rb +53 -0
- data/lib/ree/core/package_schema_loader.rb +170 -0
- data/lib/ree/core/packages_detector.rb +43 -0
- data/lib/ree/core/packages_schema.rb +19 -0
- data/lib/ree/core/packages_schema_builder.rb +50 -0
- data/lib/ree/core/packages_schema_loader.rb +95 -0
- data/lib/ree/core/packages_schema_locator.rb +27 -0
- data/lib/ree/core/packages_store.rb +32 -0
- data/lib/ree/core/path_helper.rb +104 -0
- data/lib/ree/dsl/build_package_dsl.rb +155 -0
- data/lib/ree/dsl/domain_error.rb +4 -0
- data/lib/ree/dsl/error_builder.rb +39 -0
- data/lib/ree/dsl/error_dsl.rb +27 -0
- data/lib/ree/dsl/import_dsl.rb +106 -0
- data/lib/ree/dsl/link_import_builder.rb +66 -0
- data/lib/ree/dsl/object_dsl.rb +319 -0
- data/lib/ree/dsl/object_hooks.rb +6 -0
- data/lib/ree/dsl/package_require.rb +44 -0
- data/lib/ree/error.rb +11 -0
- data/lib/ree/facades/packages_facade.rb +197 -0
- data/lib/ree/fn_dsl.rb +24 -0
- data/lib/ree/gen/init.rb +64 -0
- data/lib/ree/gen/package.rb +56 -0
- data/lib/ree/gen.rb +8 -0
- data/lib/ree/handlers/template_handler.rb +118 -0
- data/lib/ree/link_dsl.rb +175 -0
- data/lib/ree/object_compiler.rb +149 -0
- data/lib/ree/package_dsl.rb +34 -0
- data/lib/ree/rspec_link_dsl.rb +19 -0
- data/lib/ree/spec_runner/command_generator.rb +49 -0
- data/lib/ree/spec_runner/command_params.rb +9 -0
- data/lib/ree/spec_runner/runner.rb +200 -0
- data/lib/ree/spec_runner/spec_filename_matcher.rb +27 -0
- data/lib/ree/spec_runner/view.rb +30 -0
- data/lib/ree/spec_runner.rb +11 -0
- data/lib/ree/templates/init/.gitignore +1 -0
- data/lib/ree/templates/init/.irbrc +13 -0
- data/lib/ree/templates/init/.rspec +3 -0
- data/lib/ree/templates/init/.ruby-version +1 -0
- data/lib/ree/templates/init/Gemfile +7 -0
- data/lib/ree/templates/init/Packages.schema.json +1 -0
- data/lib/ree/templates/init/bin/console +5 -0
- data/lib/ree/templates/init/readme.md +2 -0
- data/lib/ree/templates/init/ree.setup.rb +21 -0
- data/lib/ree/templates/init/spec.init.rb +7 -0
- data/lib/ree/templates/package/.gitignore +0 -0
- data/lib/ree/templates/package/.rspec +2 -0
- data/lib/ree/templates/package/<%=package_subdir_name%>/<%=package_name%>/.gitkeep +0 -0
- data/lib/ree/templates/package/<%=package_subdir_name%>/<%=package_name%>.rb +15 -0
- data/lib/ree/templates/package/Package.schema.json +0 -0
- data/lib/ree/templates/package/bin/console +5 -0
- data/lib/ree/templates/package/spec/package_schema_spec.rb +14 -0
- data/lib/ree/templates/package/spec/spec_helper.rb +3 -0
- data/lib/ree/templates/template_detector.rb +35 -0
- data/lib/ree/templates/template_renderer.rb +55 -0
- data/lib/ree/utils/render_utils.rb +20 -0
- data/lib/ree/utils/string_utils.rb +29 -0
- data/lib/ree/version.rb +5 -0
- data/lib/ree.rb +279 -0
- data/sig/ree.rbs +4 -0
- metadata +199 -0
@@ -0,0 +1,170 @@
|
|
1
|
+
# frozen_string_literal = true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
class Ree::PackageSchemaLoader
|
7
|
+
# Sample Package.schema.json
|
8
|
+
# {
|
9
|
+
# "schema_type": "package",
|
10
|
+
# "ree_version": "1.2.3",
|
11
|
+
# "name": "accounts",
|
12
|
+
# "entry_path": "package/accounts.rb",
|
13
|
+
# "depends_on": [
|
14
|
+
# {
|
15
|
+
# "name": "clock",
|
16
|
+
# },
|
17
|
+
# {
|
18
|
+
# "name": "test_utils",
|
19
|
+
# }
|
20
|
+
# ],
|
21
|
+
# "env_vars": [
|
22
|
+
# {
|
23
|
+
# "name": "accounts.string_var",
|
24
|
+
# "doc": null
|
25
|
+
# },
|
26
|
+
# {
|
27
|
+
# "name": "accounts.integer_var",
|
28
|
+
# "doc": "integer value"
|
29
|
+
# }
|
30
|
+
# ],
|
31
|
+
# "objects": [
|
32
|
+
# {
|
33
|
+
# "name": "accounts_cfg",
|
34
|
+
# "schema": "schemas/accounts/accounts_cfg.schema.json"
|
35
|
+
# },
|
36
|
+
# {
|
37
|
+
# "name": "transaction",
|
38
|
+
# "schema": "schemas/accounts/transaction.schema.json"
|
39
|
+
# }
|
40
|
+
# ]
|
41
|
+
# }
|
42
|
+
|
43
|
+
Schema = Ree::PackageSchema
|
44
|
+
|
45
|
+
# @param [String] abs_schema_path Absolute path to package Package.schema.json file
|
46
|
+
# @param [Nilor[Ree::Package]] existing_package Loaded package
|
47
|
+
# @return [Ree::Package]
|
48
|
+
def call(abs_schema_path, existing_package = nil)
|
49
|
+
if !File.exists?(abs_schema_path)
|
50
|
+
raise Ree::Error.new("File not found: #{abs_schema_path}", :invalid_package_schema)
|
51
|
+
end
|
52
|
+
|
53
|
+
json_schema = begin
|
54
|
+
JSON.load_file(abs_schema_path)
|
55
|
+
rescue
|
56
|
+
raise Ree::Error.new("Invalid content: #{abs_schema_path}", :invalid_package_schema)
|
57
|
+
end
|
58
|
+
|
59
|
+
schema_type = json_schema.fetch(Schema::SCHEMA_TYPE)
|
60
|
+
|
61
|
+
if schema_type != Schema::PACKAGE
|
62
|
+
raise Ree::Error.new("Invalid schema type: #{abs_schema_path}", :invalid_package_schema)
|
63
|
+
end
|
64
|
+
|
65
|
+
ree_version = json_schema.fetch(Schema::REE_VERSION)
|
66
|
+
entry_rpath = json_schema.fetch(Schema::ENTRY_PATH)
|
67
|
+
package_name = json_schema.fetch(Schema::NAME).to_sym
|
68
|
+
|
69
|
+
root_dir = if existing_package && existing_package.gem?
|
70
|
+
Ree.gem(existing_package.gem_name).dir
|
71
|
+
else
|
72
|
+
Ree.root_dir
|
73
|
+
end
|
74
|
+
|
75
|
+
schema_rpath = Pathname
|
76
|
+
.new(abs_schema_path)
|
77
|
+
.relative_path_from(Pathname.new(root_dir))
|
78
|
+
.to_s
|
79
|
+
|
80
|
+
object_store = {}
|
81
|
+
deps_store = {}
|
82
|
+
vars_store = {}
|
83
|
+
|
84
|
+
package = if existing_package
|
85
|
+
existing_package
|
86
|
+
.set_ree_version(ree_version)
|
87
|
+
.set_entry_rpath(entry_rpath)
|
88
|
+
.set_schema_rpath(schema_rpath)
|
89
|
+
else
|
90
|
+
Ree::Package.new(
|
91
|
+
ree_version,
|
92
|
+
package_name,
|
93
|
+
entry_rpath,
|
94
|
+
schema_rpath,
|
95
|
+
nil
|
96
|
+
)
|
97
|
+
end
|
98
|
+
|
99
|
+
package.set_schema_loaded
|
100
|
+
|
101
|
+
json_schema.fetch(Schema::OBJECTS).each do |item|
|
102
|
+
name = item[Schema::Objects::NAME].to_s
|
103
|
+
schema_rpath = item[Schema::Objects::SCHEMA].to_s
|
104
|
+
list = [name, schema_rpath]
|
105
|
+
|
106
|
+
if list.reject(&:empty?).size != list.size
|
107
|
+
raise Ree::Error.new("invalid object data for #{item.inspect}: #{abs_schema_path}", :invalid_package_schema)
|
108
|
+
end
|
109
|
+
|
110
|
+
if object_store.has_key?(name)
|
111
|
+
raise Ree::Error.new("duplicate object name for '#{item[:name]}': #{abs_schema_path}", :invalid_package_schema)
|
112
|
+
end
|
113
|
+
|
114
|
+
object_store[name] = true
|
115
|
+
|
116
|
+
object = Ree::Object.new(
|
117
|
+
name.to_sym,
|
118
|
+
schema_rpath,
|
119
|
+
Ree::PathHelper.object_rpath(schema_rpath),
|
120
|
+
)
|
121
|
+
|
122
|
+
object.set_package(package.name)
|
123
|
+
|
124
|
+
package.set_object(object)
|
125
|
+
end
|
126
|
+
|
127
|
+
deps = json_schema.fetch(Schema::DEPENDS_ON).map do |item|
|
128
|
+
name = item[Schema::DependsOn::NAME].to_sym
|
129
|
+
list = [name]
|
130
|
+
|
131
|
+
if list.reject(&:empty?).size != list.size
|
132
|
+
raise Ree::Error.new("invalid depends_on for: #{item.inspect}", :invalid_package_schema)
|
133
|
+
end
|
134
|
+
|
135
|
+
if deps_store.has_key?(name)
|
136
|
+
raise Ree::Error.new("duplicate depends_on name for '#{item[:name]}'", :invalid_package_schema)
|
137
|
+
end
|
138
|
+
|
139
|
+
deps_store[name] = true
|
140
|
+
Ree::PackageDep.new(name)
|
141
|
+
end
|
142
|
+
|
143
|
+
package.set_deps(deps)
|
144
|
+
|
145
|
+
env_vars = json_schema.fetch(Schema::ENV_VARS).map do |item|
|
146
|
+
name = item[Schema::EnvVars::NAME].to_s
|
147
|
+
doc = item[Schema::EnvVars::DOC]
|
148
|
+
list = [name]
|
149
|
+
|
150
|
+
if list.reject(&:empty?).size != list.size
|
151
|
+
raise Ree::Error.new("invalid env_var for: #{item.inspect}", :invalid_package_schema)
|
152
|
+
end
|
153
|
+
|
154
|
+
if vars_store.has_key?(name)
|
155
|
+
raise Ree::Error.new("duplicate env_var name for '#{item[:name]}'", :invalid_package_schema)
|
156
|
+
end
|
157
|
+
|
158
|
+
vars_store[name] = true
|
159
|
+
|
160
|
+
Ree::PackageEnvVar.new(name, doc)
|
161
|
+
end
|
162
|
+
|
163
|
+
package.set_env_vars(env_vars)
|
164
|
+
|
165
|
+
tags = json_schema.fetch(Schema::TAGS)
|
166
|
+
package.set_tags(tags)
|
167
|
+
|
168
|
+
package
|
169
|
+
end
|
170
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal = true
|
2
|
+
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
class Ree::PackagesDetector
|
6
|
+
# @param [String] dir Packages root dir
|
7
|
+
# @return [ArrayOf[{name: String, entry_path: String, package_schema_path: String, gem_name: Nilor[String]}]]
|
8
|
+
def call(dir, gem_name = nil)
|
9
|
+
if !Dir.exists?(dir)
|
10
|
+
raise Ree::Error.new("dir does not exist: #{dir}", :invalid_dir)
|
11
|
+
end
|
12
|
+
|
13
|
+
files = File.join(dir, "**/", Ree::PACKAGE_SCHEMA_FILE)
|
14
|
+
names = {}
|
15
|
+
|
16
|
+
Dir[files].map do |file|
|
17
|
+
package_schema_path = Pathname
|
18
|
+
.new(file)
|
19
|
+
.relative_path_from(Pathname.new(dir))
|
20
|
+
.to_s
|
21
|
+
|
22
|
+
name = package_schema_path.split('/')[-2]
|
23
|
+
entry_path = Ree::PathHelper.package_entry_path(package_schema_path)
|
24
|
+
|
25
|
+
if !File.exists?(File.join(dir, entry_path))
|
26
|
+
Ree.logger.error("Entry file does not exist for '#{name}' package: #{entry_path}")
|
27
|
+
end
|
28
|
+
|
29
|
+
if names.has_key?(name)
|
30
|
+
raise Ree::Error.new("package '#{name}' has duplicate defintions.\n\t1) #{names[name]},\n\t2) #{entry_path}", :duplicate_package)
|
31
|
+
end
|
32
|
+
|
33
|
+
names[name] = entry_path
|
34
|
+
|
35
|
+
{
|
36
|
+
name: name.to_sym,
|
37
|
+
entry_path: entry_path,
|
38
|
+
package_schema_path: package_schema_path,
|
39
|
+
gem_name: gem_name
|
40
|
+
}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal = true
|
2
|
+
|
3
|
+
module Ree::PackagesSchema
|
4
|
+
SCHEMA_TYPE = 'schema_type'
|
5
|
+
REE_VERSION = 'ree_version'
|
6
|
+
PACKAGES = 'packages'
|
7
|
+
GEM_PACKAGES = 'gem_packages'
|
8
|
+
|
9
|
+
module Packages
|
10
|
+
NAME = 'name'
|
11
|
+
SCHEMA = 'schema'
|
12
|
+
GEM = 'gem'
|
13
|
+
end
|
14
|
+
|
15
|
+
module GemPackages
|
16
|
+
NAME = 'name'
|
17
|
+
SCHEMA = 'schema'
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal = true
|
2
|
+
|
3
|
+
require 'pathname'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
class Ree::PackagesSchemaBuilder
|
7
|
+
Schema = Ree::PackagesSchema
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@packages_detector = Ree::PackagesDetector.new
|
11
|
+
end
|
12
|
+
|
13
|
+
# @dir [String] - path to root project dir
|
14
|
+
def call
|
15
|
+
packages = @packages_detector.call(Ree.root_dir)
|
16
|
+
gem_packages = []
|
17
|
+
|
18
|
+
Ree.gems.each do |gem|
|
19
|
+
gem_packages += @packages_detector.call(gem.dir, gem.name)
|
20
|
+
end
|
21
|
+
|
22
|
+
result = {
|
23
|
+
Schema::REE_VERSION => Ree::VERSION,
|
24
|
+
Schema::SCHEMA_TYPE => Schema::PACKAGES,
|
25
|
+
Schema::PACKAGES => packages.sort_by { _1[:name] }.map {
|
26
|
+
{
|
27
|
+
Schema::Packages::NAME => _1.fetch(:name),
|
28
|
+
Schema::Packages::SCHEMA => _1.fetch(:package_schema_path),
|
29
|
+
}
|
30
|
+
},
|
31
|
+
Schema::GEM_PACKAGES => gem_packages.sort_by { [_1.fetch(:gem_name), _1.fetch(:name)] }.map {
|
32
|
+
{
|
33
|
+
Schema::Packages::GEM => _1.fetch(:gem_name),
|
34
|
+
Schema::Packages::NAME => _1.fetch(:name),
|
35
|
+
Schema::Packages::SCHEMA => _1.fetch(:package_schema_path),
|
36
|
+
}
|
37
|
+
},
|
38
|
+
}
|
39
|
+
|
40
|
+
json = JSON.pretty_generate(result)
|
41
|
+
|
42
|
+
File.write(
|
43
|
+
File.join(Ree.root_dir, Ree::PACKAGES_SCHEMA_FILE),
|
44
|
+
json,
|
45
|
+
mode: 'w'
|
46
|
+
)
|
47
|
+
|
48
|
+
result
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal = true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
class Ree::PackagesSchemaLoader
|
6
|
+
# Sample Packages.schema.json
|
7
|
+
# {
|
8
|
+
# "schema_type": "packages",
|
9
|
+
# "ree_version": "1.2.3",
|
10
|
+
# "packages": [
|
11
|
+
# {
|
12
|
+
# "name": "accounts",
|
13
|
+
# "schema": "bc/accounts/Package.schema.json"
|
14
|
+
# },
|
15
|
+
# {
|
16
|
+
# "name": "tests",
|
17
|
+
# "schema": "bc/tests/Package.schema.json"
|
18
|
+
# }
|
19
|
+
# ]
|
20
|
+
# }
|
21
|
+
|
22
|
+
Schema = Ree::PackagesSchema
|
23
|
+
|
24
|
+
# @param [String] path Absolute path to Packages.schema.json file
|
25
|
+
# @param Nilor[Ree::PackagesStore] packages_store Existing packages store
|
26
|
+
# @return [Ree::PackagesStore]
|
27
|
+
def call(abs_schema_path, packages_store = nil, gem_name = nil)
|
28
|
+
if !File.exists?(abs_schema_path)
|
29
|
+
raise Ree::Error.new("File not found: #{abs_schema_path}", :invalid_packages_schema)
|
30
|
+
end
|
31
|
+
|
32
|
+
schema = begin
|
33
|
+
JSON.load_file(abs_schema_path)
|
34
|
+
rescue
|
35
|
+
raise Ree::Error.new("Invalid content: #{abs_schema_path}", :invalid_packages_schema)
|
36
|
+
end
|
37
|
+
|
38
|
+
schema_type = schema.fetch(Schema::SCHEMA_TYPE)
|
39
|
+
|
40
|
+
if schema_type != Schema::PACKAGES
|
41
|
+
raise Ree::Error.new("Invalid schema type: #{abs_schema_path}", :invalid_packages_schema)
|
42
|
+
end
|
43
|
+
|
44
|
+
ree_version = schema.fetch(Schema::REE_VERSION)
|
45
|
+
data = schema.fetch(Schema::PACKAGES)
|
46
|
+
packages_store ||= Ree::PackagesStore.new(ree_version)
|
47
|
+
names = {}
|
48
|
+
|
49
|
+
data.each do |item|
|
50
|
+
name = item[Schema::Packages::NAME].to_s
|
51
|
+
schema_rpath = item[Schema::Packages::SCHEMA].to_s
|
52
|
+
list = [name, schema]
|
53
|
+
|
54
|
+
if list.reject(&:empty?).size != list.size
|
55
|
+
raise Ree::Error.new("invalid package data for: #{item.inspect}", :invalid_packages_schema)
|
56
|
+
end
|
57
|
+
|
58
|
+
if names.has_key?(name)
|
59
|
+
raise Ree::Error.new("duplicate package name for '#{item[:name]}'", :invalid_packages_schema)
|
60
|
+
end
|
61
|
+
|
62
|
+
names[name] = true
|
63
|
+
|
64
|
+
package = Ree::Package.new(
|
65
|
+
ree_version,
|
66
|
+
name.to_sym,
|
67
|
+
Ree::PathHelper.package_entry_path(schema_rpath),
|
68
|
+
schema_rpath,
|
69
|
+
gem_name
|
70
|
+
)
|
71
|
+
|
72
|
+
existing = packages_store.get(package.name)
|
73
|
+
|
74
|
+
if existing && existing.gem_name != package.gem_name
|
75
|
+
if existing.gem_name.nil?
|
76
|
+
raise Ree::Error.new("Unable to add package `#{existing.name}` from `#{package.gem_name}` gem. Project has same package definition.", :duplicate_package)
|
77
|
+
else
|
78
|
+
raise Ree::Error.new("Unable to add package `#{existing.name}` from `#{package.gem_name}` gem. Package was already added from `#{existing.gem_name}` gem.", :duplicate_package)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
packages_store.add_package(
|
83
|
+
Ree::Package.new(
|
84
|
+
ree_version,
|
85
|
+
name.to_sym,
|
86
|
+
Ree::PathHelper.package_entry_path(schema_rpath),
|
87
|
+
schema_rpath,
|
88
|
+
gem_name
|
89
|
+
)
|
90
|
+
)
|
91
|
+
end
|
92
|
+
|
93
|
+
packages_store
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal = true
|
2
|
+
|
3
|
+
class Ree::PackagesSchemaLocator
|
4
|
+
def call(path)
|
5
|
+
find_source_path_in_hierarchy(path)
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def find_source_path_in_hierarchy(some_path)
|
11
|
+
some_path = File.expand_path(some_path)
|
12
|
+
|
13
|
+
raise Ree::Error.new("#{Ree::PACKAGES_SCHEMA_FILE} not found", :packages_json_not_found) if some_path == '/'
|
14
|
+
|
15
|
+
return potential_file(some_path) if present?(some_path)
|
16
|
+
|
17
|
+
find_source_path_in_hierarchy(File.dirname(some_path))
|
18
|
+
end
|
19
|
+
|
20
|
+
def present?(some_path)
|
21
|
+
File.exist?(potential_file(some_path))
|
22
|
+
end
|
23
|
+
|
24
|
+
def potential_file(some_path)
|
25
|
+
File.join(some_path, Ree::PACKAGES_SCHEMA_FILE)
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal = true
|
2
|
+
|
3
|
+
class Ree::PackagesStore
|
4
|
+
attr_reader :ree_version
|
5
|
+
|
6
|
+
def initialize(ree_version = Ree::VERSION)
|
7
|
+
@ree_version = ree_version
|
8
|
+
@store = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def set_ree_version(val)
|
12
|
+
@ree_version = val; self
|
13
|
+
end
|
14
|
+
|
15
|
+
def packages
|
16
|
+
@store.values
|
17
|
+
end
|
18
|
+
|
19
|
+
# @param [Symbol] name
|
20
|
+
# @return [Ree::Package]
|
21
|
+
def get(name)
|
22
|
+
@store[name]
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param [Ree::Package] package
|
26
|
+
def add_package(package)
|
27
|
+
existing = get(package.name)
|
28
|
+
return existing if existing
|
29
|
+
|
30
|
+
@store[package.name] = package
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# frozen_string_literal = true
|
2
|
+
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
class Ree::PathHelper
|
6
|
+
SCHEMAS_FOLDER = 'schemas'
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def abs_package_object_schemas_path(package)
|
10
|
+
root_dir = project_root_dir(package)
|
11
|
+
File.join(root_dir, SCHEMAS_FOLDER)
|
12
|
+
end
|
13
|
+
|
14
|
+
# @param [Ree::Object] object
|
15
|
+
# @return [String] Absolute object file path
|
16
|
+
def abs_object_path(object)
|
17
|
+
package = Ree.container.packages_facade.get_package(object.package_name)
|
18
|
+
File.join(project_root_dir(package), object.rpath)
|
19
|
+
end
|
20
|
+
|
21
|
+
# @param [Ree::Object] object
|
22
|
+
# @return [String] Absolute object schema path
|
23
|
+
def abs_object_schema_path(object)
|
24
|
+
package = Ree.container.packages_facade.get_package(object.package_name)
|
25
|
+
File.join(project_root_dir(package), object.schema_rpath)
|
26
|
+
end
|
27
|
+
|
28
|
+
# @param [String] schema_path Relative path of an object schema (ex. bc/accounts/schemas/accounts/object.schema.json)
|
29
|
+
# @return [String] Relative path to a object source file (ex. bc/accounts/object.rb)
|
30
|
+
def object_rpath(schema_rpath)
|
31
|
+
nodes = schema_rpath.split('/')
|
32
|
+
index = nodes.index(SCHEMAS_FOLDER)
|
33
|
+
nodes[index] = Ree::PACKAGE
|
34
|
+
object_name = nodes[-1].split('.').first
|
35
|
+
filename = "#{object_name}.rb"
|
36
|
+
nodes[-1] = filename
|
37
|
+
nodes.join('/')
|
38
|
+
end
|
39
|
+
|
40
|
+
# @param [String] object_rpath Relative path of an object (bc/accounts/package/accounts/object.rb)
|
41
|
+
# @return [String] Relative path of a object schema (ex. bc/accounts/schemas/accounts/object.schema.json)
|
42
|
+
def object_schema_rpath(object_rpath)
|
43
|
+
nodes = object_rpath.split('/')
|
44
|
+
index = nodes.index(Ree::PACKAGE)
|
45
|
+
nodes[index] = Ree::SCHEMAS
|
46
|
+
filename = File.basename(nodes[-1], '.*')
|
47
|
+
schema_name = "#{filename}.#{Ree::SCHEMA}.json"
|
48
|
+
nodes[-1] = schema_name
|
49
|
+
nodes.join('/')
|
50
|
+
end
|
51
|
+
|
52
|
+
# @param [String] schema_path Absolute or relative path of a package schema (bc/accounts/package/accounts/Package.json)
|
53
|
+
# @return [String] Absolute or relative path of a package entry file (ex. bc/accounts/schemas/accounts.rb)
|
54
|
+
def package_entry_path(schema_path)
|
55
|
+
dir = Pathname.new(schema_path).dirname.to_s
|
56
|
+
name = dir.split('/').last
|
57
|
+
File.join(dir, "#{Ree::PACKAGE}/#{name}.rb")
|
58
|
+
end
|
59
|
+
|
60
|
+
# @param [Ree::Package] package Package schema
|
61
|
+
# @return [String] Absolute package entry path (ex. /data/project/bc/accounts/package/accounts.rb)
|
62
|
+
def abs_package_entry_path(package)
|
63
|
+
File.join(project_root_dir(package), package.entry_rpath)
|
64
|
+
end
|
65
|
+
|
66
|
+
# @param [Ree::Package] package Package schema
|
67
|
+
# @return [String] Absolute package folder path (ex. /data/project/bc/accounts/package/accounts)
|
68
|
+
def abs_package_module_dir(package)
|
69
|
+
File.join(
|
70
|
+
project_root_dir(package), package.dir, Ree::PACKAGE, package.name.to_s
|
71
|
+
)
|
72
|
+
end
|
73
|
+
|
74
|
+
# @param [Ree::Package] package Package schema
|
75
|
+
# @return [String] Absolute package schema path
|
76
|
+
def abs_package_schema_path(package)
|
77
|
+
File.join(project_root_dir(package), package.schema_rpath)
|
78
|
+
end
|
79
|
+
|
80
|
+
# @param [Ree::Package] package Package schema
|
81
|
+
# @return [String] Absolute package folder path (ex. /data/project/bc/accounts)
|
82
|
+
def abs_package_dir(package)
|
83
|
+
File.join(project_root_dir(package), package.dir)
|
84
|
+
end
|
85
|
+
|
86
|
+
# @param [Ree::Package] package Package schema
|
87
|
+
# @param [String] absolute file path
|
88
|
+
# @return [String] File path relative to package (ex. accounts/entities/user.rb)
|
89
|
+
def package_relative_path(package, path)
|
90
|
+
Pathname
|
91
|
+
.new(path)
|
92
|
+
.relative_path_from(File.join(Ree.root_dir, package.dir, Ree::PACKAGE))
|
93
|
+
.to_s
|
94
|
+
end
|
95
|
+
|
96
|
+
def project_root_dir(package)
|
97
|
+
if package.gem?
|
98
|
+
Ree.gem(package.gem_name).dir
|
99
|
+
else
|
100
|
+
Ree.root_dir
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
# frozen_string_literal = true
|
2
|
+
|
3
|
+
class Ree::BuildPackageDsl
|
4
|
+
include Ree::Args
|
5
|
+
|
6
|
+
attr_reader :package
|
7
|
+
|
8
|
+
# @param [Ree::PackagesFacade] packages_facade
|
9
|
+
# @param [Module] mod
|
10
|
+
# @param [Nilor[String]] path
|
11
|
+
def initialize(packages_facade, mod)
|
12
|
+
@packages_facade = packages_facade
|
13
|
+
@package = register_package(mod)
|
14
|
+
end
|
15
|
+
|
16
|
+
# @param [ArrayOf[String]] lists
|
17
|
+
def tags(list)
|
18
|
+
list.each do |tag|
|
19
|
+
check_arg(tag, :tag, String)
|
20
|
+
end
|
21
|
+
|
22
|
+
list += [@package.name.to_s]
|
23
|
+
list.uniq
|
24
|
+
|
25
|
+
@package.set_tags(list)
|
26
|
+
end
|
27
|
+
|
28
|
+
# @param [Symbol] depends_on
|
29
|
+
def depends_on(depends_on)
|
30
|
+
check_arg(depends_on, :depends_on, Symbol)
|
31
|
+
|
32
|
+
if depends_on == @package.name
|
33
|
+
raise_error("A package cannot depend on itself")
|
34
|
+
end
|
35
|
+
|
36
|
+
if @package.get_dep(depends_on)
|
37
|
+
raise_error("Dependent package :#{depends_on} already added for package :#{@package.name}")
|
38
|
+
end
|
39
|
+
|
40
|
+
package_dep = @package.set_dep(
|
41
|
+
Ree::PackageDep.new(depends_on)
|
42
|
+
)
|
43
|
+
|
44
|
+
dep_package = begin
|
45
|
+
@packages_facade.get_package(depends_on)
|
46
|
+
rescue Ree::Error
|
47
|
+
raise_error("Dependent package :#{depends_on} was not found in #{Ree::PACKAGES_SCHEMA_FILE}. Run `ree gen.packages_json` to update schema or fix package name")
|
48
|
+
end
|
49
|
+
|
50
|
+
@packages_facade.load_package_entry(dep_package.name)
|
51
|
+
|
52
|
+
package_dep
|
53
|
+
end
|
54
|
+
|
55
|
+
# @param [Proc] block
|
56
|
+
def default_links(&block)
|
57
|
+
raise Ree::Error.new("block missing") if !block_given?
|
58
|
+
|
59
|
+
@package.set_default_links(&block)
|
60
|
+
end
|
61
|
+
|
62
|
+
# @param [String] var_name
|
63
|
+
# @param [Nilor[String]] doc
|
64
|
+
def env_var(var_name, doc: nil)
|
65
|
+
check_arg(var_name, :env_var, String)
|
66
|
+
check_arg(doc, :doc, String) if doc
|
67
|
+
|
68
|
+
if @package.get_env_var(var_name)
|
69
|
+
raise_error("Duplicate env var '#{var_name}'")
|
70
|
+
end
|
71
|
+
|
72
|
+
@package.set_env_var(
|
73
|
+
Ree::PackageEnvVar.new(
|
74
|
+
var_name, doc
|
75
|
+
)
|
76
|
+
)
|
77
|
+
end
|
78
|
+
|
79
|
+
# @param [HashOf[Symbol, ArrayOf[Symbol]]] opts
|
80
|
+
def preload(opts)
|
81
|
+
check_arg(opts, :opts, Hash)
|
82
|
+
|
83
|
+
opts.each do |env, list|
|
84
|
+
check_arg(list, :object_list, Array)
|
85
|
+
|
86
|
+
list.each do |object_name|
|
87
|
+
check_arg(object_name, :object_name, Symbol)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
@package.set_preload(opts)
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def check_module(mod)
|
97
|
+
check_arg(mod, :module_name, Module)
|
98
|
+
module_name = mod.to_s
|
99
|
+
list = module_name.split('::')
|
100
|
+
|
101
|
+
if list.size != 1
|
102
|
+
raise Ree::Error.new("depends_on should be defined for top level modules only", :invalid_dsl_usage)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def register_package(mod)
|
107
|
+
check_module(mod)
|
108
|
+
check_arg(mod, :module, Module)
|
109
|
+
|
110
|
+
if mod.name.nil?
|
111
|
+
raise Ree::Error.new("package decorator should be applied to a named module", :invalid_dsl_usage)
|
112
|
+
end
|
113
|
+
|
114
|
+
path = Object.const_source_location(mod.name)[0].split(':').first
|
115
|
+
module_name = mod.to_s
|
116
|
+
list = module_name.split('::')
|
117
|
+
|
118
|
+
if list.size != 1
|
119
|
+
raise Ree::Error.new("package should be defined for top level modules only", :invalid_dsl_usage)
|
120
|
+
end
|
121
|
+
|
122
|
+
name_from_path = File.basename(path, ".*").to_sym
|
123
|
+
name = Ree::StringUtils.underscore(list[0]).to_sym
|
124
|
+
|
125
|
+
if !Ree.irb_mode? && name != name_from_path
|
126
|
+
raise Ree::Error.new("Package module '#{module_name}' does not correspond to package name 'name'. Fix file name or module name.")
|
127
|
+
end
|
128
|
+
|
129
|
+
package = @packages_facade.get_package(name, false)
|
130
|
+
|
131
|
+
if package.nil?
|
132
|
+
package = Ree::Package.new(Ree::VERSION, name, nil, nil, nil)
|
133
|
+
@packages_facade.store_package(package)
|
134
|
+
end
|
135
|
+
|
136
|
+
package.set_module(mod)
|
137
|
+
package.set_tags([name])
|
138
|
+
|
139
|
+
package.reset
|
140
|
+
package.set_entry_loaded
|
141
|
+
package.set_loaded
|
142
|
+
|
143
|
+
package
|
144
|
+
end
|
145
|
+
|
146
|
+
def raise_error(text, code = :invalid_dsl_usage)
|
147
|
+
msg = <<~DOC
|
148
|
+
package: :#{@package.name}
|
149
|
+
path: #{File.join(Ree.root_dir, @package.entry_rpath)}
|
150
|
+
error: #{text}
|
151
|
+
DOC
|
152
|
+
|
153
|
+
raise Ree::Error.new(msg, code)
|
154
|
+
end
|
155
|
+
end
|