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,197 @@
|
|
1
|
+
# frozen_string_literal = true
|
2
|
+
|
3
|
+
class Ree::PackagesFacade
|
4
|
+
include Ree::Args
|
5
|
+
|
6
|
+
attr_reader :packages_store, :package_loader
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
load_packages_schema
|
10
|
+
@package_loader = Ree::PackageLoader.new(@packages_store)
|
11
|
+
end
|
12
|
+
|
13
|
+
class << self
|
14
|
+
def write_packages_schema
|
15
|
+
Ree.logger.debug("write_packages_schema")
|
16
|
+
Ree::PackagesSchemaBuilder.new.call
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def perf_mode?(package)
|
21
|
+
package.gem? ? true : Ree.performance_mode?
|
22
|
+
end
|
23
|
+
|
24
|
+
# @param [Symbol] package_name
|
25
|
+
# @return [Ree::Package]
|
26
|
+
def get_loaded_package(package_name)
|
27
|
+
package = get_package(package_name)
|
28
|
+
return package if package.schema_loaded?
|
29
|
+
|
30
|
+
if perf_mode?(package)
|
31
|
+
read_package_schema_json(package_name)
|
32
|
+
else
|
33
|
+
load_entire_package(package_name)
|
34
|
+
end
|
35
|
+
|
36
|
+
package
|
37
|
+
end
|
38
|
+
|
39
|
+
# @param [Symbol] package_name
|
40
|
+
# @param [Symbol] object_name
|
41
|
+
# @return [Ree::Object]
|
42
|
+
def get_object(package_name, object_name)
|
43
|
+
package = get_loaded_package(package_name)
|
44
|
+
object = package.get_object(object_name)
|
45
|
+
|
46
|
+
if !object && perf_mode?(package)
|
47
|
+
raise Ree::Error.new("Ree object :#{object_name} for package :#{package_name} not found")
|
48
|
+
end
|
49
|
+
|
50
|
+
object
|
51
|
+
end
|
52
|
+
|
53
|
+
# @param [Symbol] package_name
|
54
|
+
# @return nil
|
55
|
+
def write_package_schema(package_name)
|
56
|
+
Ree.logger.debug("write_package_schema(:#{package_name})")
|
57
|
+
|
58
|
+
load_entire_package(package_name)
|
59
|
+
package = get_package(package_name)
|
60
|
+
|
61
|
+
if package.dir
|
62
|
+
schema_path = Ree::PathHelper.abs_package_schema_path(package)
|
63
|
+
Ree::PackageSchemaBuilder.new.call(package, schema_path)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# @param [Symbol] package_name
|
68
|
+
# @param [Symbol] object_name
|
69
|
+
# @return [String]
|
70
|
+
def write_object_schema(package_name, object_name)
|
71
|
+
Ree.logger.debug("write_object_schema(package_name: #{package_name}, object_name: #{object_name})")
|
72
|
+
object = get_object(package_name, object_name)
|
73
|
+
|
74
|
+
if !object || (object && !object&.schema_rpath)
|
75
|
+
raise Ree::Error.new("Object :#{object_name} schema path not found")
|
76
|
+
end
|
77
|
+
|
78
|
+
schema_path = Ree::PathHelper.abs_object_schema_path(object)
|
79
|
+
|
80
|
+
Ree::ObjectSchemaBuilder.new.call(object, schema_path)
|
81
|
+
end
|
82
|
+
|
83
|
+
# @param [Symbol] package_name
|
84
|
+
# @return nil
|
85
|
+
def load_package_entry(package_name)
|
86
|
+
package = @packages_store.get(package_name)
|
87
|
+
return if package.loaded?
|
88
|
+
|
89
|
+
Ree.logger.debug("load_package_entry(:#{package_name})")
|
90
|
+
|
91
|
+
load_file(
|
92
|
+
Ree::PathHelper.abs_package_entry_path(package),
|
93
|
+
package_name
|
94
|
+
)
|
95
|
+
end
|
96
|
+
|
97
|
+
# @param [Symbol] package_name
|
98
|
+
# @param [Symbol] object_name
|
99
|
+
# @return [Ree::Object]
|
100
|
+
def load_package_object(package_name, object_name)
|
101
|
+
package = get_loaded_package(package_name)
|
102
|
+
load_package_entry(package_name)
|
103
|
+
|
104
|
+
object = get_object(package_name, object_name)
|
105
|
+
return object if object && object.loaded?
|
106
|
+
|
107
|
+
if !object && !perf_mode?(package)
|
108
|
+
Dir[
|
109
|
+
File.join(
|
110
|
+
Ree::PathHelper.abs_package_module_dir(package),
|
111
|
+
"**/#{object_name}.rb"
|
112
|
+
)
|
113
|
+
].each do |path|
|
114
|
+
load_file(path, package_name)
|
115
|
+
end
|
116
|
+
|
117
|
+
object = get_object(package_name, object_name)
|
118
|
+
end
|
119
|
+
|
120
|
+
if !object
|
121
|
+
raise Ree::Error.new("object :#{object_name} from :#{package_name} was not found")
|
122
|
+
end
|
123
|
+
|
124
|
+
Ree.logger.debug("load_package_object(:#{package_name}, :#{object_name})")
|
125
|
+
|
126
|
+
if object.rpath
|
127
|
+
object_path = Ree::PathHelper.abs_object_path(object)
|
128
|
+
load_file(object_path, package_name)
|
129
|
+
end
|
130
|
+
|
131
|
+
object
|
132
|
+
end
|
133
|
+
|
134
|
+
# @param [Symbol] package_name
|
135
|
+
# @return [Ree::Package]
|
136
|
+
def load_entire_package(package_name)
|
137
|
+
@package_loader.call(package_name)
|
138
|
+
end
|
139
|
+
|
140
|
+
# @param [Symbol] package_name
|
141
|
+
# @return [Ree::Package]
|
142
|
+
def read_package_schema_json(package_name)
|
143
|
+
@loaded_schemas ||= {}
|
144
|
+
return @loaded_schemas[package_name] if @loaded_schemas[package_name]
|
145
|
+
|
146
|
+
Ree.logger.debug("read_package_schema_json(:#{package_name})")
|
147
|
+
package = get_package(package_name)
|
148
|
+
|
149
|
+
if !package.dir
|
150
|
+
package.set_schema_loaded
|
151
|
+
return package
|
152
|
+
end
|
153
|
+
|
154
|
+
schema_path = Ree::PathHelper.abs_package_schema_path(package)
|
155
|
+
@loaded_schemas[package_name] = Ree::PackageSchemaLoader.new.call(schema_path, package)
|
156
|
+
end
|
157
|
+
|
158
|
+
# @return [Ree::PackagesStore]
|
159
|
+
def load_packages_schema
|
160
|
+
Ree.logger.debug("load_packages_schema: #{self.object_id}")
|
161
|
+
@packages_store = Ree::PackagesSchemaLoader.new.call(Ree.packages_schema_path, @packages_store)
|
162
|
+
|
163
|
+
Ree.gems.each do |gem|
|
164
|
+
Ree::PackagesSchemaLoader.new.call(
|
165
|
+
gem.packages_schema_path, @packages_store, gem.name
|
166
|
+
)
|
167
|
+
end
|
168
|
+
|
169
|
+
@packages_store
|
170
|
+
end
|
171
|
+
|
172
|
+
# @param [Symbol] package_name
|
173
|
+
# @return [Ree::Package]
|
174
|
+
def get_package(package_name, raise_if_missing = true)
|
175
|
+
check_arg(package_name, :package_name, Symbol)
|
176
|
+
package = @packages_store.get(package_name)
|
177
|
+
|
178
|
+
if !package && raise_if_missing
|
179
|
+
raise Ree::Error.new("Package :#{package_name} is not found in Packages.schema.json. Run `ree gen.packages_json` to update schema.", :package_schema_not_found)
|
180
|
+
end
|
181
|
+
|
182
|
+
package
|
183
|
+
end
|
184
|
+
|
185
|
+
# @param [Ree::Package] package
|
186
|
+
# @return [Ree::Package]
|
187
|
+
def store_package(package)
|
188
|
+
@packages_store.add_package(package)
|
189
|
+
end
|
190
|
+
|
191
|
+
# @param [String] path
|
192
|
+
# @param [Symbol] package_name
|
193
|
+
# @return [nil]
|
194
|
+
def load_file(path, package_name)
|
195
|
+
@package_loader.load_file(path, package_name)
|
196
|
+
end
|
197
|
+
end
|
data/lib/ree/fn_dsl.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ree::FnDSL
|
4
|
+
def self.included(base)
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.extended(base)
|
9
|
+
base.extend(ClassMethods)
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
def fn(name, &proc)
|
14
|
+
dsl = Ree::ObjectDsl.new(
|
15
|
+
Ree.container.packages_facade, name, self, :fn
|
16
|
+
)
|
17
|
+
|
18
|
+
dsl.instance_exec(&proc) if block_given?
|
19
|
+
dsl.object.set_as_compiled(false)
|
20
|
+
|
21
|
+
Ree.container.compile(dsl.package, name)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/ree/gen/init.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal = true
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
module Ree
|
7
|
+
module Gen
|
8
|
+
class Init
|
9
|
+
TEMPLATE_NAME = 'init'
|
10
|
+
INIT_PATH = './'
|
11
|
+
LOCAL_TEMPLATES_PATH = '.ree/templates'
|
12
|
+
|
13
|
+
class << self
|
14
|
+
def generate(project_path:, test: 'rspec', console: 'irb', stdout: STDOUT)
|
15
|
+
Ree::Gen::Init.new(project_path, test, console, stdout).generate
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(project_path, test, console, stdout)
|
20
|
+
@project_path = project_path
|
21
|
+
@test = test
|
22
|
+
@console = console
|
23
|
+
@template_detector = Ree::TemplateDetector.new(project_path)
|
24
|
+
@stdout = stdout
|
25
|
+
end
|
26
|
+
|
27
|
+
def generate
|
28
|
+
if @project_path.nil? || @project_path.empty?
|
29
|
+
raise Ree::Error.new("Project folder not specified. Type path to ree project, ex: 'ree init .'")
|
30
|
+
end
|
31
|
+
|
32
|
+
if !Dir.exist?(@project_path)
|
33
|
+
raise Ree::Error.new("#{@project_path} doesn't exist. Initialize new ree project with existing directory")
|
34
|
+
end
|
35
|
+
|
36
|
+
if File.exist?(File.join(@project_path, Ree::PACKAGES_SCHEMA_FILE))
|
37
|
+
raise Ree::Error.new("#{@project_path} has already #{Ree::PACKAGES_SCHEMA_FILE}")
|
38
|
+
end
|
39
|
+
|
40
|
+
generated_files = Ree::TemplateHandler.generate(
|
41
|
+
template_name: TEMPLATE_NAME,
|
42
|
+
project_path: @project_path,
|
43
|
+
local_path: INIT_PATH,
|
44
|
+
stdout: @stdout
|
45
|
+
)
|
46
|
+
|
47
|
+
FileUtils.mkdir_p(local_templates_path)
|
48
|
+
|
49
|
+
FileUtils.cp_r(
|
50
|
+
@template_detector.gem_template_folder('package'),
|
51
|
+
File.dirname(@template_detector.project_template_folder('package'))
|
52
|
+
)
|
53
|
+
|
54
|
+
generated_files
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def local_templates_path
|
60
|
+
File.join(@project_path, LOCAL_TEMPLATES_PATH)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal = true
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
module Ree
|
7
|
+
module Gen
|
8
|
+
class Package
|
9
|
+
TEMPLATE_NAME = 'package'
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def generate(package_name:, project_path:, local_path:, locals: {})
|
13
|
+
Ree::Gen::Package.new(package_name, project_path, local_path, locals).create
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(package_name, project_path, local_path, locals = {})
|
18
|
+
@project_path = project_path
|
19
|
+
@package_name = package_name
|
20
|
+
@local_path = local_path
|
21
|
+
@locals = locals
|
22
|
+
@schema = get_schema
|
23
|
+
end
|
24
|
+
|
25
|
+
def create
|
26
|
+
if Dir.exist?(File.join(Ree.root_dir, @local_path))
|
27
|
+
raise Ree::Error.new("Package directory #{@local_path} already exists")
|
28
|
+
end
|
29
|
+
|
30
|
+
if @package_name.nil? || @package_name.empty?
|
31
|
+
raise Ree::Error.new('Package name was not specified')
|
32
|
+
end
|
33
|
+
|
34
|
+
if @schema.packages.map(&:name).include?(@package_name)
|
35
|
+
raise Ree::Error.new('Package already exists')
|
36
|
+
end
|
37
|
+
|
38
|
+
generated_files = Ree::TemplateHandler.generate(
|
39
|
+
template_name: TEMPLATE_NAME,
|
40
|
+
project_path: @project_path,
|
41
|
+
local_path: @local_path,
|
42
|
+
locals: { package_name: @package_name, local_path: @local_path }.merge(@locals)
|
43
|
+
)
|
44
|
+
|
45
|
+
generated_files
|
46
|
+
end
|
47
|
+
|
48
|
+
def get_schema
|
49
|
+
@schema ||= begin
|
50
|
+
Ree.init(@project_path)
|
51
|
+
Ree.container.packages_facade.load_packages_schema
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/ree/gen.rb
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
# frozen_string_literal = true
|
2
|
+
|
3
|
+
require 'pathname'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
class Ree::TemplateHandler
|
7
|
+
REJECTED_TEMPLATE_FILES = %W(.DS_Store)
|
8
|
+
NOT_HANDLED_TEMPLATES_EXT = %W(.erb)
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def generate(template_name:, local_path:, project_path:, locals: {},
|
12
|
+
stdout: STDOUT, stdin: STDIN)
|
13
|
+
|
14
|
+
Ree::TemplateHandler.new(
|
15
|
+
template_name: template_name.to_s,
|
16
|
+
local_path: local_path,
|
17
|
+
project_path: project_path,
|
18
|
+
locals: locals,
|
19
|
+
stdout: stdout,
|
20
|
+
stdin: stdin
|
21
|
+
).generate
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(
|
26
|
+
template_name:,
|
27
|
+
local_path:,
|
28
|
+
project_path:,
|
29
|
+
locals:,
|
30
|
+
stdout:,
|
31
|
+
stdin:
|
32
|
+
)
|
33
|
+
|
34
|
+
@template_name = template_name
|
35
|
+
@local_path = local_path
|
36
|
+
@project_path = project_path
|
37
|
+
@missing_variables = []
|
38
|
+
@stdout = stdout
|
39
|
+
@stdin = stdin
|
40
|
+
default_locals = { package_subdir_name: 'package' }
|
41
|
+
@locals = default_locals.merge(locals)
|
42
|
+
end
|
43
|
+
|
44
|
+
def generate
|
45
|
+
project_path = @project_path
|
46
|
+
template_detector = Ree::TemplateDetector.new(project_path)
|
47
|
+
|
48
|
+
@template_directory = template_detector.detect_template_folder(@template_name)
|
49
|
+
@destination_directory = File.join(project_path, @local_path)
|
50
|
+
|
51
|
+
template_files_list = Dir
|
52
|
+
.glob(File.join(@template_directory, '**', '*'), File::FNM_DOTMATCH)
|
53
|
+
.reject { |path| REJECTED_TEMPLATE_FILES.include? File.basename(path) }
|
54
|
+
|
55
|
+
template_files_list.each do |path|
|
56
|
+
@missing_variables.concat(
|
57
|
+
Ree::TemplateRenderer.get_undefined_variables(get_destination_path(path), @locals)
|
58
|
+
)
|
59
|
+
|
60
|
+
if handle_file_content?(path)
|
61
|
+
@missing_variables.concat(
|
62
|
+
Ree::TemplateRenderer.get_undefined_variables(File.read(path), @locals)
|
63
|
+
)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
if @missing_variables.any?
|
68
|
+
@missing_variables.uniq!
|
69
|
+
|
70
|
+
@stdout.puts "Undefined variables were found:"
|
71
|
+
@missing_variables.size.times { |t| @stdout.puts " #{t+1}. #{@missing_variables[t]}" }
|
72
|
+
|
73
|
+
@missing_variables.each do |var|
|
74
|
+
@stdout.print "Type value for '#{var}': "
|
75
|
+
@locals[var] = @stdin.gets.chomp
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
template_files_list.map! do |path|
|
80
|
+
rendered_abs_path = Ree::TemplateRenderer.handle(get_destination_path(path), @locals)
|
81
|
+
rendered_rel_path = Pathname.new(rendered_abs_path).relative_path_from Pathname.new(project_path)
|
82
|
+
|
83
|
+
if File.file?(rendered_abs_path) && File.exists?(rendered_abs_path)
|
84
|
+
@stdout.puts "Warning! #{rendered_rel_path} already exists. Skipping file creation..."
|
85
|
+
next
|
86
|
+
end
|
87
|
+
|
88
|
+
if File.directory?(path)
|
89
|
+
FileUtils.mkdir_p(rendered_abs_path)
|
90
|
+
next
|
91
|
+
end
|
92
|
+
|
93
|
+
rendered_file_content = handle_file_content?(path) ?
|
94
|
+
Ree::TemplateRenderer.handle(File.read(path), @locals) :
|
95
|
+
File.read(path)
|
96
|
+
|
97
|
+
FileUtils.mkdir_p(File.dirname(rendered_abs_path))
|
98
|
+
File.open(rendered_abs_path, 'w') { |f| f.write rendered_file_content }
|
99
|
+
|
100
|
+
rendered_rel_path
|
101
|
+
end
|
102
|
+
|
103
|
+
template_files_list.compact
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
def get_destination_path(file)
|
109
|
+
return nil unless defined? @template_directory && defined? @destination_directory
|
110
|
+
|
111
|
+
template_rel_path = Pathname.new(file).relative_path_from Pathname.new(@template_directory)
|
112
|
+
File.join(@destination_directory, template_rel_path)
|
113
|
+
end
|
114
|
+
|
115
|
+
def handle_file_content?(path)
|
116
|
+
File.file?(path) && !NOT_HANDLED_TEMPLATES_EXT.include?(File.extname(path))
|
117
|
+
end
|
118
|
+
end
|
data/lib/ree/link_dsl.rb
ADDED
@@ -0,0 +1,175 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ree::LinkDSL
|
4
|
+
def self.included(base)
|
5
|
+
validate(base)
|
6
|
+
base.extend(ClassMethods)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.extended(base)
|
10
|
+
validate(base)
|
11
|
+
base.extend(ClassMethods)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.validate(base)
|
15
|
+
if !base.is_a?(Class)
|
16
|
+
raise ArgumentError, "Ree::LinkDSL should be included to named classed only"
|
17
|
+
end
|
18
|
+
|
19
|
+
if self.name.nil?
|
20
|
+
raise ArgumentError, "LinkDSL does not support anonymous classes"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
module ClassMethods
|
25
|
+
include Ree::Args
|
26
|
+
|
27
|
+
def link(*args, **kwargs)
|
28
|
+
if args.first.is_a?(Symbol)
|
29
|
+
_link_object(*args, **kwargs)
|
30
|
+
elsif args.first.is_a?(String)
|
31
|
+
_link_file(args[0], args[1])
|
32
|
+
else
|
33
|
+
_raise_error("Invalid link DSL usage. Args should be Hash or String")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
# @param [Symbol] object_name
|
40
|
+
# @param [Nilor[Symbol]] as
|
41
|
+
# @param [Nilor[Symbol]] from
|
42
|
+
# @param [Nilor[ArrayOf[Symbol]]] methods
|
43
|
+
# @param [Nilor[Proc]] import
|
44
|
+
def _link_object(object_name, as: nil, from: nil, methods: nil, import: nil)
|
45
|
+
check_arg(object_name, :object_name, Symbol)
|
46
|
+
check_arg(as, :as, Symbol) if as
|
47
|
+
check_arg(from, :from, Symbol) if from
|
48
|
+
check_arg(import, :import, Proc) if import
|
49
|
+
check_arg_array_of(methods, :methods, Symbol) if methods
|
50
|
+
|
51
|
+
package_name = Ree::StringUtils.underscore(self.name.split('::').first).to_sym
|
52
|
+
link_package_name = from.nil? ? package_name : from
|
53
|
+
link_object_name = object_name
|
54
|
+
link_as = as ? as : object_name
|
55
|
+
|
56
|
+
_check_package_dependency_added(link_package_name, package_name)
|
57
|
+
|
58
|
+
if import
|
59
|
+
Ree::LinkImportBuilder
|
60
|
+
.new(Ree.container.packages_facade)
|
61
|
+
.build(
|
62
|
+
self,
|
63
|
+
link_package_name,
|
64
|
+
link_object_name,
|
65
|
+
import
|
66
|
+
)
|
67
|
+
end
|
68
|
+
|
69
|
+
obj = Ree
|
70
|
+
.container
|
71
|
+
.packages_facade
|
72
|
+
.load_package_object(link_package_name, link_object_name)
|
73
|
+
|
74
|
+
if obj.fn?
|
75
|
+
self.class_eval %Q(
|
76
|
+
private def _#{link_as}
|
77
|
+
@#{link_as} ||= #{obj.klass}.new
|
78
|
+
end
|
79
|
+
|
80
|
+
private def #{link_as}(*args, **kwargs, &block)
|
81
|
+
_#{link_as}.call(*args, **kwargs, &block)
|
82
|
+
end
|
83
|
+
)
|
84
|
+
else
|
85
|
+
self.class_eval %Q(
|
86
|
+
private def #{link_as}
|
87
|
+
@#{link_as} ||= #{obj.klass}.new
|
88
|
+
end
|
89
|
+
)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# @param [String] path Relative package file path ('accounts/entities/user')
|
94
|
+
# @param [Proc] proc Import constants proc
|
95
|
+
def _link_file(path, import_proc = nil)
|
96
|
+
check_arg(import_proc, :import, Proc) if import_proc
|
97
|
+
|
98
|
+
list = path.split('/')
|
99
|
+
package_name = File.basename(list[0], ".*").to_sym
|
100
|
+
current_package_name = Ree::StringUtils.underscore(self.name.split('::').first).to_sym
|
101
|
+
|
102
|
+
_check_package_dependency_added(package_name, current_package_name)
|
103
|
+
|
104
|
+
Ree.container.packages_facade.load_package_entry(package_name)
|
105
|
+
package = Ree.container.packages_facade.get_package(package_name)
|
106
|
+
|
107
|
+
file_path = File.join(
|
108
|
+
Ree::PathHelper.abs_package_dir(package),
|
109
|
+
Ree::PACKAGE, path
|
110
|
+
)
|
111
|
+
|
112
|
+
if !File.exists?(file_path)
|
113
|
+
file_path = "#{file_path}.rb"
|
114
|
+
|
115
|
+
if !File.exists?(file_path)
|
116
|
+
_raise_error("Unable to link '#{path}'. File not found #{file_path}")
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
Ree.container.packages_facade.load_file(file_path, package.name)
|
121
|
+
|
122
|
+
const_list = path.split('/').map { |_| Ree::StringUtils.camelize(_) }
|
123
|
+
const_short = [const_list[0], const_list.last].join("::")
|
124
|
+
const_long = const_list.join("::")
|
125
|
+
|
126
|
+
file_const = if Object.const_defined?(const_long)
|
127
|
+
Object.const_get(const_long)
|
128
|
+
elsif Object.const_defined?(const_short)
|
129
|
+
Object.const_get(const_short)
|
130
|
+
else
|
131
|
+
_raise_error("Unable to link '#{path}'. #{const_long} or #{const_short} was not defined in #{file_path}")
|
132
|
+
end
|
133
|
+
|
134
|
+
if import_proc
|
135
|
+
Ree::LinkImportBuilder
|
136
|
+
.new(Ree.container.packages_facade)
|
137
|
+
.build_for_const(
|
138
|
+
self,
|
139
|
+
file_const,
|
140
|
+
import_proc
|
141
|
+
)
|
142
|
+
end
|
143
|
+
|
144
|
+
nil
|
145
|
+
end
|
146
|
+
|
147
|
+
def _raise_error(text, code = :invalid_dsl_usage)
|
148
|
+
msg = <<~DOC
|
149
|
+
object: :#{@object.name}
|
150
|
+
path: #{Ree::PathHelper.abs_object_path(@object)}
|
151
|
+
error: #{text}
|
152
|
+
DOC
|
153
|
+
|
154
|
+
raise Ree::Error.new(msg, code)
|
155
|
+
end
|
156
|
+
|
157
|
+
def _check_package_dependency_added(package_name, current_package_name)
|
158
|
+
return if package_name == current_package_name
|
159
|
+
|
160
|
+
facade = Ree.container.packages_facade
|
161
|
+
facade.load_package_entry(package_name)
|
162
|
+
facade.load_package_entry(current_package_name)
|
163
|
+
|
164
|
+
current_package = facade.get_package(current_package_name)
|
165
|
+
|
166
|
+
dep_package = current_package.deps.detect do |d|
|
167
|
+
d.name == package_name
|
168
|
+
end
|
169
|
+
|
170
|
+
if dep_package.nil?
|
171
|
+
raise_error("Package :#{package_name} is not added as dependency for :#{current_package_name} package\npackage path: #{File.join(Ree.root_dir, current_package)}")
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|