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,132 @@
1
+ # frozen_string_literal = true
2
+
3
+ class Ree::Object
4
+ attr_reader :name, :rpath, :schema_rpath, :package_name, :klass,
5
+ :package_name, :factory, :after_init,
6
+ :class_name, :links, :mount_as, :freeze,
7
+ :errors, :linked_const_list, :compiled_frozen,
8
+ :singleton
9
+
10
+ # @param [Symbol] name Object name
11
+ # @param [String] schema_rpath Object schema path relative to project root dir
12
+ # @param [String] rpath Object source file path relative to project root dir
13
+ def initialize(name, schema_rpath, rpath)
14
+ @name = name
15
+ @schema_rpath = schema_rpath
16
+ @rpath = rpath
17
+ @links = []
18
+ @errors = []
19
+ @loaded = false
20
+ @freeze = true
21
+ @compiled = false
22
+ @singleton = false
23
+ @compiled_frozen = @freeze
24
+ @linked_const_list = []
25
+ end
26
+
27
+ def reset
28
+ @compiled = false
29
+ @singleton = false
30
+ @loaded = false
31
+ @factory = nil
32
+ @after_init = nil
33
+ @freeze = true
34
+ @links = []
35
+ @errors = []
36
+ @linked_const_list = []
37
+ end
38
+
39
+ # @param [ArrayOf[String]] list List of imported constants, modules and classes
40
+ # @return [ArrayOf[String]] All imported constants
41
+ def add_const_list(list)
42
+ @linked_const_list += list
43
+ @linked_const_list.uniq
44
+ end
45
+
46
+ # @param [Bool]
47
+ def set_as_compiled(frozen)
48
+ @compiled = true
49
+ @compiled_frozen = frozen
50
+ end
51
+
52
+ def set_as_not_compiled
53
+ @compiled = false
54
+ @compiled_frozen = @freeze
55
+ end
56
+
57
+ def compiled?
58
+ @compiled
59
+ end
60
+
61
+ def factory?
62
+ !!@factory
63
+ end
64
+
65
+ def after_init?
66
+ !!@after_init
67
+ end
68
+
69
+ def set_loaded
70
+ @loaded = true
71
+ end
72
+
73
+ def loaded?
74
+ @loaded
75
+ end
76
+
77
+ def freeze?
78
+ @freeze
79
+ end
80
+
81
+ # @param [Symbol] val Object mount as type (:fn or :bean)
82
+ def set_mount_as(val)
83
+ @mount_as = val; self
84
+ end
85
+
86
+ # @param [Bool]
87
+ def set_freeze(val)
88
+ @freeze = val; self
89
+ end
90
+
91
+ def set_as_singleton
92
+ @singleton = true; self
93
+ end
94
+
95
+ def object?
96
+ @mount_as == :object
97
+ end
98
+
99
+ def fn?
100
+ @mount_as == :fn
101
+ end
102
+
103
+ # @param [String] rpath Object source file path relative to project root dir
104
+ def set_rpath(val)
105
+ @rpath = val; self
106
+ end
107
+
108
+ # @param [String] schema_rpath Object schema path relative to project root dir
109
+ def set_schema_rpath(val)
110
+ @schema_rpath = val; self
111
+ end
112
+
113
+ # @param [Class] Object class
114
+ def set_class(klass)
115
+ @klass = klass; @class_name = klass.to_s; self
116
+ end
117
+
118
+ # @param [Symbol] Package name
119
+ def set_package(val)
120
+ @package_name = val; self
121
+ end
122
+
123
+ # @param [Symbol] Factory method name
124
+ def set_factory(val)
125
+ @factory = val; self
126
+ end
127
+
128
+ # @param [Symbol] After init method name
129
+ def set_after_init(val)
130
+ @after_init = val; self
131
+ end
132
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal = true
2
+
3
+ class Ree::ObjectError
4
+ attr_reader :class_name
5
+
6
+ def initialize(class_name)
7
+ @class_name = class_name
8
+ end
9
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal = true
2
+
3
+ class Ree::ObjectLink
4
+ attr_reader :object_name, :package_name, :as, :constants
5
+
6
+ # @param [Symbol] object_name Linked object name
7
+ # @param [Symbol] package_name Linked object package
8
+ # @param [Symbol] as Linked object alias name
9
+ def initialize(object_name, package_name, as)
10
+ @object_name = object_name
11
+ @package_name = package_name
12
+ @as = as
13
+ @constants = []
14
+ end
15
+
16
+ # @param [ArrayOf[String]]
17
+ # @return [ArrayOf[String]]
18
+ def set_constants(const_list)
19
+ @constants = const_list
20
+ end
21
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal = true
2
+
3
+ module Ree::ObjectSchema
4
+ SCHEMA_TYPE = 'schema_type'
5
+ REE_VERSION = 'ree_version'
6
+ NAME = 'name'
7
+ OBJECT = 'object'
8
+ LINKS = 'links'
9
+ CONTEXT = 'context'
10
+ PATH = 'path'
11
+ METHODS = 'methods'
12
+ CLASS = 'class'
13
+ PACKAGE_NAME = 'package_name'
14
+ MOUNT_AS = 'mount_as'
15
+ FACTORY = 'factory'
16
+ ERRORS = 'errors'
17
+
18
+ module Links
19
+ NAME = 'name'
20
+ PACKAGE_NAME = 'package_name'
21
+ TARGET = 'target'
22
+ AS = 'as'
23
+ IMPORTS = 'imports'
24
+
25
+ module Imports
26
+ CONST = 'const'
27
+ AS = 'as'
28
+ end
29
+ end
30
+
31
+ module Methods
32
+ ARGS = 'args'
33
+ METHOD = 'method'
34
+ RETURN = 'return'
35
+ THROWS = 'throws'
36
+ DOC = 'doc'
37
+
38
+ module Args
39
+ ARG = 'arg'
40
+ TYPE = 'type'
41
+ end
42
+ end
43
+
44
+ module Errors
45
+ CODE = 'code'
46
+ end
47
+ end
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal = true
2
+
3
+ class Ree::ObjectSchemaBuilder
4
+ Schema = Ree::ObjectSchema
5
+
6
+ # @param [Ree::Object] object
7
+ # @param [String] - path to object.schema.json file (ex. /project/bc/accounts/schemas/accounts/accounts_cfg.schema.json)
8
+ # @return [String]
9
+ def call(object, schema_path)
10
+ Ree.logger.debug("generating object schema for '#{object.name}' package")
11
+
12
+ if !File.exists?(schema_path)
13
+ only_dir_path = schema_path.split('/')[0..-2]
14
+ FileUtils.mkdir_p(File.join(only_dir_path))
15
+ end
16
+
17
+ if !object.loaded?
18
+ raise Ree::Error.new("object `#{object.name}` from package `#{object.package_name}` is not loaded", :invalid_schema)
19
+ end
20
+
21
+ data = {
22
+ Schema::SCHEMA_TYPE => Schema::OBJECT,
23
+ Schema::REE_VERSION => Ree::VERSION,
24
+ Schema::NAME => object.name,
25
+ Schema::PATH => object.rpath,
26
+ Schema::MOUNT_AS => object.mount_as,
27
+ Schema::CLASS => object.klass.name,
28
+ Schema::FACTORY => object.factory,
29
+ Schema::METHODS => map_object_methods(object),
30
+ Schema::LINKS => object.links.sort_by(&:object_name).map { |link|
31
+ {
32
+ Schema::Links::TARGET => link.object_name,
33
+ Schema::Links::PACKAGE_NAME => link.package_name,
34
+ Schema::Links::AS => link.as,
35
+ Schema::Links::IMPORTS => link.constants
36
+ }
37
+ }
38
+ }
39
+
40
+ json = JSON.pretty_generate(data)
41
+
42
+ File.write(schema_path, json, mode: 'w')
43
+ json
44
+ end
45
+
46
+ private
47
+
48
+ Arg = Ree::Contracts::CalledArgsValidator::Arg
49
+
50
+ def map_object_methods(object)
51
+ if !object.fn?
52
+ return []
53
+ end
54
+
55
+ klass = object.klass
56
+
57
+ method_decorator = Ree::Contracts.get_method_decorator(
58
+ klass, :call, scope: :instance
59
+ )
60
+
61
+ begin
62
+ if method_decorator.nil?
63
+ parameters = klass.instance_method(:call).parameters
64
+
65
+ args = parameters.inject({}) do |res, param|
66
+ res[param.last] = Arg.new(
67
+ param.last, param.first, nil, nil
68
+ )
69
+
70
+ res
71
+ end
72
+ else
73
+ parameters = method_decorator.args.params
74
+ args = method_decorator.args.get_args
75
+ end
76
+ rescue NameError
77
+ raise Ree::Error.new("method call is not defined for #{klass}")
78
+ end
79
+
80
+ arg_list = parameters.map do |param|
81
+ arg = args[param.last]
82
+ validator = arg.validator
83
+ arg_type = arg.type
84
+
85
+ type = if validator
86
+ validator.to_s
87
+ else
88
+ if arg_type == :block
89
+ "Block"
90
+ else
91
+ "Any"
92
+ end
93
+ end
94
+
95
+ {
96
+ Schema::Methods::Args::ARG => arg.name,
97
+ Schema::Methods::Args::TYPE => type
98
+ }
99
+ end
100
+
101
+ [
102
+ {
103
+ Schema::Methods::DOC => method_decorator&.doc || "",
104
+ Schema::Methods::THROWS => method_decorator&.errors&.map { _1.name } || [],
105
+ Schema::Methods::RETURN => method_decorator&.contract_definition&.return_contract || "Any",
106
+ Schema::Methods::ARGS => arg_list
107
+ }
108
+ ]
109
+ end
110
+ end
@@ -0,0 +1,177 @@
1
+ # frozen_string_literal = true
2
+
3
+ require 'pathname'
4
+
5
+ class Ree::Package
6
+ attr_reader :ree_version, :name, :schema_rpath, :entry_rpath,
7
+ :module, :tags, :preload, :default_links, :gem_name
8
+
9
+ def initialize(ree_version, name, entry_rpath, schema_rpath, gem_name = nil)
10
+ @ree_version = ree_version
11
+ @name = name
12
+ @schema_rpath = schema_rpath
13
+ @entry_rpath = entry_rpath
14
+ @objects_store = {}
15
+ @deps_store = {}
16
+ @env_vars_store = {}
17
+ @entry_loaded = false
18
+ @schema_loaded = false
19
+ @loaded = false
20
+ @tags = []
21
+ @preload = {}
22
+ @preloaded = false
23
+ @gem_name = gem_name
24
+ end
25
+
26
+ def set_default_links(&block)
27
+ @default_links = block; self
28
+ end
29
+
30
+ # @param [Bool] val
31
+ def set_preloaded(val)
32
+ @preloaded = val; self
33
+ end
34
+
35
+ def preloaded?
36
+ @preloaded
37
+ end
38
+
39
+ # @param [String] val
40
+ def set_ree_version(val)
41
+ @ree_version = val; self
42
+ end
43
+
44
+ # @param [String] val
45
+ def set_entry_rpath(val)
46
+ @entry_rpath = val; self
47
+ end
48
+
49
+ # @param [ArrayOf[String]] list
50
+ def set_tags(list)
51
+ @tags = (@tags + list).map(&:to_s).uniq; self
52
+ end
53
+
54
+ # @param [String] val
55
+ def set_schema_rpath(val)
56
+ @schema_rpath = val; self
57
+ end
58
+
59
+ def reset
60
+ @entry_loaded = false
61
+ @schema_loaded = false
62
+ @loaded = false
63
+ @deps_store = {}
64
+ @env_vars_store = {}
65
+ @preload = {}
66
+ end
67
+
68
+ def set_preload(val)
69
+ @preload = val; self
70
+ end
71
+
72
+ def loaded?
73
+ @loaded
74
+ end
75
+
76
+ def set_loaded
77
+ @loaded = true
78
+ end
79
+
80
+ def set_entry_loaded
81
+ @entry_loaded = true
82
+ end
83
+
84
+ def set_schema_loaded
85
+ @schema_loaded = true
86
+ end
87
+
88
+ def entry_loaded?
89
+ @entry_loaded
90
+ end
91
+
92
+ def schema_loaded?
93
+ @schema_loaded
94
+ end
95
+
96
+ def dir
97
+ @dir ||= @schema_rpath ? Pathname.new(@schema_rpath).dirname.to_s : nil
98
+ end
99
+
100
+ def gem?
101
+ !!@gem_name
102
+ end
103
+
104
+ # @param [Module] mod
105
+ def set_module(mod)
106
+ @module = mod; self
107
+ end
108
+
109
+ # @list [ArrayOf[Ree::PackageDepsSchema]]
110
+ def set_deps(list)
111
+ list.each do |item|
112
+ @deps_store[item.name] = item
113
+ end
114
+ end
115
+
116
+ def deps
117
+ @deps_store.values
118
+ end
119
+
120
+ # @param [Ree::PackageDep] dep
121
+ def set_dep(dep)
122
+ old = @deps_store[dep.name]
123
+ @deps_store[dep.name] = dep
124
+ old
125
+ end
126
+
127
+ # @param [Symbol] name
128
+ def get_dep(name)
129
+ @deps_store[name]
130
+ end
131
+
132
+ # @param [ArrayOf[Ree::PackageEnvVar]] list
133
+ def set_env_vars(list)
134
+ list.each do |item|
135
+ @env_vars_store[item.name] = item
136
+ end
137
+ end
138
+
139
+ def env_vars
140
+ @env_vars_store.values
141
+ end
142
+
143
+ # @param [Ree::PackageEnvVar] var
144
+ def set_env_var(var)
145
+ old = @env_vars_store[var.name]
146
+ @env_vars_store[var.name] = var
147
+ old
148
+ end
149
+
150
+ # @param [String] name
151
+ def get_env_var(name)
152
+ @env_vars_store[name]
153
+ end
154
+
155
+ # @param [Ree::Object] object
156
+ # @return [Nilor[Ree::Object]] Previous object version
157
+ def set_object(object)
158
+ if object.package_name != @name
159
+ raise Ree::Error.new("package should only include objects from the same package")
160
+ end
161
+
162
+ existing = @objects_store[object.name]
163
+ return existing if existing
164
+
165
+ @objects_store[object.name] = object
166
+ end
167
+
168
+ # @param [Symbol] name
169
+ # @return [Nilor[Ree::Object]]
170
+ def get_object(name)
171
+ @objects_store[name]
172
+ end
173
+
174
+ def objects
175
+ @objects_store.values.flatten
176
+ end
177
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal = true
2
+
3
+ class Ree::PackageDep
4
+ attr_reader :name
5
+
6
+ def initialize(name)
7
+ @name = name
8
+ end
9
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal = true
2
+
3
+ class Ree::PackageEnvVar
4
+ attr_reader :name, :doc
5
+
6
+ # @param [String] name Env var name
7
+ # @param [Nilor[String]] Env var description
8
+ def initialize(name, doc)
9
+ @name = name
10
+ @doc = doc
11
+ end
12
+ end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal = true
2
+
3
+ require 'set'
4
+ require 'pathname'
5
+
6
+ class Ree::PackageLoader
7
+ def initialize(packages_store)
8
+ @packages_store = packages_store
9
+ @loaded_paths = {}
10
+ @loaded_packages = {}
11
+ end
12
+
13
+ def reset
14
+ @loaded_paths = {}
15
+ end
16
+
17
+ # @param [Symbol] name Package name
18
+ def call(name)
19
+ return @loaded_packages[name] if @loaded_packages.has_key?(name)
20
+
21
+ Ree.logger.debug("full_package_load(:#{name})")
22
+ recursively_load_package(name, Hash.new(false))
23
+ @loaded_packages[name]
24
+ end
25
+
26
+ def load_file(path, package_name)
27
+ @loaded_paths[package_name] ||= {}
28
+ return if @loaded_paths[package_name][path]
29
+ @loaded_paths[package_name][path] = true
30
+
31
+ Ree.logger.debug("load_file(:#{package_name}, '#{path}')")
32
+ Kernel.require(path)
33
+ end
34
+
35
+ private
36
+
37
+ def recursively_load_package(name, loaded_packages)
38
+ @loaded_packages[name] = true
39
+ package = @packages_store.get(name)
40
+
41
+ if package.dir.nil?
42
+ package.set_schema_loaded
43
+ return package
44
+ end
45
+
46
+ if !package
47
+ raise Ree::Error.new(
48
+ "Package :#{name} was not found. Did you mistype the name? Run `ree gen.packages_json` to update Packages.schema.json",
49
+ :invalid_package_name
50
+ )
51
+ end
52
+
53
+ not_loaded = Set.new(
54
+ [name, package.deps.map(&:name)]
55
+ .uniq
56
+ .select { |pn| !loaded_packages[pn] }
57
+ )
58
+
59
+ if not_loaded.include?(name)
60
+ load_file(
61
+ Ree::PathHelper.abs_package_entry_path(package), name
62
+ )
63
+
64
+ Dir[File.join(Ree::PathHelper.abs_package_module_dir(package), '**/*.rb')].each do |path|
65
+ load_file(path, name)
66
+ end
67
+
68
+ loaded_packages[name] = true
69
+ end
70
+
71
+ if !ENV.has_key?('REE_SKIP_ENV_VARS_CHECK')
72
+ package.env_vars.each do |env_var|
73
+ if !ENV.has_key?(env_var.name)
74
+ msg = <<~DOC
75
+ package: :#{package.name}
76
+ path: #{File.join(Ree::PathHelper.project_root_dir(package), package.entry_rpath)}
77
+ error: Package :#{name} requires env var '#{env_var.name}' to be set
78
+ DOC
79
+
80
+ raise Ree::Error.new(msg, :env_var_not_set)
81
+ end
82
+ end
83
+ end
84
+
85
+ package.deps.each do |dep|
86
+ if !loaded_packages[dep.name]
87
+ recursively_load_package(dep.name, loaded_packages)
88
+ end
89
+ end
90
+
91
+ package.set_schema_loaded
92
+
93
+ @loaded_packages[name] = package
94
+ end
95
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal = true
2
+
3
+ module Ree::PackageSchema
4
+ SCHEMA_TYPE = 'schema_type'
5
+ REE_VERSION = 'ree_version'
6
+ NAME = 'name'
7
+ PACKAGE = 'package'
8
+ ENTRY_PATH = 'entry_path'
9
+ OBJECTS = 'objects'
10
+ ENV_VARS = 'env_vars'
11
+ DEPENDS_ON = 'depends_on'
12
+ TAGS = 'tags'
13
+
14
+ module Objects
15
+ NAME = 'name'
16
+ SCHEMA = 'schema'
17
+ end
18
+
19
+ module DependsOn
20
+ NAME = 'name'
21
+ end
22
+
23
+ module EnvVars
24
+ NAME = 'name'
25
+ DOC = 'doc'
26
+ end
27
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal = true
2
+
3
+ require 'pathname'
4
+ require 'json'
5
+
6
+ class Ree::PackageSchemaBuilder
7
+ Schema = Ree::PackageSchema
8
+
9
+ # @param [Ree::Package] package
10
+ # @param [String] - abs_path Absolute path to Package.schema.json file (ex. /project/bc/accounts/Package.schema.json)
11
+ # @return [nil]
12
+ def call(package, abs_path)
13
+ Ree.logger.debug("generating package schema for '#{package.name}' package")
14
+
15
+ if !File.exists?(abs_path)
16
+ raise Ree::Error.new("File does not exist: #{abs_path}", :invalid_path)
17
+ end
18
+
19
+ if !package.loaded?
20
+ raise Ree::Error.new("package schema should be loaded", :invalid_schema)
21
+ end
22
+
23
+ data = {
24
+ Schema::SCHEMA_TYPE => Schema::PACKAGE,
25
+ Schema::REE_VERSION => Ree::VERSION,
26
+ Schema::NAME => package.name,
27
+ Schema::ENTRY_PATH => package.entry_rpath,
28
+ Schema::TAGS => package.tags,
29
+ Schema::DEPENDS_ON => package.deps.sort_by(&:name).map { |dep|
30
+ {
31
+ Schema::DependsOn::NAME => dep.name,
32
+ }
33
+ },
34
+ Schema::ENV_VARS => package.env_vars.sort_by(&:name).map { |var|
35
+ {
36
+ Schema::EnvVars::NAME => var.name,
37
+ Schema::EnvVars::DOC => var.doc,
38
+ }
39
+ },
40
+ Schema::OBJECTS => package.objects.select { !_1.rpath.nil? }.sort_by(&:name).map { |object|
41
+ {
42
+ Schema::Objects::NAME => object.name,
43
+ Schema::Objects::SCHEMA => object.schema_rpath,
44
+ }
45
+ }
46
+ }
47
+
48
+ json = JSON.pretty_generate(data)
49
+
50
+ File.write(abs_path, json, mode: 'w')
51
+ nil
52
+ end
53
+ end