packs-specification 0.0.8 → 0.0.10

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6fc4e79e4786eb16e964a3431d06fa071f48c7f4ae361c7d9747a50bd1634e76
4
- data.tar.gz: 772de64f7ea2558241e0a3c234e3ce7660750fe37c49d09935c11260734bf282
3
+ metadata.gz: a95a4c598305baa6990d07093e98b49f55c3289c80d384e7beb558bcafde63ca
4
+ data.tar.gz: b6f2537d04165bee29925da1d29d9613da1b0219227ab397973efc65a1e64259
5
5
  SHA512:
6
- metadata.gz: 29bf27fd2b72214370cb3513944f8b383bcc06aed7ff82fe92a1954aba1fd22111e6566d3c7158e43b8ca022723214e2e9176af3c7de72200b7cf8835e56c8fe
7
- data.tar.gz: 48a3d36d1d9a587ca9c0ccf3fe984c5baf24cc3cc704e4f544deddc19a00661e6545d8361148aeaf3c1a68fe05f7fa3af4b3a75c3be3f4f815c90c0fb88f4dba
6
+ metadata.gz: 4cc9f93bad4fd2fe25d1d5ac32c4895d6dfcdf64de56b0f6aec31b29129a9a9f902e62f8c5820972efee538e0ecf6f45efd976f2b2bf8dcff577f2369c62d68f
7
+ data.tar.gz: 0cb00ea631d12ee411150657650da2864303e24c92ce3747471e9328a4018478d490db599f94e3b69e9b9727259e6b4fe5e2ca51e80e881c8e8ec3384b328e00
data/README.md CHANGED
@@ -1,25 +1,26 @@
1
1
  # packs-specification
2
+ This is a low-dependency gem that allows your production environment to query simple information about [`packs`](https://github.com/rubyatscale/packs).
2
3
 
3
- Welcome to `packs-specification`! `packs` are a simple ruby specification for an extensible packaging system to help modularize Ruby applications.
4
4
 
5
- A `pack` (short for `package`) is a folder of Ruby code with a `package.yml` at the root that is intended to represent a well-modularized domain, and the rest of the [rubyatscale](https://github.com/rubyatscale) ecosystem is intended to help make the boundaries between a pack and any other more clear.
5
+ ## Usage
6
+ ```ruby
6
7
 
7
- # Configuration
8
- By default, this library will look for `packs` in the folder `packs/*/package.yml` (as well as nested packs at `packs/*/*/package.yml`). To change where `packs` are located, create a `packs.yml` file:
9
- ```
10
- pack_paths:
11
- - "{packs,utilities,deprecated}/*" # packs with multiple roots!
12
- - "{packs,utilities,deprecated}/*/*" # nested packs!
13
- - gems/* # gems can be packs too!
14
- ```
8
+ require 'packs-specification'
15
9
 
16
- Here are some example integrations with `packs`:
17
- - [`packs-rails`](https://github.com/rubyatscale/packs-rails) can be used to integrate `packs` into your `rails` application
18
- - [`rubocop-packs`](https://github.com/rubyatscale/rubocop-packs) contains cops to improve boundaries around `packs`
19
- - [`packwerk`](https://github.com/Shopify/packwerk) and [`packwerk-extensions`](https://github.com/rubyatscale/packwerk-extensions) help you describe and constrain your package graph in terms of dependencies between packs and pack public API
20
- - [`code_ownership`](https://github.com/rubyatscale/code_ownership) gives your application the capability to determine the owner of a pack
21
- - [`use_packs`](https://github.com/rubyatscale/use_packs) gives a CLI, `bin/packs`, that makes it easy to create new packs, move files between packs, and more.
22
- - [`pack_stats`](https://github.com/rubyatscale/pack_stats) makes it easy to send metrics about pack adoption and modularization to your favorite metrics provider, such as DataDog (which has built-in support).
10
+ # Getting all packs
11
+ # Example use: adding pack paths to a list of fixture paths
12
+ # Returns a T::Array[Packs::Pack]
13
+ Packs.all
23
14
 
24
- # How is a pack different from a gem?
25
- A ruby [`gem`](https://guides.rubygems.org/what-is-a-gem/) is the Ruby community solution for packaging and distributing Ruby code. A gem is a great place to start new projects, and a great end state for code that's been extracted from an existing codebase. `packs` are intended to help gradually modularize an application that has some conceptual boundaries, but is not yet ready to be factored into gems.
15
+ # Getting the pack for a specific file
16
+ # Example use: Associating a file with an owner via a pack owner
17
+ # Returns a T.nilable(Packs::Pack)
18
+ Packs.for_file('/path/to/file.rb')
19
+ Packs.for_file(Pathname.new('/path/to/file.rb')) # also works
20
+
21
+ # Getting a pack with a specific name
22
+ # Example use: Special casing certain behavior for a specific pack
23
+ # Example use: Development tools that operate on user inputted pack names
24
+ # Returns a T.nilable(Packs::Pack)
25
+ Packs.find('packs/my_pack')
26
+ ```
data/lib/packs/pack.rb CHANGED
@@ -13,7 +13,7 @@ module Packs
13
13
  def self.from(package_yml_absolute_path)
14
14
  package_loaded_yml = YAML.load_file(package_yml_absolute_path)
15
15
  path = package_yml_absolute_path.dirname
16
- relative_path = path.relative_path_from(Private.root)
16
+ relative_path = path.relative_path_from(Specification.root)
17
17
  package_name = relative_path.cleanpath.to_s
18
18
 
19
19
  Pack.new(
@@ -36,7 +36,7 @@ module Packs
36
36
  end
37
37
 
38
38
  sig { returns(T::Boolean) }
39
- def is_gem?
39
+ def is_gem? # rubocop:disable Naming/PredicateName
40
40
  @is_gem ||= T.let(relative_path.glob('*.gemspec').any?, T.nilable(T::Boolean))
41
41
  end
42
42
 
@@ -5,17 +5,23 @@ RSpec.configure do |config|
5
5
 
6
6
  config.before do
7
7
  # We bust_cache always because each test may write its own packs
8
- Packs.bust_cache!
8
+ Packs::Specification.bust_cache!
9
9
  end
10
10
 
11
11
  # Eventually, we could make this opt-in via metadata so someone can use this support without affecting all their tests.
12
12
  config.around do |example|
13
- prefix = [File.basename($0), Process.pid].join('-') # rubocop:disable Style/SpecialGlobalVars
14
- tmpdir = Dir.mktmpdir(prefix)
15
- Dir.chdir(tmpdir) do
13
+ if example.metadata[:skip_chdir_to_tmpdir]
16
14
  example.run
15
+ else
16
+ begin
17
+ prefix = [File.basename($0), Process.pid].join('-') # rubocop:disable Style/SpecialGlobalVars
18
+ tmpdir = Dir.mktmpdir(prefix)
19
+ Dir.chdir(tmpdir) do
20
+ example.run
21
+ end
22
+ ensure
23
+ FileUtils.rm_rf(tmpdir)
24
+ end
17
25
  end
18
- ensure
19
- FileUtils.rm_rf(tmpdir)
20
26
  end
21
27
  end
@@ -1,7 +1,7 @@
1
1
  # typed: strict
2
2
 
3
3
  module Packs
4
- module Private
4
+ module Specification
5
5
  class Configuration < T::Struct
6
6
  extend T::Sig
7
7
  CONFIGURATION_PATHNAME = T.let(Pathname.new('packs.yml'), Pathname)
@@ -0,0 +1,73 @@
1
+ # typed: strict
2
+
3
+ require 'packs/specification/configuration'
4
+
5
+ module Packs
6
+ module Specification
7
+ extend T::Sig
8
+
9
+ class << self
10
+ extend T::Sig
11
+
12
+ sig { returns(Pathname) }
13
+ def root
14
+ Pathname.pwd
15
+ end
16
+
17
+ sig { returns(Configuration) }
18
+ def config
19
+ @config = T.let(@config, T.nilable(Configuration))
20
+ @config ||= Configuration.fetch
21
+ end
22
+
23
+ sig { void }
24
+ def bust_cache!
25
+ @packs_by_name = nil
26
+ @for_file = nil
27
+ @config = nil
28
+ end
29
+
30
+ sig { returns(T::Array[Pack]) }
31
+ def all
32
+ packs_by_name.values
33
+ end
34
+
35
+ sig { params(name: String).returns(T.nilable(Pack)) }
36
+ def find(name)
37
+ packs_by_name[name]
38
+ end
39
+
40
+ sig { params(file_path: T.any(Pathname, String)).returns(T.nilable(Pack)) }
41
+ def for_file(file_path)
42
+ path_string = file_path.to_s
43
+ @for_file = T.let(@for_file, T.nilable(T::Hash[String, T.nilable(Pack)]))
44
+ @for_file ||= {}
45
+ @for_file[path_string] ||= all.find { |package| path_string.start_with?("#{package.name}/") || path_string == package.name }
46
+ end
47
+
48
+ private
49
+
50
+ sig { returns(T::Hash[String, Pack]) }
51
+ def packs_by_name
52
+ @packs_by_name = T.let(@packs_by_name, T.nilable(T::Hash[String, Pack]))
53
+ @packs_by_name ||= begin
54
+ all_packs = package_glob_patterns.map do |path|
55
+ Pack.from(path)
56
+ end
57
+
58
+ # We want to match more specific paths first so for_file works correctly.
59
+ sorted_packages = all_packs.sort_by { |package| -package.name.length }
60
+ sorted_packages.to_h { |p| [p.name, p] }
61
+ end
62
+ end
63
+
64
+ sig { returns(T::Array[Pathname]) }
65
+ def package_glob_patterns
66
+ absolute_root = Specification.root
67
+ Specification.config.pack_paths.flat_map do |pack_path|
68
+ Pathname.glob(absolute_root.join(pack_path).join(PACKAGE_FILE))
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -4,8 +4,11 @@ require 'yaml'
4
4
  require 'pathname'
5
5
  require 'sorbet-runtime'
6
6
  require 'packs/pack'
7
- require 'packs/private'
7
+ require 'packs/specification'
8
8
 
9
+ # We let `packs-specification` define some API methods such as all, find, and for_file,
10
+ # because this allows a production environment to require `packs-specification` only and get some simple functionality, without
11
+ # needing to load all of `packs`.
9
12
  module Packs
10
13
  PACKAGE_FILE = T.let('package.yml'.freeze, String)
11
14
 
@@ -14,67 +17,17 @@ module Packs
14
17
 
15
18
  sig { returns(T::Array[Pack]) }
16
19
  def all
17
- packs_by_name.values
20
+ Specification.all
18
21
  end
19
22
 
20
23
  sig { params(name: String).returns(T.nilable(Pack)) }
21
24
  def find(name)
22
- packs_by_name[name]
25
+ Specification.find(name)
23
26
  end
24
27
 
25
28
  sig { params(file_path: T.any(Pathname, String)).returns(T.nilable(Pack)) }
26
29
  def for_file(file_path)
27
- path_string = file_path.to_s
28
- @for_file = T.let(@for_file, T.nilable(T::Hash[String, T.nilable(Pack)]))
29
- @for_file ||= {}
30
- @for_file[path_string] ||= all.find { |package| path_string.start_with?("#{package.name}/") || path_string == package.name }
31
- end
32
-
33
- sig { void }
34
- def bust_cache!
35
- @packs_by_name = nil
36
- @config = nil
37
- @for_file = nil
38
- end
39
-
40
- sig { returns(Private::Configuration) }
41
- def config
42
- @config = T.let(@config, T.nilable(Private::Configuration))
43
- @config ||= Private::Configuration.fetch
44
- end
45
-
46
- sig { params(blk: T.proc.params(arg0: Private::Configuration).void).void }
47
- def configure(&blk)
48
- # If packs.yml is being used, then ignore direct configuration.
49
- # This is only a stop-gap to permit Stimpack users to more easily migrate
50
- # to packs.yml
51
- return if Private::Configuration::CONFIGURATION_PATHNAME.exist?
52
-
53
- yield(config)
54
- end
55
-
56
- private
57
-
58
- sig { returns(T::Hash[String, Pack]) }
59
- def packs_by_name
60
- @packs_by_name = T.let(@packs_by_name, T.nilable(T::Hash[String, Pack]))
61
- @packs_by_name ||= begin
62
- all_packs = package_glob_patterns.map do |path|
63
- Pack.from(path)
64
- end
65
-
66
- # We want to match more specific paths first so for_file works correctly.
67
- sorted_packages = all_packs.sort_by { |package| -package.name.length }
68
- sorted_packages.to_h { |p| [p.name, p] }
69
- end
70
- end
71
-
72
- sig { returns(T::Array[Pathname]) }
73
- def package_glob_patterns
74
- absolute_root = Private.root
75
- config.pack_paths.flat_map do |pack_path|
76
- Pathname.glob(absolute_root.join(pack_path).join(PACKAGE_FILE))
77
- end
30
+ Specification.for_file(file_path)
78
31
  end
79
32
  end
80
33
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: packs-specification
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.0.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gusto Engineers
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-08-09 00:00:00.000000000 Z
11
+ date: 2023-08-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sorbet-runtime
@@ -118,10 +118,10 @@ files:
118
118
  - README.md
119
119
  - lib/packs-specification.rb
120
120
  - lib/packs/pack.rb
121
- - lib/packs/private.rb
122
- - lib/packs/private/configuration.rb
123
121
  - lib/packs/rspec/fixture_helper.rb
124
122
  - lib/packs/rspec/support.rb
123
+ - lib/packs/specification.rb
124
+ - lib/packs/specification/configuration.rb
125
125
  homepage: https://github.com/rubyatscale/packs-specification
126
126
  licenses:
127
127
  - MIT
data/lib/packs/private.rb DELETED
@@ -1,16 +0,0 @@
1
- # typed: strict
2
-
3
- require 'packs/private/configuration'
4
-
5
- module Packs
6
- module Private
7
- extend T::Sig
8
-
9
- sig { returns(Pathname) }
10
- def self.root
11
- Pathname.pwd
12
- end
13
- end
14
-
15
- private_constant :Private
16
- end