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,39 @@
1
+ # frozen_string_literal = true
2
+
3
+ class Ree::ErrorBuilder
4
+ def initialize(packages_facade)
5
+ @packages_facade = packages_facade
6
+ end
7
+
8
+ def build(object, code, &proc)
9
+ result = Ree::ErrorDsl.new.execute(object.klass, &proc)
10
+
11
+ if result.is_a?(Ree::DomainError)
12
+ object.klass.send(:remove_const, result.name) rescue nil
13
+ result = Ree::ErrorDsl.new.execute(object.klass, &proc)
14
+ end
15
+
16
+ if !result.is_a?(Ree::ErrorDsl::ClassConstant)
17
+ raise Ree::Error.new("invalid def_error usage", :invalid_dsl_usage)
18
+ end
19
+
20
+ object.klass.send(:remove_const, result.name) rescue nil
21
+
22
+ object.klass.class_eval <<-ruby_eval, __FILE__, __LINE__ + 1
23
+ class #{result.name} < Ree::DomainError
24
+ attr_reader :code, :extra_code, :error_code, :package_name, :object_name
25
+
26
+ def initialize(msg = nil, extra_code = nil)
27
+ @code = #{code.inspect}
28
+ @extra_code = extra_code
29
+ @error_code = :#{Ree::StringUtils.underscore(result.name)}
30
+ @package_name = :#{object.package_name}
31
+ @object_name = :#{object.name}
32
+ super(msg || #{result.message.inspect})
33
+ end
34
+ end
35
+ ruby_eval
36
+
37
+ result.name
38
+ end
39
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal = true
2
+
3
+ class Ree::ErrorDsl
4
+ def execute(klass, &proc)
5
+ self.class.instance_exec(&proc)
6
+ rescue NameError => e
7
+ proc
8
+ .binding
9
+ .eval("#{e.name} = Ree::ErrorDsl::ClassConstant.new('#{e.name}')")
10
+
11
+ retry
12
+ end
13
+
14
+ class ClassConstant
15
+ attr_reader :name, :message
16
+
17
+ def initialize(name)
18
+ @name = name
19
+ @message = nil
20
+ end
21
+
22
+ def [](msg)
23
+ @message = msg
24
+ self
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal = true
2
+
3
+ class Ree::ImportDsl
4
+ def execute(klass, proc)
5
+ self.class.instance_exec(&proc)
6
+ rescue Ree::ImportDsl::UnlinkConstError => e
7
+ const_removed = remove_const(klass, e.const)
8
+
9
+ retry if const_removed
10
+ rescue NoMethodError => e
11
+ if e.name == :&
12
+ const_removed = remove_const(klass, e.receiver)
13
+
14
+ if const_removed
15
+ retry
16
+ else
17
+ raise Ree::Error.new("'#{e.receiver}' already linked or defined in '#{klass}'", :invalid_dsl_usage)
18
+ end
19
+ else
20
+ raise e
21
+ end
22
+ rescue NameError => e
23
+ proc
24
+ .binding
25
+ .eval("#{e.name} = Ree::ImportDsl::ClassConstant.new('#{e.name}')")
26
+
27
+ retry
28
+ end
29
+
30
+ class UnlinkConstError < StandardError
31
+ attr_reader :const
32
+
33
+ def initialize(const)
34
+ @const = const
35
+ end
36
+ end
37
+
38
+ class ClassConstant
39
+ attr_reader :name, :constants
40
+
41
+ def initialize(name)
42
+ @name = name
43
+ @as = nil
44
+ @constants = []
45
+ end
46
+
47
+ def &(obj)
48
+ if !obj.is_a?(ClassConstant)
49
+ raise Ree::ImportDsl::UnlinkConstError.new(obj)
50
+ end
51
+
52
+ new_obj = if obj.is_a?(Class)
53
+ ClassConstant.new(obj.to_s.split("::").last)
54
+ else
55
+ obj
56
+ end
57
+
58
+ return self if @constants.detect { |_| _.name == new_obj.name }
59
+ @constants.push(new_obj)
60
+
61
+ self
62
+ end
63
+
64
+ def get_as
65
+ @as
66
+ end
67
+
68
+ def as(obj)
69
+ if !obj.is_a?(ClassConstant)
70
+ raise Ree::ImportDsl::UnlinkConstError.new(obj)
71
+ end
72
+
73
+ @as = if obj.is_a?(Class)
74
+ ClassConstant.new(obj.to_s.split("::").last)
75
+ else
76
+ obj
77
+ end
78
+
79
+ self
80
+ end
81
+ end
82
+
83
+ private
84
+
85
+ def remove_const(klass, constant)
86
+ const_removed = false
87
+
88
+ klass.constants.each do |const_sym|
89
+ const = klass.const_get(const_sym)
90
+
91
+ if constant.is_a?(Class) || constant.is_a?(Module)
92
+ if (const.is_a?(Class) || const.is_a?(Module)) && const.name == constant.name
93
+ klass.send(:remove_const, const_sym)
94
+ const_removed = true
95
+ break
96
+ end
97
+ elsif const == constant
98
+ klass.send(:remove_const, const_sym)
99
+ const_removed = true
100
+ break
101
+ end
102
+ end
103
+
104
+ const_removed
105
+ end
106
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal = true
2
+
3
+ class Ree::LinkImportBuilder
4
+ def initialize(packages_facade)
5
+ @packages_facade = packages_facade
6
+ end
7
+
8
+ # @param [Class] klass Object class
9
+ # @param [Symbol] package_name
10
+ # @param [Symbol] object_name
11
+ # @param [Proc] proc
12
+ # @return [ArrayOf[String]] List of names of imported constants
13
+ def build(klass, package_name, object_name, proc)
14
+ result = Ree::ImportDsl.new.execute(klass, proc)
15
+
16
+ @packages_facade.load_package_object(package_name, object_name)
17
+
18
+ package = @packages_facade.get_package(package_name)
19
+ object = package.get_object(object_name)
20
+ const_list = [result] + result.constants
21
+
22
+ const_list.each do |const_obj|
23
+ if object.klass.const_defined?(const_obj.name)
24
+ set_const(klass, object.klass.const_get(const_obj.name), const_obj)
25
+ elsif package.module.const_defined?(const_obj.name)
26
+ set_const(klass, package.module.const_get(const_obj.name), const_obj)
27
+ else
28
+ raise Ree::Error.new("'#{const_obj.name}' is not found in :#{object.name}")
29
+ end
30
+ end
31
+
32
+ const_list.map(&:name)
33
+ end
34
+
35
+ # @param [Class] klass Object class
36
+ # @param [Class] source_const Source class
37
+ # @param [Proc] proc
38
+ # @return [ArrayOf[String]] List of names of imported constants
39
+ def build_for_const(klass, source_const, proc)
40
+ result = Ree::ImportDsl.new.execute(klass, proc)
41
+ mod_const = Object.const_get(source_const.name.split("::").first)
42
+ const_list = [result] + result.constants
43
+
44
+ const_list.each do |const_obj|
45
+ if source_const.const_defined?(const_obj.name)
46
+ set_const(klass, source_const.const_get(const_obj.name), const_obj)
47
+ elsif mod_const.const_defined?(const_obj.name)
48
+ set_const(klass, mod_const.const_get(const_obj.name), const_obj)
49
+ else
50
+ raise Ree::Error.new("'#{const_obj.name}' is not found in '#{source_const}'")
51
+ end
52
+ end
53
+ end
54
+
55
+ private
56
+
57
+ def set_const(target_klass, ref_class, const_obj)
58
+ if const_obj.get_as
59
+ target_klass.send(:remove_const, const_obj.get_as.name) rescue nil
60
+ target_klass.const_set(const_obj.get_as.name, ref_class)
61
+ else
62
+ target_klass.send(:remove_const, const_obj.name) rescue nil
63
+ target_klass.const_set(const_obj.name, ref_class)
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,319 @@
1
+ # frozen_string_literal = true
2
+
3
+ require 'pathname'
4
+
5
+ class Ree::ObjectDsl
6
+ include Ree::Args
7
+
8
+ attr_reader :package, :object
9
+
10
+ # @param [Ree::PackagesFacade] packages_facade
11
+ # @param [Class] klass
12
+ # @param [Symbol] name
13
+ # @param [Nilor[String]] abs_path
14
+ # @param [Symbol] mount_as
15
+ def initialize(packages_facade, klass, name, mount_as)
16
+ @packages_facade = packages_facade
17
+
18
+ @object = register_object(
19
+ klass, name, mount_as,
20
+ )
21
+
22
+ @package = @packages_facade.get_loaded_package(@object.package_name)
23
+
24
+ if @package.default_links
25
+ instance_exec(&@package.default_links)
26
+ end
27
+ end
28
+
29
+ # Proxy method for link_object & link_file
30
+ def link(*args, **kwargs)
31
+ if args.first.is_a?(Symbol)
32
+ link_object(*args, **kwargs)
33
+ elsif args.first.is_a?(String)
34
+ link_file(args[0], args[1])
35
+ else
36
+ raise_error("Invalid link DSL usage. Args should be Hash or String")
37
+ end
38
+ end
39
+
40
+ # @param [Symbol] object_name
41
+ # @param [Nilor[Symbol]] as
42
+ # @param [Nilor[Symbol]] from
43
+ # @param [Nilor[ArrayOf[Symbol]]] methods
44
+ # @param [Nilor[Proc]] import
45
+ def link_object(object_name, as: nil, from: nil, methods: nil, import: nil)
46
+ check_arg(object_name, :object_name, Symbol)
47
+ check_arg(as, :as, Symbol) if as
48
+ check_arg(from, :from, Symbol) if from
49
+ check_arg(import, :import, Proc) if import
50
+ check_arg_array_of(methods, :methods, Symbol) if methods
51
+
52
+ link_package_name = from.nil? ? @object.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)
57
+
58
+ const_list = if import
59
+ Ree::LinkImportBuilder
60
+ .new(@packages_facade)
61
+ .build(
62
+ @object.klass,
63
+ link_package_name,
64
+ link_object_name,
65
+ import
66
+ )
67
+ end
68
+
69
+ link = Ree::ObjectLink.new(
70
+ link_object_name, link_package_name, link_as
71
+ )
72
+
73
+ if const_list
74
+ link.set_constants(const_list)
75
+ @object.add_const_list(const_list)
76
+ end
77
+
78
+ @object.links.push(link)
79
+ Ree.logger.debug(" #{@object.klass}.link(:#{link_object_name}, from: #{link_package_name}, as: #{link_as})")
80
+
81
+ @packages_facade.load_package_object(link_package_name, link_object_name)
82
+ end
83
+
84
+ # @param [Symbol] method_name
85
+ def factory(method_name)
86
+ if !@object.object?
87
+ raise_error("Factory methods only available for beans")
88
+ end
89
+
90
+ if @object.after_init
91
+ raise_error("Factory beans do not support after_init DSL")
92
+ end
93
+
94
+ check_arg(method_name, :method_name, Symbol)
95
+ @object.set_factory(method_name)
96
+ end
97
+
98
+ def singleton
99
+ @object.set_as_singleton
100
+ end
101
+
102
+ # @param [Symbol] method_name
103
+ def after_init(method_name)
104
+ if @object.factory?
105
+ raise_error("Factory beans do not support after_init DSL")
106
+ end
107
+
108
+ check_arg(method_name, :method_name, Symbol)
109
+ @object.set_after_init(method_name)
110
+ end
111
+
112
+ # @param [Bool] flag
113
+ def freeze(flag)
114
+ check_bool(flag, :flag)
115
+ @object.set_freeze(flag)
116
+ end
117
+
118
+ # @param [Nilor[Symbol]] code Global error code
119
+ # @param [Proc] proc Error DSL proc
120
+ def def_error(code = nil, &proc)
121
+ check_arg(code, :code, Symbol) if code
122
+
123
+ if !block_given?
124
+ raise_error("def_error should accept block with error class definition")
125
+ end
126
+
127
+ if code && !Ree.error_types.include?(code)
128
+ raise_error("Invalid error code :#{code}. Did you forget to setup it with Ree.add_error_types(*args)?")
129
+ end
130
+
131
+ class_name = begin
132
+ Ree::ErrorBuilder
133
+ .new(@packages_facade)
134
+ .build(
135
+ @object,
136
+ code,
137
+ &proc
138
+ )
139
+ rescue Ree::Error
140
+ raise_error("invalid def_error usage. Valid examples: def_error { InvalidDomainErr } or def_error(:validation) { EmailTakenErr['email taken'] }")
141
+ end
142
+
143
+ @object.add_const_list([class_name])
144
+
145
+ @object.errors.push(
146
+ Ree::ObjectError.new(
147
+ class_name
148
+ )
149
+ )
150
+ end
151
+
152
+ # @param [String] path Relative package file path ('accounts/entities/user')
153
+ # @param [Proc] proc Import constants proc
154
+ def link_file(path, import_proc = nil)
155
+ check_arg(import_proc, :import, Proc) if import_proc
156
+
157
+ list = path.split('/')
158
+ package_name = File.basename(list[0], ".*").to_sym
159
+
160
+ check_package_dependency_added(package_name)
161
+
162
+ @packages_facade.load_package_entry(package_name)
163
+ package = @packages_facade.get_package(package_name)
164
+
165
+ file_path = File.join(
166
+ Ree::PathHelper.abs_package_dir(package),
167
+ Ree::PACKAGE, path
168
+ )
169
+
170
+ if !File.exists?(file_path)
171
+ file_path = "#{file_path}.rb"
172
+
173
+ if !File.exists?(file_path)
174
+ raise_error("Unable to link '#{path}'. File not found #{file_path}")
175
+ end
176
+ end
177
+
178
+ @packages_facade.load_file(file_path, package.name)
179
+
180
+ const_list = path.split('/').map { |_| Ree::StringUtils.camelize(_) }
181
+ const_short = [const_list[0], const_list.last].join("::")
182
+ const_long = const_list.join("::")
183
+
184
+ file_const = if Object.const_defined?(const_long)
185
+ Object.const_get(const_long)
186
+ elsif Object.const_defined?(const_short)
187
+ Object.const_get(const_short)
188
+ else
189
+ raise_error("Unable to link '#{path}'. #{const_long} or #{const_short} was not defined in #{file_path}")
190
+ end
191
+
192
+ const_list = if import_proc
193
+ Ree::LinkImportBuilder
194
+ .new(@packages_facade)
195
+ .build_for_const(
196
+ @object.klass,
197
+ file_const,
198
+ import_proc
199
+ )
200
+ end
201
+
202
+ if const_list
203
+ @object.add_const_list(const_list.map(&:name))
204
+ end
205
+
206
+ file_const
207
+ end
208
+
209
+ private
210
+
211
+ MOUNT_AS = [:fn, :object]
212
+
213
+ def register_object(object_name, klass, mount_as)
214
+ check_arg(object_name, :object_name, Symbol)
215
+ check_arg(klass, :klass, Class)
216
+ check_arg(mount_as, :mount_as, Symbol)
217
+
218
+ if klass.name.nil?
219
+ raise Ree::Error.new("Anonymous classes are not supported", :invalid_dsl_usage)
220
+ end
221
+
222
+ path = Object.const_source_location(klass.name)[0].split(':').first
223
+
224
+ if !MOUNT_AS.include?(mount_as)
225
+ raise Ree::Error.new("Mount as should be one of #{MOUNT_AS.inspect}", :invalid_dsl_usage)
226
+ end
227
+
228
+ object_name_from_path = if File.exists?(path) && !Ree.irb_mode?
229
+ File.basename(path, ".*").to_sym
230
+ end
231
+
232
+ if !Ree.irb_mode? && object_name_from_path && object_name != object_name_from_path
233
+ raise Ree::Error.new("Object name does not correspond to a file name (#{object_name}, #{object_name_from_path}.rb). Fix object name or rename object file", :invalid_dsl_usage)
234
+ end
235
+
236
+ class_name = klass.to_s
237
+ list = class_name.split('::')
238
+
239
+ if list.size > 3
240
+ raise Ree::Error.new("Objects should be declared inside parent modules or inside there submodules", :invalid_dsl_usage)
241
+ end
242
+
243
+ package_name = if list.size == 1
244
+ raise Ree::Error.new("Object declarations should only appear for classes declared inside modules", :invalid_dsl_usage)
245
+ else
246
+ Ree::StringUtils.underscore(list[0]).to_sym
247
+ end
248
+
249
+ auto_object_name = Ree::StringUtils.underscore(list.last).to_sym
250
+
251
+ if auto_object_name != object_name
252
+ raise Ree::Error.new(":#{object_name} does not correspond to class name #{list.last}. Change object name to '#{auto_object_name}' or change name of the class", :invalid_dsl_usage)
253
+ end
254
+
255
+ package = @packages_facade.get_package(package_name)
256
+ object = package.get_object(object_name)
257
+
258
+ object_rpath = if !Ree.irb_mode?
259
+ Pathname
260
+ .new(path)
261
+ .relative_path_from(Pathname.new(Ree::PathHelper.project_root_dir(package)))
262
+ .to_s
263
+ end
264
+
265
+ schema_rpath = if !Ree.irb_mode?
266
+ Ree::PathHelper.object_schema_rpath(object_rpath)
267
+ end
268
+
269
+ if !object
270
+ object = Ree::Object.new(
271
+ object_name,
272
+ schema_rpath,
273
+ object_rpath,
274
+ )
275
+ else
276
+ object
277
+ .set_rpath(object_rpath)
278
+ .set_schema_rpath(schema_rpath)
279
+ end
280
+
281
+ object.reset
282
+
283
+ object
284
+ .set_mount_as(mount_as)
285
+ .set_class(klass)
286
+ .set_package(package.name)
287
+ .set_rpath(object_rpath)
288
+
289
+ package.set_object(object)
290
+ object.set_loaded
291
+
292
+ object
293
+ end
294
+
295
+ private
296
+
297
+ def check_package_dependency_added(package_name)
298
+ @packages_facade.load_package_entry(package_name)
299
+ return if package_name == @package.name
300
+
301
+ dep_package = @package.deps.detect do |d|
302
+ d.name == package_name
303
+ end
304
+
305
+ if dep_package.nil?
306
+ raise_error("Package :#{package_name} is not added as dependency for :#{@object.package_name} package\npackage path: #{File.join(Ree.root_dir, @package.entry_rpath)}")
307
+ end
308
+ end
309
+
310
+ def raise_error(text, code = :invalid_dsl_usage)
311
+ msg = <<~DOC
312
+ object: :#{@object.name}
313
+ path: #{Ree::PathHelper.abs_object_path(@object)}
314
+ error: #{text}
315
+ DOC
316
+
317
+ raise Ree::Error.new(msg, code)
318
+ end
319
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Object
4
+ include Ree::Contracts::Core
5
+ include Ree::Contracts::ArgContracts
6
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ def package_require(path)
4
+ list = path.split('/')
5
+ package_name = list.shift.to_sym
6
+ packages_facade = Ree.container.packages_facade
7
+ package = packages_facade.get_package(package_name)
8
+
9
+ return false if package.dir.nil?
10
+
11
+ path = File.join(
12
+ Ree::PathHelper.abs_package_module_dir(package), list.join('/')
13
+ )
14
+
15
+ if !File.exists?(path)
16
+ path = path + '.rb'
17
+ end
18
+
19
+ if !File.exists?(path)
20
+ raise Ree::Error.new("file not found: #{path}")
21
+ end
22
+
23
+ Ree.logger.debug("package_require(#{path})")
24
+ packages_facade.load_package_entry(package_name)
25
+ packages_facade.load_file(path, package_name)
26
+ end
27
+
28
+ def package_file_exists?(path)
29
+ list = path.split('/')
30
+ package_name = list.shift.to_sym
31
+ packages_facade = Ree.container.packages_facade
32
+ package = packages_facade.get_package(package_name)
33
+
34
+ return false if package.dir.nil?
35
+
36
+ path = File.join(
37
+ Ree::PathHelper.abs_package_module_dir(package), list.join('/')
38
+ )
39
+
40
+ return true if File.exists?(path)
41
+
42
+ path = path + '.rb'
43
+ File.exists?(path)
44
+ end
data/lib/ree/error.rb ADDED
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal = true
2
+
3
+ class Ree::Error < StandardError
4
+ attr_reader :code, :type
5
+
6
+ def initialize(message, code = nil, type = nil)
7
+ super(message)
8
+ @type = type
9
+ @code = code
10
+ end
11
+ end