packs-specification 0.0.8 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
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