Module: ParsePackwerk

Extended by:
T::Sig
Defined in:
lib/parse_packwerk/package.rb,
lib/parse_packwerk.rb,
lib/parse_packwerk/constants.rb,
lib/parse_packwerk/violation.rb,
lib/parse_packwerk/extensions.rb,
lib/parse_packwerk/package_set.rb,
lib/parse_packwerk/package_todo.rb,
lib/parse_packwerk/configuration.rb

Overview

typed: strict

Defined Under Namespace

Classes: Configuration, MissingConfiguration, Package, PackageParseError, PackageSet, PackageTodo, Violation

Constant Summary collapse

ROOT_PACKAGE_NAME =
T.let('.'.freeze, String)
PACKAGE_YML_NAME =
T.let('package.yml'.freeze, String)
PACKWERK_YML_NAME =
T.let('packwerk.yml'.freeze, String)
PACKAGE_TODO_YML_NAME =
T.let('package_todo.yml'.freeze, String)
ENFORCE_DEPENDENCIES =
T.let('enforce_dependencies'.freeze, String)
ENFORCE_PRIVACY =
T.let('enforce_privacy'.freeze, String)
ENFORCE_LAYERS =
T.let('enforce_layers'.freeze, String)
DEPENDENCY_VIOLATION_TYPE =
T.let('dependency'.freeze, String)
PRIVACY_VIOLATION_TYPE =
T.let('privacy'.freeze, String)
PUBLIC_PATH =
T.let('public_path'.freeze, String)
METADATA =
T.let('metadata'.freeze, String)
DEPENDENCIES =
T.let('dependencies'.freeze, String)
MetadataYmlType =

Since this metadata is unstructured YAML, it could be any type. We leave it to clients of ‘ParsePackwerk::Package` to add types based on their known usage of metadata.

T.type_alias do
  T::Hash[T.untyped, T.untyped]
end
DEFAULT_EXCLUDE_GLOBS =
T.let(['{bin,node_modules,script,tmp,vendor}/**/*'], T::Array[String])
DEFAULT_PACKAGE_PATHS =
T.let(['**/'], T::Array[String])
DEFAULT_PUBLIC_PATH =
T.let('app/public', String)

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.preserve_key_orderObject

Returns the value of attribute preserve_key_order.



44
45
46
# File 'lib/parse_packwerk.rb', line 44

def preserve_key_order
  @preserve_key_order
end

Class Method Details

.allObject



50
51
52
# File 'lib/parse_packwerk.rb', line 50

def self.all
  packages_by_name.values
end

.bust_cache!Object



163
164
165
166
# File 'lib/parse_packwerk.rb', line 163

def self.bust_cache!
  @packages_by_name = nil
  @package_from_path = nil
end

.find(name) ⇒ Object



55
56
57
# File 'lib/parse_packwerk.rb', line 55

def self.find(name)
  packages_by_name[name]
end

.key_sort_orderObject



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/parse_packwerk.rb', line 132

def self.key_sort_order
  %w[
    enforce_dependencies
    enforce_privacy
    enforce_visibility
    enforce_layers
    public_path
    owner
    layer
    dependencies
    ignored_dependencies
    visible_to
    metadata
  ]
end

.package_from_path(file_path) ⇒ Object



65
66
67
68
69
70
71
72
73
# File 'lib/parse_packwerk.rb', line 65

def self.package_from_path(file_path)
  path_string = file_path.to_s
  @package_from_path = T.let(@package_from_path, T.nilable(T::Hash[String, Package]))
  @package_from_path ||= {}
  @package_from_path[path_string] ||= T.must(begin
    matching_package = all.find { |package| path_string.start_with?("#{package.name}/") || path_string == package.name }
    matching_package || find(ROOT_PACKAGE_NAME)
  end)
end

.sort_keys(config, original_key_order) ⇒ Object



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/parse_packwerk.rb', line 115

def self.sort_keys(config, original_key_order)
  if preserve_key_order && original_key_order.any?
    # Preserve original key order: existing keys stay in their original position,
    # new keys are appended in the default sort order
    existing_keys = original_key_order & config.keys
    new_keys = config.keys - original_key_order
    sorted_new_keys = new_keys.sort_by { |key| key_sort_order.index(key) || 1000 }

    ordered_keys = existing_keys + sorted_new_keys
    ordered_keys.each_with_object({}) { |key, hash| hash[key] = config[key] if config.key?(key) }
  else
    # Default behavior: sort by canonical key order
    config.to_a.sort_by { |key, _value| T.unsafe(key_sort_order).index(key) || 1000 }.to_h
  end
end

.write_package_yml!(package) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/parse_packwerk.rb', line 76

def self.write_package_yml!(package)
  FileUtils.mkdir_p(package.directory)

  File.open(package.yml, 'w') do |file|
    merged_config = package.config

    merged_config.merge!('enforce_dependencies' => package.enforce_dependencies)

    if Extensions.privacy_extension_installed?
      merged_config.merge!('enforce_privacy' => package.enforce_privacy)
    end

    if Extensions.layer_extension_installed?
      merged_config.merge!('enforce_layers' => package.enforce_layers)
    end

    unless package.public_path == DEFAULT_PUBLIC_PATH
      merged_config.merge!('public_path' => package.public_path)
    end

    if package.dependencies.nil? || package.dependencies.none?
      merged_config.delete('dependencies')
    else
      merged_config.merge!('dependencies' => package.dependencies)
    end

    if package..any?
      merged_config.merge!('metadata' => package.)
    end

    merged_config = sort_keys(merged_config, package.original_key_order)

    raw_yaml = YAML.dump(merged_config)
    stylized_yaml = raw_yaml.gsub("---\n", '')
    file.write(stylized_yaml)
  end
end

.ymlObject



60
61
62
# File 'lib/parse_packwerk.rb', line 60

def self.yml
  Configuration.fetch
end