ree 1.0.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.
Files changed (140) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +13 -0
  4. data/.ruby-version +1 -0
  5. data/CHANGELOG.md +5 -0
  6. data/CODE_OF_CONDUCT.md +84 -0
  7. data/Gemfile +9 -0
  8. data/Gemfile.lock +41 -0
  9. data/LICENSE.txt +21 -0
  10. data/README.md +474 -0
  11. data/Rakefile +8 -0
  12. data/bin/console +8 -0
  13. data/bin/setup +8 -0
  14. data/exe/ree +264 -0
  15. data/lib/ree/args.rb +34 -0
  16. data/lib/ree/bean_dsl.rb +24 -0
  17. data/lib/ree/cli/generate_package.rb +18 -0
  18. data/lib/ree/cli/generate_package_schema.rb +54 -0
  19. data/lib/ree/cli/generate_packages_schema.rb +17 -0
  20. data/lib/ree/cli/generate_template.rb +20 -0
  21. data/lib/ree/cli/init.rb +22 -0
  22. data/lib/ree/cli/spec_runner.rb +184 -0
  23. data/lib/ree/cli.rb +12 -0
  24. data/lib/ree/container.rb +67 -0
  25. data/lib/ree/contracts/arg_contracts/any.rb +15 -0
  26. data/lib/ree/contracts/arg_contracts/array_of.rb +52 -0
  27. data/lib/ree/contracts/arg_contracts/block.rb +15 -0
  28. data/lib/ree/contracts/arg_contracts/bool.rb +21 -0
  29. data/lib/ree/contracts/arg_contracts/eq.rb +28 -0
  30. data/lib/ree/contracts/arg_contracts/exactly.rb +28 -0
  31. data/lib/ree/contracts/arg_contracts/hash_of.rb +59 -0
  32. data/lib/ree/contracts/arg_contracts/ksplat.rb +141 -0
  33. data/lib/ree/contracts/arg_contracts/kwargs.rb +22 -0
  34. data/lib/ree/contracts/arg_contracts/nilor.rb +16 -0
  35. data/lib/ree/contracts/arg_contracts/none.rb +15 -0
  36. data/lib/ree/contracts/arg_contracts/optblock.rb +11 -0
  37. data/lib/ree/contracts/arg_contracts/or.rb +30 -0
  38. data/lib/ree/contracts/arg_contracts/range_of.rb +51 -0
  39. data/lib/ree/contracts/arg_contracts/set_of.rb +54 -0
  40. data/lib/ree/contracts/arg_contracts/splat.rb +297 -0
  41. data/lib/ree/contracts/arg_contracts/splat_of.rb +64 -0
  42. data/lib/ree/contracts/arg_contracts/squarable.rb +11 -0
  43. data/lib/ree/contracts/arg_contracts/subclass_of.rb +28 -0
  44. data/lib/ree/contracts/arg_contracts.rb +29 -0
  45. data/lib/ree/contracts/called_args_validator.rb +291 -0
  46. data/lib/ree/contracts/contract_definition.rb +142 -0
  47. data/lib/ree/contracts/contractable.rb +34 -0
  48. data/lib/ree/contracts/core.rb +17 -0
  49. data/lib/ree/contracts/engine.rb +71 -0
  50. data/lib/ree/contracts/engine_proxy.rb +13 -0
  51. data/lib/ree/contracts/errors/bad_contract_error.rb +4 -0
  52. data/lib/ree/contracts/errors/contract_error.rb +4 -0
  53. data/lib/ree/contracts/errors/error.rb +4 -0
  54. data/lib/ree/contracts/errors/return_contract_error.rb +4 -0
  55. data/lib/ree/contracts/method_decorator.rb +158 -0
  56. data/lib/ree/contracts/truncatable.rb +9 -0
  57. data/lib/ree/contracts/utils.rb +9 -0
  58. data/lib/ree/contracts/validators/array_validator.rb +51 -0
  59. data/lib/ree/contracts/validators/base_validator.rb +27 -0
  60. data/lib/ree/contracts/validators/class_validator.rb +17 -0
  61. data/lib/ree/contracts/validators/default_validator.rb +20 -0
  62. data/lib/ree/contracts/validators/hash_validator.rb +100 -0
  63. data/lib/ree/contracts/validators/proc_validator.rb +17 -0
  64. data/lib/ree/contracts/validators/range_validator.rb +17 -0
  65. data/lib/ree/contracts/validators/regexp_validator.rb +17 -0
  66. data/lib/ree/contracts/validators/valid_validator.rb +28 -0
  67. data/lib/ree/contracts/validators.rb +42 -0
  68. data/lib/ree/contracts.rb +45 -0
  69. data/lib/ree/core/link_validator.rb +42 -0
  70. data/lib/ree/core/object.rb +132 -0
  71. data/lib/ree/core/object_error.rb +9 -0
  72. data/lib/ree/core/object_link.rb +21 -0
  73. data/lib/ree/core/object_schema.rb +47 -0
  74. data/lib/ree/core/object_schema_builder.rb +110 -0
  75. data/lib/ree/core/package.rb +177 -0
  76. data/lib/ree/core/package_dep.rb +9 -0
  77. data/lib/ree/core/package_env_var.rb +12 -0
  78. data/lib/ree/core/package_loader.rb +95 -0
  79. data/lib/ree/core/package_schema.rb +27 -0
  80. data/lib/ree/core/package_schema_builder.rb +53 -0
  81. data/lib/ree/core/package_schema_loader.rb +170 -0
  82. data/lib/ree/core/packages_detector.rb +43 -0
  83. data/lib/ree/core/packages_schema.rb +19 -0
  84. data/lib/ree/core/packages_schema_builder.rb +50 -0
  85. data/lib/ree/core/packages_schema_loader.rb +95 -0
  86. data/lib/ree/core/packages_schema_locator.rb +27 -0
  87. data/lib/ree/core/packages_store.rb +32 -0
  88. data/lib/ree/core/path_helper.rb +104 -0
  89. data/lib/ree/dsl/build_package_dsl.rb +155 -0
  90. data/lib/ree/dsl/domain_error.rb +4 -0
  91. data/lib/ree/dsl/error_builder.rb +39 -0
  92. data/lib/ree/dsl/error_dsl.rb +27 -0
  93. data/lib/ree/dsl/import_dsl.rb +106 -0
  94. data/lib/ree/dsl/link_import_builder.rb +66 -0
  95. data/lib/ree/dsl/object_dsl.rb +319 -0
  96. data/lib/ree/dsl/object_hooks.rb +6 -0
  97. data/lib/ree/dsl/package_require.rb +44 -0
  98. data/lib/ree/error.rb +11 -0
  99. data/lib/ree/facades/packages_facade.rb +197 -0
  100. data/lib/ree/fn_dsl.rb +24 -0
  101. data/lib/ree/gen/init.rb +64 -0
  102. data/lib/ree/gen/package.rb +56 -0
  103. data/lib/ree/gen.rb +8 -0
  104. data/lib/ree/handlers/template_handler.rb +118 -0
  105. data/lib/ree/link_dsl.rb +175 -0
  106. data/lib/ree/object_compiler.rb +149 -0
  107. data/lib/ree/package_dsl.rb +34 -0
  108. data/lib/ree/rspec_link_dsl.rb +19 -0
  109. data/lib/ree/spec_runner/command_generator.rb +49 -0
  110. data/lib/ree/spec_runner/command_params.rb +9 -0
  111. data/lib/ree/spec_runner/runner.rb +200 -0
  112. data/lib/ree/spec_runner/spec_filename_matcher.rb +27 -0
  113. data/lib/ree/spec_runner/view.rb +30 -0
  114. data/lib/ree/spec_runner.rb +11 -0
  115. data/lib/ree/templates/init/.gitignore +1 -0
  116. data/lib/ree/templates/init/.irbrc +13 -0
  117. data/lib/ree/templates/init/.rspec +3 -0
  118. data/lib/ree/templates/init/.ruby-version +1 -0
  119. data/lib/ree/templates/init/Gemfile +7 -0
  120. data/lib/ree/templates/init/Packages.schema.json +1 -0
  121. data/lib/ree/templates/init/bin/console +5 -0
  122. data/lib/ree/templates/init/readme.md +2 -0
  123. data/lib/ree/templates/init/ree.setup.rb +21 -0
  124. data/lib/ree/templates/init/spec.init.rb +7 -0
  125. data/lib/ree/templates/package/.gitignore +0 -0
  126. data/lib/ree/templates/package/.rspec +2 -0
  127. data/lib/ree/templates/package/<%=package_subdir_name%>/<%=package_name%>/.gitkeep +0 -0
  128. data/lib/ree/templates/package/<%=package_subdir_name%>/<%=package_name%>.rb +15 -0
  129. data/lib/ree/templates/package/Package.schema.json +0 -0
  130. data/lib/ree/templates/package/bin/console +5 -0
  131. data/lib/ree/templates/package/spec/package_schema_spec.rb +14 -0
  132. data/lib/ree/templates/package/spec/spec_helper.rb +3 -0
  133. data/lib/ree/templates/template_detector.rb +35 -0
  134. data/lib/ree/templates/template_renderer.rb +55 -0
  135. data/lib/ree/utils/render_utils.rb +20 -0
  136. data/lib/ree/utils/string_utils.rb +29 -0
  137. data/lib/ree/version.rb +5 -0
  138. data/lib/ree.rb +279 -0
  139. data/sig/ree.rbs +4 -0
  140. 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
@@ -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,8 @@
1
+ # frozen_string_literal = true
2
+
3
+ module Ree
4
+ module Gen
5
+ autoload :Init, 'ree/gen/init'
6
+ autoload :Package, 'ree/gen/package'
7
+ end
8
+ end
@@ -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
@@ -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