packs 0.0.1 → 0.0.2

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: 156ed7ab94d5a72f12a96cb0437a3c7ec4dfb3299a56c2bdc3414f588f0497ac
4
- data.tar.gz: 6df13268bafbb79c6b03477ff9981a40a83a18a424e44d51ecf0f42d8689e54b
3
+ metadata.gz: 29e18f23de09397b4441c88789b231d1226bd68bea5d0fce16655d0367f93b9b
4
+ data.tar.gz: bfd5b5aefd4de2aa8b126accd52c44a980ca1302a57c49d6faf37a969ca2d1f5
5
5
  SHA512:
6
- metadata.gz: 0a14fd70f566933916a9047daf9b7201679ace0992d21938de3b33e0d21fa64482f120b5784c2a5166e1cc1fe9d1b8f96238b38e7a1f3d8b684e4adf6937a5de
7
- data.tar.gz: a3214873c063d7f26324eccc7d5ddb206296959cbd0f67747e042014c13633f4186d963337c5cbb14541ff8422ff17dc98183a1eb30417d4d921eceb8d3761a1
6
+ metadata.gz: 29a0c8a277e0ae42061219e86ab7371dcd014e3649e3728db0d166f98c30ad430ad04a9d8cec82d862e34e075a12dbaf4ae4b96e4f77e97addfc01881762cf8f
7
+ data.tar.gz: c9dccdac635c403f4a0ec2f305bf9947b7ca2b96ef943ae2088888e3b2a553743f19baae48b0451c574b69abda8de2c71275de6ce6637767640a0e6f431479a2
data/README.md CHANGED
@@ -1 +1,16 @@
1
1
  # packs
2
+
3
+ Welcome to `packs`! `packs` are a simple ruby specification for an extensible packaging system to help modularize Ruby applications.
4
+
5
+ A `pack` (also called `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.
6
+
7
+ Here are some example integrations with `packs`:
8
+ - [`stimpack`](https://github.com/rubyatscale/stimpack) can be used to integrate `packs` into your `rails` application
9
+ - [`rubocop-packs`](https://github.com/rubyatscale/rubocop-packs) contains cops to improve boundaries around `packs`
10
+ - [`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
11
+ - [`code_ownership`](https://github.com/rubyatscale/code_ownership) gives your application the capability to determine the owner of a pack
12
+ - [`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.
13
+ - [`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).
14
+
15
+ # How is a pack different from a gem?
16
+ 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.
@@ -0,0 +1,37 @@
1
+ # typed: strict
2
+
3
+ module Packs
4
+ class Configuration
5
+ extend T::Sig
6
+
7
+ sig { params(roots: T::Array[String]).void }
8
+ attr_writer :roots
9
+
10
+ sig { void }
11
+ def initialize
12
+ @roots = T.let(ROOTS, T::Array[String])
13
+ end
14
+
15
+ sig { returns(T::Array[Pathname]) }
16
+ def roots
17
+ @roots.map do |root|
18
+ Pathname.new(root)
19
+ end
20
+ end
21
+ end
22
+
23
+ class << self
24
+ extend T::Sig
25
+
26
+ sig { returns(Configuration) }
27
+ def config
28
+ @config = T.let(@config, T.nilable(Configuration))
29
+ @config ||= Configuration.new
30
+ end
31
+
32
+ sig { params(blk: T.proc.params(arg0: Configuration).void).void }
33
+ def configure(&blk)
34
+ yield(config)
35
+ end
36
+ end
37
+ end
data/lib/packs/pack.rb ADDED
@@ -0,0 +1,43 @@
1
+ # typed: strict
2
+
3
+ module Packs
4
+ class Pack < T::Struct
5
+ extend T::Sig
6
+
7
+ const :name, String
8
+ const :path, Pathname
9
+ const :relative_path, Pathname
10
+ const :raw_hash, T::Hash[T.untyped, T.untyped]
11
+
12
+ sig { params(package_yml_absolute_path: Pathname).returns(Pack) }
13
+ def self.from(package_yml_absolute_path)
14
+ package_loaded_yml = YAML.load_file(package_yml_absolute_path)
15
+ path = package_yml_absolute_path.dirname
16
+ relative_path = path.relative_path_from(Private.root)
17
+ package_name = relative_path.cleanpath.to_s
18
+
19
+ Pack.new(
20
+ name: package_name,
21
+ path: path,
22
+ relative_path: relative_path,
23
+ raw_hash: package_loaded_yml || {}
24
+ )
25
+ end
26
+
27
+ sig { params(relative: T::Boolean).returns(Pathname) }
28
+ def yml(relative: true)
29
+ path_to_use = relative ? relative_path : path
30
+ path_to_use.join(PACKAGE_FILE).cleanpath
31
+ end
32
+
33
+ sig { returns(String) }
34
+ def last_name
35
+ relative_path.basename.to_s
36
+ end
37
+
38
+ sig { returns(T::Hash[T.untyped, T.untyped]) }
39
+ def metadata
40
+ raw_hash['metadata'] || {}
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,14 @@
1
+ # typed: strict
2
+
3
+ module Packs
4
+ module Private
5
+ extend T::Sig
6
+
7
+ sig { returns(Pathname) }
8
+ def self.root
9
+ Pathname.pwd
10
+ end
11
+ end
12
+
13
+ private_constant :Private
14
+ end
data/lib/packs.rb CHANGED
@@ -1,5 +1,68 @@
1
1
  # typed: strict
2
2
 
3
- # Coming soon...!
3
+ require 'yaml'
4
+ require 'sorbet-runtime'
5
+ require 'packs/pack'
6
+ require 'packs/configuration'
7
+ require 'packs/private'
8
+
4
9
  module Packs
10
+ PACKAGE_FILE = T.let('package.yml'.freeze, String)
11
+ ROOTS = T.let(%w[packs components], T::Array[String])
12
+
13
+ class << self
14
+ extend T::Sig
15
+
16
+ sig { returns(T::Array[Pack]) }
17
+ def all
18
+ packs_by_name.values
19
+ end
20
+
21
+ sig { params(name: String).returns(T.nilable(Pack)) }
22
+ def find(name)
23
+ packs_by_name[name]
24
+ end
25
+
26
+ sig { params(file_path: T.any(Pathname, String)).returns(T.nilable(Pack)) }
27
+ def for_file(file_path)
28
+ path_string = file_path.to_s
29
+ @for_file = T.let(@for_file, T.nilable(T::Hash[String, T.nilable(Pack)]))
30
+ @for_file ||= {}
31
+ @for_file[path_string] ||= all.find { |package| path_string.start_with?("#{package.name}/") || path_string == package.name }
32
+ end
33
+
34
+ sig { void }
35
+ def bust_cache!
36
+ @packs_by_name = nil
37
+ @config = nil
38
+ @for_file = nil
39
+ end
40
+
41
+ private
42
+
43
+ sig { returns(T::Hash[String, Pack]) }
44
+ def packs_by_name
45
+ @packs_by_name = T.let(@packs_by_name, T.nilable(T::Hash[String, Pack]))
46
+ @packs_by_name ||= begin
47
+ all_packs = package_glob_patterns.map do |path|
48
+ Pack.from(path)
49
+ end
50
+
51
+ # We want to match more specific paths first so for_file works correctly.
52
+ sorted_packages = all_packs.sort_by { |package| -package.name.length }
53
+ sorted_packages.to_h { |p| [p.name, p] }
54
+ end
55
+ end
56
+
57
+ sig { returns(T::Array[Pathname]) }
58
+ def package_glob_patterns
59
+ config.roots.flat_map do |root|
60
+ absolute_root = Private.root.join(root)
61
+ [
62
+ *absolute_root.glob("*/#{PACKAGE_FILE}"),
63
+ *absolute_root.glob("*/*/#{PACKAGE_FILE}")
64
+ ]
65
+ end
66
+ end
67
+ end
5
68
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: packs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gusto Engineers
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-10-05 00:00:00.000000000 Z
11
+ date: 2022-12-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sorbet-runtime
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: sorbet
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -104,8 +118,9 @@ extra_rdoc_files: []
104
118
  files:
105
119
  - README.md
106
120
  - lib/packs.rb
107
- - sorbet/config
108
- - sorbet/rbi/todo.rbi
121
+ - lib/packs/configuration.rb
122
+ - lib/packs/pack.rb
123
+ - lib/packs/private.rb
109
124
  homepage: https://github.com/rubyatscale/packs
110
125
  licenses:
111
126
  - MIT
@@ -129,7 +144,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
129
144
  - !ruby/object:Gem::Version
130
145
  version: '0'
131
146
  requirements: []
132
- rubygems_version: 3.3.7
147
+ rubygems_version: 3.1.6
133
148
  signing_key:
134
149
  specification_version: 4
135
150
  summary: Packs are the specification for gradual modularization in the `rubyatscale`
data/sorbet/config DELETED
@@ -1,3 +0,0 @@
1
- --dir
2
- .
3
- --ignore=/vendor/bundle
data/sorbet/rbi/todo.rbi DELETED
@@ -1,5 +0,0 @@
1
- # This file is autogenerated. Do not edit it by hand. Regenerate it with:
2
- # srb rbi todo
3
-
4
- # typed: strong
5
- module ::RSpec; end