packs 0.0.1 → 0.0.2
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 +4 -4
- data/README.md +15 -0
- data/lib/packs/configuration.rb +37 -0
- data/lib/packs/pack.rb +43 -0
- data/lib/packs/private.rb +14 -0
- data/lib/packs.rb +64 -1
- metadata +20 -5
- data/sorbet/config +0 -3
- data/sorbet/rbi/todo.rbi +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 29e18f23de09397b4441c88789b231d1226bd68bea5d0fce16655d0367f93b9b
|
4
|
+
data.tar.gz: bfd5b5aefd4de2aa8b126accd52c44a980ca1302a57c49d6faf37a969ca2d1f5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
data/lib/packs.rb
CHANGED
@@ -1,5 +1,68 @@
|
|
1
1
|
# typed: strict
|
2
2
|
|
3
|
-
|
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.
|
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-
|
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
|
-
-
|
108
|
-
-
|
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.
|
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