mono_repo_deps 0.1.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.ruby-version +1 -0
  4. data/.standard.yml +3 -0
  5. data/CHANGELOG.md +5 -0
  6. data/CODE_OF_CONDUCT.md +84 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +193 -0
  9. data/Rakefile +8 -0
  10. data/example/Gemfile +1 -0
  11. data/example/Gemfile.lock +51 -0
  12. data/example/MonoRepoConfig.rb +16 -0
  13. data/example/bounded_contexts/cart/cart_app/Package.rb +11 -0
  14. data/example/bounded_contexts/cart/cart_app/bin/console +11 -0
  15. data/example/bounded_contexts/cart/cart_app/package/cart_app.rb +2 -0
  16. data/example/bounded_contexts/cart/cart_core/Package.rb +12 -0
  17. data/example/bounded_contexts/cart/cart_core/bin/console +9 -0
  18. data/example/bounded_contexts/cart/cart_core/package/cart_core.rb +2 -0
  19. data/example/bounded_contexts/cart/cart_datasets/Package.rb +10 -0
  20. data/example/bounded_contexts/cart/cart_datasets/bin/console +9 -0
  21. data/example/bounded_contexts/cart/cart_datasets/package/cart_datasets.rb +2 -0
  22. data/example/bounded_contexts/orders/orders_app/Package.rb +12 -0
  23. data/example/bounded_contexts/orders/orders_app/bin/console +9 -0
  24. data/example/bounded_contexts/orders/orders_app/package/orders_app.rb +2 -0
  25. data/example/bounded_contexts/orders/orders_core/Package.rb +13 -0
  26. data/example/bounded_contexts/orders/orders_core/bin/console +9 -0
  27. data/example/bounded_contexts/orders/orders_core/package/orders_core.rb +2 -0
  28. data/example/bounded_contexts/orders/orders_datasets/Package.rb +11 -0
  29. data/example/bounded_contexts/orders/orders_datasets/bin/console +9 -0
  30. data/example/bounded_contexts/orders/orders_datasets/package/orders_datasets.rb +2 -0
  31. data/example/bounded_contexts/orders/orders_query_api/Package.rb +13 -0
  32. data/example/bounded_contexts/orders/orders_query_api/bin/console +9 -0
  33. data/example/bounded_contexts/orders/orders_query_api/package/cart_query_api.rb +2 -0
  34. data/example/bounded_contexts/orders/paypal_client/Package.rb +9 -0
  35. data/example/bounded_contexts/orders/paypal_client/bin/console +9 -0
  36. data/example/bounded_contexts/orders/paypal_client/package/paypal_client.rb +2 -0
  37. data/example/bounded_contexts/shared/db_connection/Package.rb +10 -0
  38. data/example/bounded_contexts/shared/db_connection/bin/console +9 -0
  39. data/example/bounded_contexts/shared/db_connection/package/db_connection.rb +2 -0
  40. data/example/bounded_contexts/shared/test_utils/Package.rb +9 -0
  41. data/example/bounded_contexts/shared/test_utils/bin/console +9 -0
  42. data/example/bounded_contexts/shared/test_utils/package/test_utils.rb +2 -0
  43. data/example/bounded_contexts/storefront/storefront_app/Package.rb +11 -0
  44. data/example/bounded_contexts/storefront/storefront_app/bin/console +9 -0
  45. data/example/bounded_contexts/storefront/storefront_app/package/storefront_app.rb +2 -0
  46. data/example/bounded_contexts/storefront/storefront_core/Package.rb +11 -0
  47. data/example/bounded_contexts/storefront/storefront_core/bin/console +9 -0
  48. data/example/bounded_contexts/storefront/storefront_core/package/storefront_core.rb +2 -0
  49. data/example/bounded_contexts/storefront/storefront_datasets/Package.rb +11 -0
  50. data/example/bounded_contexts/storefront/storefront_datasets/bin/console +9 -0
  51. data/example/bounded_contexts/storefront/storefront_datasets/package/storefront_datasets.rb +2 -0
  52. data/example/configs/cart_app/default.yml +4 -0
  53. data/example/configs/cart_app/test.yml +3 -0
  54. data/example/configs/orders_app/default.yml +4 -0
  55. data/example/configs/orders_app/test.yml +2 -0
  56. data/exe/mono_repo_deps +15 -0
  57. data/exe/mrd +15 -0
  58. data/lib/mono_repo_deps/config/loader.rb +74 -0
  59. data/lib/mono_repo_deps/config/manager.rb +20 -0
  60. data/lib/mono_repo_deps/config.rb +23 -0
  61. data/lib/mono_repo_deps/loaders/base.rb +63 -0
  62. data/lib/mono_repo_deps/loaders/zeitwerk.rb +77 -0
  63. data/lib/mono_repo_deps/package/builder.rb +27 -0
  64. data/lib/mono_repo_deps/package/dependency_bypasser.rb +44 -0
  65. data/lib/mono_repo_deps/package/factory.rb +100 -0
  66. data/lib/mono_repo_deps/package/find_root.rb +33 -0
  67. data/lib/mono_repo_deps/package/indexer.rb +30 -0
  68. data/lib/mono_repo_deps/package/initializer.rb +38 -0
  69. data/lib/mono_repo_deps/package/list.rb +10 -0
  70. data/lib/mono_repo_deps/package/repo.rb +55 -0
  71. data/lib/mono_repo_deps/package.rb +48 -0
  72. data/lib/mono_repo_deps/project/builder.rb +20 -0
  73. data/lib/mono_repo_deps/project/factory.rb +115 -0
  74. data/lib/mono_repo_deps/project/find_root.rb +31 -0
  75. data/lib/mono_repo_deps/project/initializer.rb +26 -0
  76. data/lib/mono_repo_deps/project.rb +43 -0
  77. data/lib/mono_repo_deps/task/manager.rb +55 -0
  78. data/lib/mono_repo_deps/task.rb +21 -0
  79. data/lib/mono_repo_deps/version.rb +5 -0
  80. data/lib/mono_repo_deps.rb +138 -0
  81. data/sig/mono_repo_deps.rbs +4 -0
  82. metadata +314 -0
@@ -0,0 +1,9 @@
1
+ package do
2
+ name 'test_utils'
3
+ end
4
+
5
+ dependency do
6
+ end
7
+
8
+ dependency :test do
9
+ end
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'mono_repo_deps'
5
+
6
+ MonoRepoDeps.init(__dir__)
7
+
8
+ require 'irb'
9
+ IRB.start
@@ -0,0 +1,2 @@
1
+ module TestUtils
2
+ end
@@ -0,0 +1,11 @@
1
+ package do
2
+ name 'storefront_app'
3
+ end
4
+
5
+ dependency do
6
+ import 'storefront_core'
7
+ end
8
+
9
+ dependency :test do
10
+ import 'test_utils'
11
+ end
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'mono_repo_deps'
5
+
6
+ MonoRepoDeps.init(__dir__)
7
+
8
+ require 'irb'
9
+ IRB.start
@@ -0,0 +1,2 @@
1
+ module StorefrontApp
2
+ end
@@ -0,0 +1,11 @@
1
+ package do
2
+ name 'storefront_core'
3
+ end
4
+
5
+ dependency do
6
+ import 'storefront_datasets'
7
+ end
8
+
9
+ dependency :test do
10
+ import 'test_utils'
11
+ end
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'mono_repo_deps'
5
+
6
+ MonoRepoDeps.init(__dir__)
7
+
8
+ require 'irb'
9
+ IRB.start
@@ -0,0 +1,11 @@
1
+ package do
2
+ name 'storefront_datasets'
3
+ end
4
+
5
+ dependency do
6
+ import 'db_connection'
7
+ end
8
+
9
+ dependency :test do
10
+ import 'test_utils'
11
+ end
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'mono_repo_deps'
5
+
6
+ MonoRepoDeps.init(__dir__)
7
+
8
+ require 'irb'
9
+ IRB.start
@@ -0,0 +1,4 @@
1
+ cart_app:
2
+ host: 'some_host'
3
+ port: 1234
4
+ db: 'some_db'
@@ -0,0 +1,3 @@
1
+ cart_app:
2
+ host: 'some_test_host'
3
+ db: 'some_test_db'
@@ -0,0 +1,4 @@
1
+ orders_app:
2
+ host: 'some_host'
3
+ port: 1234
4
+ db: 'some_db'
@@ -0,0 +1,2 @@
1
+ orders_app:
2
+ host: 'some_test_host'
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "mono_repo_deps"
6
+ require "thor"
7
+
8
+ class MonoRepoDepsCli < Thor
9
+ desc "mono_repo cd PACKAGE", "go to PACKAGE"
10
+ def cd(package)
11
+ puts "cd #{MonoRepoDeps.packages(File.expand_path(".")).find(package.to_sym).root_path}"
12
+ end
13
+ end
14
+
15
+ MonoRepoDepsCli.start(ARGV)
data/exe/mrd ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "mono_repo_deps"
6
+ require "thor"
7
+
8
+ class MonoRepoDepsCli < Thor
9
+ desc "mono_repo cd PACKAGE", "go to PACKAGE"
10
+ def path(package)
11
+ puts "cd #{MonoRepoDeps.packages(File.expand_path(".")).find!(package.to_sym).root_path}"
12
+ end
13
+ end
14
+
15
+ MonoRepoDepsCli.start(ARGV)
@@ -0,0 +1,74 @@
1
+ require 'yaml'
2
+ require 'erb'
3
+ require 'ostruct'
4
+
5
+ class MonoRepoDeps::Config::Loader
6
+ include MonoRepoDeps::Mixins
7
+
8
+ DEFAULT_CONFIG_FILENAME = 'default.yml'
9
+
10
+ sig do
11
+ params(
12
+ config_name: T.any(String, Symbol),
13
+ )
14
+ .returns(MonoRepoDeps::Config)
15
+ end
16
+ def call(config_name)
17
+ config_name = config_name.to_s
18
+ config = MonoRepoDeps::Config.new
19
+
20
+ default_config_filename = File.join(
21
+ MonoRepoDeps.current_project.root_path,
22
+ MonoRepoDeps.current_project.configs_dir,
23
+ config_name,
24
+ DEFAULT_CONFIG_FILENAME
25
+ )
26
+
27
+ unless File.exist?(default_config_filename)
28
+ raise StandardError.new("Config '#{config_name}' was not found. Add it to '#{default_config_filename}'")
29
+ end
30
+
31
+ hash =
32
+ begin
33
+ YAML.load( ERB.new(File.read(default_config_filename)).result )
34
+ rescue => e
35
+ puts ERB.new(File.read(default_config_filename)).result.inspect
36
+ end
37
+
38
+ hash_to_config(
39
+ hash: hash,
40
+ config: config
41
+ )
42
+
43
+ env_config_filename = File.join(
44
+ MonoRepoDeps.current_project.root_path,
45
+ MonoRepoDeps.current_project.configs_dir,
46
+ config_name,
47
+ "#{MonoRepoDeps.current_project.env}.yml"
48
+ )
49
+
50
+ hash_to_config(
51
+ hash: YAML.load( ERB.new(File.read(env_config_filename)).result ),
52
+ config: config
53
+ ) if File.exist?(env_config_filename)
54
+
55
+ config.send(config_name)
56
+ end
57
+
58
+ private
59
+
60
+ def hash_to_config(hash:, config:)
61
+ hash.each do |key, value|
62
+ if value.is_a?(Hash)
63
+ nested_config = config.read_attribute(key)
64
+ if nested_config.nil? || !nested_config.is_a?(MonoRepoDeps::Config)
65
+ nested_config = MonoRepoDeps::Config.new
66
+ end
67
+ hash_to_config(hash: value, config: nested_config)
68
+ config.write_attribute(key, nested_config)
69
+ else
70
+ config.write_attribute(key, value)
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,20 @@
1
+ class MonoRepoDeps::Config::Manager
2
+ include MonoRepoDeps::Mixins
3
+
4
+ Inject = MonoRepoDeps::Deps[
5
+ config_loader: "config.loader"
6
+ ]
7
+
8
+ include Inject
9
+
10
+ sig do
11
+ params(
12
+ method_name: Symbol,
13
+ args: T.anything
14
+ )
15
+ .returns(MonoRepoDeps::Config)
16
+ end
17
+ def method_missing(method_name, *args)
18
+ config_loader.call(method_name)
19
+ end
20
+ end
@@ -0,0 +1,23 @@
1
+ class MonoRepoDeps::Config
2
+ def initialize(attributes = {})
3
+ @attributes = attributes
4
+ end
5
+
6
+ def read_attribute(key)
7
+ @attributes[key.to_s]
8
+ end
9
+
10
+ def write_attribute(key, value)
11
+ @attributes[key.to_s] = value
12
+ end
13
+
14
+ def method_missing(method_name, *_args)
15
+ read_attribute(method_name)
16
+ end
17
+
18
+ def to_h
19
+ @attributes.each_with_object({}) do |(k, v), h|
20
+ h[k] = self.class === v ? v.to_h : v
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,63 @@
1
+ class MonoRepoDeps::Loaders::Base
2
+ include MonoRepoDeps::Mixins
3
+
4
+ class << self
5
+ def registry
6
+ @registry ||= {}
7
+ end
8
+
9
+ def inherited(subclass)
10
+ name = subclass.to_s.split("::").last.downcase.to_sym
11
+
12
+ registry[name] = subclass
13
+ end
14
+ end
15
+
16
+ attr_reader :overwriters, :inflections, :ignore_dirs, :autoload_dirs, :loader, :root_path
17
+
18
+ def initialize(root_path, &block)
19
+ @root_path = root_path
20
+ @overwriters = []
21
+ @inflections = {}
22
+ @ignore_dirs = []
23
+ @autoload_dirs = []
24
+
25
+ instance_exec(&block) if block_given?
26
+ end
27
+
28
+ def push_dir(dir)
29
+ @autoload_dirs.push(dir)
30
+ end
31
+
32
+ def setup
33
+ raise StandardError.new('not implemented')
34
+ end
35
+
36
+ def reload
37
+ raise StandardError.new('not implemented')
38
+ end
39
+
40
+ def eager_load
41
+ raise StandardError.new('not implemented')
42
+ end
43
+
44
+ def check_classes
45
+ raise StandardError.new('not implemented')
46
+ end
47
+
48
+ module SetupDsl
49
+ def inflect(hash)
50
+ @inflections.merge!(hash)
51
+ end
52
+
53
+ def overwrite(proc)
54
+ overwriters.push(proc)
55
+ end
56
+
57
+ def ignore(glob)
58
+ @ignore_dirs.push(glob)
59
+ end
60
+ end
61
+
62
+ include SetupDsl
63
+ end
@@ -0,0 +1,77 @@
1
+ require 'zeitwerk'
2
+ require 'benchmark'
3
+
4
+ class MonoRepoDeps::Loaders::Zeitwerk < MonoRepoDeps::Loaders::Base
5
+ include MonoRepoDeps::Mixins
6
+
7
+ ERROR_MESSAGE_REGEX = /expected file (?<path>[\w\/]+.rb) to define constant (?<klass>[\w:]+)/
8
+
9
+ def initialize(...)
10
+ @loader = Zeitwerk::Loader.new
11
+ @loader.inflector = Class.new(Zeitwerk::Inflector).new
12
+
13
+ super(...)
14
+ end
15
+
16
+ def setup
17
+ apply_rules_for(@loader)
18
+ @loader.setup
19
+ end
20
+
21
+ def eager_load
22
+ time = Benchmark.realtime do
23
+ @loader.eager_load
24
+ end
25
+
26
+ puts "eager_load dependencies in #{'%.2f' % time} seconds"
27
+ end
28
+
29
+ def check_classes
30
+ check_classes_loader = @loader.dup
31
+ check_classes_loader.on_load { |cpath, value, abspath| puts value }
32
+
33
+ errors = []
34
+
35
+ begin
36
+ check_classes_loader.eager_load
37
+ rescue Zeitwerk::NameError => e
38
+ match = e.message.match(ERROR_MESSAGE_REGEX)
39
+
40
+ raise e if match.nil?
41
+
42
+ # TODO: use logger
43
+ errors << "#{match[:path]} => #{match[:klass]}"
44
+ check_classes_loader.ignore(match[:path])
45
+ retry
46
+ end
47
+
48
+ puts errors
49
+ raise StandardError.new("loader fails with #{errors.count} errors") if errors.any?
50
+
51
+ nil
52
+ end
53
+
54
+ def apply_rules_for(entity)
55
+ @autoload_dirs.uniq.each { entity.push_dir(_1) }
56
+ @ignore_dirs.uniq
57
+ .map { File.join(MonoRepoDeps.current_project.root_path, _1) }
58
+ .each { entity.ignore( _1 ) }
59
+
60
+ entity.inflector.inflect(@inflections)
61
+
62
+ result_overwriter = ->(kname) { @overwriters.each { |o| kname = o.call(kname) }; kname }
63
+ entity.inflector.define_singleton_method(:camelize) do |basename, abspath|
64
+ result_overwriter.call( super(basename, abspath) )
65
+ end
66
+ end
67
+
68
+ def ignore(glob)
69
+ super(glob)
70
+
71
+ # TODO: if loader.setup is true => push dir directly to the @loader
72
+ @ignore_dirs
73
+ .uniq
74
+ .map { File.join(root_path, _1) }
75
+ .each { @loader.ignore( _1 ) }
76
+ end
77
+ end
@@ -0,0 +1,27 @@
1
+ class MonoRepoDeps::Package::Builder
2
+ include MonoRepoDeps::Mixins
3
+
4
+ Inject = MonoRepoDeps::Deps[
5
+ "package.find_root",
6
+ "package.factory"
7
+ ]
8
+
9
+ include Inject
10
+
11
+ sig do
12
+ params(
13
+ package_path: String,
14
+ project_root: String,
15
+ package_dirname: String
16
+ )
17
+ .returns(MonoRepoDeps::Package)
18
+ end
19
+ def call(package_path, project_root, package_dirname)
20
+ package_root_path = find_root.call(package_path, project_root)
21
+ package_file_path = "#{package_root_path}/#{MonoRepoDeps::PACKAGE_FILENAME}"
22
+
23
+ package_init_proc = proc { instance_eval(File.read(package_file_path)) }
24
+
25
+ package = factory.call(package_root_path, package_dirname, init_proc: package_init_proc)
26
+ end
27
+ end
@@ -0,0 +1,44 @@
1
+ class MonoRepoDeps::Package::DependencyBypasser
2
+ include MonoRepoDeps::Mixins
3
+
4
+ Inject = MonoRepoDeps::Deps[
5
+ packages_repo: "package.repo"
6
+ ]
7
+
8
+ include Inject
9
+
10
+ sig do
11
+ params(
12
+ package_name: Symbol,
13
+ env: Symbol,
14
+ only: T.nilable(T::Array[Symbol]),
15
+ skip: T.nilable(T::Array[Symbol]),
16
+ imported: T::Array[Symbol],
17
+ packages_order: T::Array[Symbol],
18
+ )
19
+ .returns(T::Array[Symbol])
20
+ end
21
+ def call(package_name:, env:, only: nil, skip: nil, imported: [], packages_order: [])
22
+ package = packages_repo.find!(package_name)
23
+
24
+ return [] if imported.include?(package_name)
25
+ imported.push(package.name)
26
+
27
+ package_dependencies = package.get_dependencies(env)
28
+ package_dependencies = package_dependencies.select { only.include?(_1.name) } unless only.nil?
29
+ package_dependencies = package_dependencies.reject { skip.include?(_1.name) } unless skip.nil?
30
+
31
+ package_dependencies.each do |dependency_dto|
32
+ self.call(
33
+ package_name: dependency_dto.name,
34
+ skip: dependency_dto.skip,
35
+ only: dependency_dto.only,
36
+ imported: imported,
37
+ packages_order: packages_order,
38
+ env: env
39
+ )
40
+ end
41
+
42
+ packages_order.push(package_name)
43
+ end
44
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+ class MonoRepoDeps::Package::Factory
3
+ include MonoRepoDeps::Mixins
4
+
5
+ sig do
6
+ params(
7
+ package_root: String,
8
+ package_dirname: String,
9
+ init_proc: T.proc.params(args: T.anything).returns(T.anything)
10
+ )
11
+ .returns(MonoRepoDeps::Package)
12
+ end
13
+ def call(package_root, package_dirname, init_proc:)
14
+ @dependencies = Hash.new { |h, k| h[k] = [] }
15
+ @current_env = MonoRepoDeps::Package::DEFAULT_ENV
16
+
17
+ instance_exec(&init_proc)
18
+
19
+ package = MonoRepoDeps::Package.new(
20
+ name: @name,
21
+ root_path: package_root,
22
+ package_dirname: package_dirname,
23
+ dependencies: @dependencies
24
+ ).tap { check_duplicate_dependencies(_1) }
25
+ end
26
+
27
+ private
28
+
29
+ def check_duplicate_dependencies(package)
30
+ package.get_dependency_envs.each do |env|
31
+ already_imported = package
32
+ .get_dependencies(env)
33
+ .map(&:name)
34
+ .group_by{ |e| e }
35
+ .select { |k, v| v.size > 1 }
36
+ .keys
37
+
38
+ if already_imported.any?
39
+ puts "WARNING: duplicated import for following packages #{already_imported.inspect} was already added for package '#{package.name}' for env '#{env}'"
40
+ end
41
+ end
42
+ end
43
+
44
+ sig do
45
+ params(
46
+ env: Symbol,
47
+ block: T.proc.params(args: T.anything).returns(T.anything)
48
+ )
49
+ .void
50
+ end
51
+ def dependency(env = MonoRepoDeps::Package::DEFAULT_ENV, &block)
52
+ @current_env = env
53
+ instance_eval(&block)
54
+ @current_env = MonoRepoDeps::Package::DEFAULT_ENV
55
+
56
+ nil
57
+ end
58
+
59
+ sig do
60
+ params(
61
+ package_name: T.any(Symbol, String),
62
+ skip: T.nilable(T::Array[Symbol]),
63
+ only: T.nilable(T::Array[Symbol]),
64
+ )
65
+ .void
66
+ end
67
+ def import(package_name, skip: nil, only: nil)
68
+ package_name = package_name.to_sym
69
+ skip = skip&.map(&:to_sym)
70
+ only = only&.map(&:to_sym)
71
+
72
+ @dependencies[@current_env] << MonoRepoDeps::Package::DependencyDto.new(name: package_name, skip: skip, only: only)
73
+
74
+ nil
75
+ end
76
+
77
+ sig do
78
+ params(
79
+ block: T.proc.params(args: T.anything).returns(T.anything)
80
+ )
81
+ .void
82
+ end
83
+ def package(&block)
84
+ instance_exec(&block)
85
+
86
+ nil
87
+ end
88
+
89
+ sig do
90
+ params(
91
+ value: T.any(String, Symbol)
92
+ )
93
+ .void
94
+ end
95
+ def name(value)
96
+ @name = value.to_sym
97
+
98
+ nil
99
+ end
100
+ end
@@ -0,0 +1,33 @@
1
+ class MonoRepoDeps::Package::FindRoot
2
+ include MonoRepoDeps::Mixins
3
+
4
+ SYSTEM_ROOT = '/'
5
+
6
+ sig do
7
+ params(
8
+ dir: String,
9
+ project_root: T.nilable(String),
10
+ )
11
+ .returns(String)
12
+ end
13
+ def call(dir, project_root)
14
+ init_dir = dir = File.expand_path(dir)
15
+ project_root = File.expand_path(project_root || SYSTEM_ROOT)
16
+
17
+ unless File.exist?(init_dir)
18
+ raise StandardError.new("path '#{init_dir}' does not exist")
19
+ end
20
+
21
+ loop do
22
+ project_file_path = File.expand_path(File.join(dir, MonoRepoDeps::PACKAGE_FILENAME))
23
+
24
+ if File.exist?(project_file_path)
25
+ return dir
26
+ elsif dir == project_root
27
+ raise StandardError.new("Package.rb for path '#{init_dir}' not found")
28
+ else
29
+ dir = File.expand_path("../", dir)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,30 @@
1
+ class MonoRepoDeps::Package::Indexer
2
+ include MonoRepoDeps::Mixins
3
+
4
+ Inject = MonoRepoDeps::Deps[
5
+ "package.builder",
6
+ ]
7
+
8
+ include Inject
9
+
10
+ sig do
11
+ params(
12
+ packages_lookup_subdir: String,
13
+ project_root: String,
14
+ package_dirname: String
15
+ )
16
+ .returns(T::Array[MonoRepoDeps::Package])
17
+ end
18
+ def call(packages_lookup_subdir, project_root, package_dirname)
19
+ packages_path = File.join(
20
+ project_root,
21
+ packages_lookup_subdir,
22
+ "**",
23
+ MonoRepoDeps::PACKAGE_FILENAME
24
+ )
25
+
26
+ Dir[packages_path].map do |package_file_path|
27
+ builder.call(package_file_path, project_root, package_dirname)
28
+ end
29
+ end
30
+ end