purl 1.1.0 → 1.1.1

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: 25661f74cff7bd498cd8b82d64887231cd1a576b8ce0ef59c5397c6d378759eb
4
- data.tar.gz: 0e82bbe5c1600601b3f27a82c79d9ea579587961ae97df1f1272ce31da35877e
3
+ metadata.gz: ae14d9c24e0b1f4f8d76b97c59ed34d8e34090d5329ac9358bf40be4e4acdf14
4
+ data.tar.gz: 4ff6fa43fd388006d553bae72b4685ef228cff186b135ec335d7a6b724abb034
5
5
  SHA512:
6
- metadata.gz: d95b6ca47f39eccb13394340e6a63a9acfa9c0efc8a031897e876fe0350e354ae1d1e4f45f747463e14e1060b89e455e03e3dcbedcefca3a99522fe4f4b54fa1
7
- data.tar.gz: 3e5322963a75161291bead8050759a0578c07c8e2b8a732a6a3ca7180b0ffa5a099a63f9cb95785e9dcc42674f1933b10aa6acc9450f4e30ec8f233aa9bb6983
6
+ metadata.gz: 5f965309ce3f2dddc29065c247082f11541a8ead617c2ad398a7dbd71affd6417e7f09959d88ea59492256dec7039b458507688da9288723bda2d83942f6683f
7
+ data.tar.gz: eb9fd5d72ba8a6c40cafe9c736594f76d20ea40e1886af1693d54dbb36b1ba1105ed05b415b6989098b7288df79a6e9f3c3ddb7aa095eb6dad069a7755374f39
data/README.md CHANGED
@@ -8,7 +8,7 @@ This library features comprehensive error handling with namespaced error types,
8
8
  [![Gem Version](https://badge.fury.io/rb/purl.svg)](https://rubygems.org/gems/purl)
9
9
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
10
10
 
11
- **[Available on RubyGems](https://rubygems.org/gems/purl)**
11
+ **[Available on RubyGems](https://rubygems.org/gems/purl)** | **[API Documentation](https://rdoc.info/github/andrew/purl)**
12
12
 
13
13
  ## Features
14
14
 
data/Rakefile CHANGED
@@ -2,9 +2,20 @@
2
2
 
3
3
  require "bundler/gem_tasks"
4
4
  require "minitest/test_task"
5
+ require "rdoc/task"
5
6
 
6
7
  Minitest::TestTask.create
7
8
 
9
+ RDoc::Task.new do |rdoc|
10
+ rdoc.rdoc_dir = "doc"
11
+ rdoc.title = "PURL - Package URL Library"
12
+ rdoc.main = "README.md"
13
+ rdoc.rdoc_files.include("README.md", "lib/**/*.rb")
14
+ rdoc.options << "--line-numbers"
15
+ rdoc.options << "--all"
16
+ rdoc.options << "--charset=UTF-8"
17
+ end
18
+
8
19
  task default: :test
9
20
 
10
21
  namespace :spec do
@@ -396,7 +407,14 @@ namespace :spec do
396
407
  desc "Validate JSON files against their schemas"
397
408
  task :validate_schemas do
398
409
  require "json"
399
- require "json-schema"
410
+
411
+ begin
412
+ require "json-schema"
413
+ rescue LoadError => e
414
+ puts "❌ json-schema gem not available: #{e.message}"
415
+ puts " Install with: gem install json-schema"
416
+ exit 1
417
+ end
400
418
 
401
419
  puts "🔍 Validating JSON files against schemas..."
402
420
  puts "=" * 50
data/lib/purl/errors.rb CHANGED
@@ -5,9 +5,31 @@ module Purl
5
5
  class Error < StandardError; end
6
6
 
7
7
  # Validation errors for PURL components
8
+ #
9
+ # Contains additional context about which component failed validation
10
+ # and what rule was violated.
11
+ #
12
+ # @example
13
+ # begin
14
+ # PackageURL.new(type: "123invalid", name: "test")
15
+ # rescue ValidationError => e
16
+ # puts e.component # :type
17
+ # puts e.rule # "cannot start with number"
18
+ # end
8
19
  class ValidationError < Error
9
- attr_reader :component, :value, :rule
20
+ # @return [Symbol, nil] the PURL component that failed validation
21
+ attr_reader :component
22
+
23
+ # @return [Object, nil] the value that failed validation
24
+ attr_reader :value
25
+
26
+ # @return [String, nil] the validation rule that was violated
27
+ attr_reader :rule
10
28
 
29
+ # @param message [String] error message
30
+ # @param component [Symbol, nil] component that failed validation
31
+ # @param value [Object, nil] value that failed validation
32
+ # @param rule [String, nil] validation rule that was violated
11
33
  def initialize(message, component: nil, value: nil, rule: nil)
12
34
  super(message)
13
35
  @component = component
@@ -19,40 +41,71 @@ module Purl
19
41
  # Parsing errors for malformed PURL strings
20
42
  class ParseError < Error; end
21
43
 
22
- # Specific validation errors
44
+ # Specific validation errors for PURL components
45
+
46
+ # Raised when a PURL type is invalid
23
47
  class InvalidTypeError < ValidationError; end
48
+
49
+ # Raised when a PURL name is invalid
24
50
  class InvalidNameError < ValidationError; end
51
+
52
+ # Raised when a PURL namespace is invalid
25
53
  class InvalidNamespaceError < ValidationError; end
54
+
55
+ # Raised when a PURL qualifier is invalid
26
56
  class InvalidQualifierError < ValidationError; end
57
+
58
+ # Raised when a PURL version is invalid
27
59
  class InvalidVersionError < ValidationError; end
60
+
61
+ # Raised when a PURL subpath is invalid
28
62
  class InvalidSubpathError < ValidationError; end
29
63
 
30
64
  # Parsing-specific errors
65
+
66
+ # Raised when a PURL string doesn't start with "pkg:"
31
67
  class InvalidSchemeError < ParseError; end
68
+
69
+ # Raised when a PURL string is malformed
32
70
  class MalformedUrlError < ParseError; end
33
71
 
34
72
  # Registry URL generation errors
73
+ #
74
+ # Contains additional context about which type caused the error.
35
75
  class RegistryError < Error
76
+ # @return [String, nil] the PURL type that caused the error
36
77
  attr_reader :type
37
78
 
79
+ # @param message [String] error message
80
+ # @param type [String, nil] PURL type that caused the error
38
81
  def initialize(message, type: nil)
39
82
  super(message)
40
83
  @type = type
41
84
  end
42
85
  end
43
86
 
87
+ # Raised when trying to generate registry URLs for unsupported types
44
88
  class UnsupportedTypeError < RegistryError
89
+ # @return [Array<String>] list of supported types
45
90
  attr_reader :supported_types
46
91
 
92
+ # @param message [String] error message
93
+ # @param type [String, nil] unsupported type
94
+ # @param supported_types [Array<String>] list of supported types
47
95
  def initialize(message, type: nil, supported_types: [])
48
96
  super(message, type: type)
49
97
  @supported_types = supported_types
50
98
  end
51
99
  end
52
100
 
101
+ # Raised when required registry information is missing
53
102
  class MissingRegistryInfoError < RegistryError
103
+ # @return [String, nil] the missing information (e.g., "namespace")
54
104
  attr_reader :missing
55
105
 
106
+ # @param message [String] error message
107
+ # @param type [String, nil] PURL type
108
+ # @param missing [String, nil] what information is missing
56
109
  def initialize(message, type: nil, missing: nil)
57
110
  super(message, type: type)
58
111
  @missing = missing
@@ -60,5 +113,6 @@ module Purl
60
113
  end
61
114
 
62
115
  # Legacy compatibility - matches packageurl-ruby's exception name
116
+ # @deprecated Use {ParseError} instead
63
117
  InvalidPackageURL = ParseError
64
118
  end
@@ -3,12 +3,74 @@
3
3
  require "uri"
4
4
 
5
5
  module Purl
6
+ # Represents a Package URL (PURL) - a mostly universal standard to reference
7
+ # a software package in a uniform way across many tools, programming languages
8
+ # and ecosystems.
9
+ #
10
+ # A PURL has the following components:
11
+ # - +type+: the package type (e.g., "gem", "npm", "maven")
12
+ # - +namespace+: optional namespace/scope (e.g., "@babel" for npm)
13
+ # - +name+: the package name (required)
14
+ # - +version+: optional version
15
+ # - +qualifiers+: optional key-value pairs
16
+ # - +subpath+: optional path within the package
17
+ #
18
+ # @example Creating a PackageURL
19
+ # purl = PackageURL.new(
20
+ # type: "gem",
21
+ # name: "rails",
22
+ # version: "7.0.0"
23
+ # )
24
+ # puts purl.to_s # "pkg:gem/rails@7.0.0"
25
+ #
26
+ # @example Parsing a PURL string
27
+ # purl = PackageURL.parse("pkg:npm/@babel/core@7.0.0")
28
+ # puts purl.namespace # "@babel"
29
+ # puts purl.name # "core"
30
+ #
31
+ # @see https://github.com/package-url/purl-spec PURL Specification
6
32
  class PackageURL
7
- attr_reader :type, :namespace, :name, :version, :qualifiers, :subpath
33
+ # @return [String] the package type (e.g., "gem", "npm", "maven")
34
+ attr_reader :type
35
+
36
+ # @return [String, nil] the package namespace/scope
37
+ attr_reader :namespace
38
+
39
+ # @return [String] the package name
40
+ attr_reader :name
41
+
42
+ # @return [String, nil] the package version
43
+ attr_reader :version
44
+
45
+ # @return [Hash<String, String>, nil] key-value qualifier pairs
46
+ attr_reader :qualifiers
47
+
48
+ # @return [String, nil] subpath within the package
49
+ attr_reader :subpath
8
50
 
9
51
  VALID_TYPE_CHARS = /\A[a-zA-Z0-9\.\+\-]+\z/
10
52
  VALID_QUALIFIER_KEY_CHARS = /\A[a-zA-Z0-9\.\-_]+\z/
11
53
 
54
+ # Create a new PackageURL instance
55
+ #
56
+ # @param type [String, Symbol] the package type (required)
57
+ # @param name [String] the package name (required)
58
+ # @param namespace [String, nil] optional namespace/scope
59
+ # @param version [String, nil] optional version
60
+ # @param qualifiers [Hash, nil] optional key-value qualifier pairs
61
+ # @param subpath [String, nil] optional subpath within package
62
+ #
63
+ # @raise [InvalidTypeError] if type is invalid
64
+ # @raise [InvalidNameError] if name is invalid
65
+ # @raise [ValidationError] if any component fails type-specific validation
66
+ #
67
+ # @example
68
+ # purl = PackageURL.new(
69
+ # type: "npm",
70
+ # namespace: "@babel",
71
+ # name: "core",
72
+ # version: "7.0.0"
73
+ # )
12
74
  def initialize(type:, name:, namespace: nil, version: nil, qualifiers: nil, subpath: nil)
13
75
  @type = validate_and_normalize_type(type)
14
76
  @name = validate_name(name)
@@ -21,6 +83,25 @@ module Purl
21
83
  validate_type_specific_rules
22
84
  end
23
85
 
86
+ # Parse a PURL string into a PackageURL object
87
+ #
88
+ # @param purl_string [String] PURL string starting with "pkg:"
89
+ # @return [PackageURL] parsed package URL object
90
+ # @raise [InvalidSchemeError] if string doesn't start with "pkg:"
91
+ # @raise [MalformedUrlError] if string is malformed
92
+ # @raise [ValidationError] if parsed components fail validation
93
+ #
94
+ # @example Basic parsing
95
+ # purl = PackageURL.parse("pkg:gem/rails@7.0.0")
96
+ # puts purl.type # "gem"
97
+ # puts purl.name # "rails"
98
+ # puts purl.version # "7.0.0"
99
+ #
100
+ # @example Complex parsing with all components
101
+ # purl = PackageURL.parse("pkg:npm/@babel/core@7.0.0?arch=x64#lib/index.js")
102
+ # puts purl.namespace # "@babel"
103
+ # puts purl.qualifiers # {"arch" => "x64"}
104
+ # puts purl.subpath # "lib/index.js"
24
105
  def self.parse(purl_string)
25
106
  raise InvalidSchemeError, "PURL must start with 'pkg:'" unless purl_string.start_with?("pkg:")
26
107
 
@@ -134,6 +215,13 @@ module Purl
134
215
  )
135
216
  end
136
217
 
218
+ # Convert the PackageURL to its canonical string representation
219
+ #
220
+ # @return [String] canonical PURL string
221
+ #
222
+ # @example
223
+ # purl = PackageURL.new(type: "gem", name: "rails", version: "7.0.0")
224
+ # puts purl.to_s # "pkg:gem/rails@7.0.0"
137
225
  def to_s
138
226
  result = "pkg:#{type.downcase}"
139
227
 
@@ -183,6 +271,15 @@ module Purl
183
271
  result
184
272
  end
185
273
 
274
+ # Convert the PackageURL to a hash representation
275
+ #
276
+ # @return [Hash<Symbol, Object>] hash with component keys and values
277
+ #
278
+ # @example
279
+ # purl = PackageURL.new(type: "gem", name: "rails", version: "7.0.0")
280
+ # hash = purl.to_h
281
+ # # => {:type=>"gem", :namespace=>nil, :name=>"rails", :version=>"7.0.0",
282
+ # # :qualifiers=>nil, :subpath=>nil}
186
283
  def to_h
187
284
  {
188
285
  type: type,
@@ -194,28 +291,69 @@ module Purl
194
291
  }
195
292
  end
196
293
 
294
+ # Compare two PackageURL objects for equality
295
+ #
296
+ # Two PURLs are equal if their canonical string representations are identical.
297
+ #
298
+ # @param other [Object] object to compare with
299
+ # @return [Boolean] true if equal, false otherwise
300
+ #
301
+ # @example
302
+ # purl1 = PackageURL.parse("pkg:gem/rails@7.0.0")
303
+ # purl2 = PackageURL.parse("pkg:gem/rails@7.0.0")
304
+ # puts purl1 == purl2 # true
197
305
  def ==(other)
198
306
  return false unless other.is_a?(PackageURL)
199
307
 
200
308
  to_s == other.to_s
201
309
  end
202
310
 
311
+ # Generate hash code for the PackageURL
312
+ #
313
+ # @return [Integer] hash code based on canonical string representation
203
314
  def hash
204
315
  to_s.hash
205
316
  end
206
317
 
207
318
  # Pattern matching support for Ruby 2.7+
319
+ #
320
+ # Allows destructuring PackageURL in pattern matching.
321
+ #
322
+ # @return [Array] array of [type, namespace, name, version, qualifiers, subpath]
323
+ #
324
+ # @example Ruby 2.7+ pattern matching
325
+ # case purl
326
+ # in ["gem", nil, name, version, nil, nil]
327
+ # puts "Simple gem: #{name} v#{version}"
328
+ # end
208
329
  def deconstruct
209
330
  [type, namespace, name, version, qualifiers, subpath]
210
331
  end
211
332
 
333
+ # Pattern matching support for Ruby 2.7+ (hash patterns)
334
+ #
335
+ # @param keys [Array<Symbol>, nil] keys to extract, or nil for all keys
336
+ # @return [Hash<Symbol, Object>] hash with requested keys
337
+ #
338
+ # @example Ruby 2.7+ hash pattern matching
339
+ # case purl
340
+ # in {type: "gem", name:, version:}
341
+ # puts "Gem #{name} version #{version}"
342
+ # end
212
343
  def deconstruct_keys(keys)
213
344
  return to_h.slice(*keys) if keys
214
345
  to_h
215
346
  end
216
347
 
217
348
  # Create a new PackageURL with modified attributes
218
- # Usage: new_purl = purl.with(version: "2.0.0", qualifiers: {"arch" => "x64"})
349
+ #
350
+ # @param changes [Hash] attributes to change
351
+ # @return [PackageURL] new PackageURL instance with changes applied
352
+ #
353
+ # @example
354
+ # purl = PackageURL.parse("pkg:gem/rails@7.0.0")
355
+ # new_purl = purl.with(version: "7.1.0", qualifiers: {"arch" => "x64"})
356
+ # puts new_purl.to_s # "pkg:gem/rails@7.1.0?arch=x64"
219
357
  def with(**changes)
220
358
  current_attrs = to_h
221
359
  new_attrs = current_attrs.merge(changes)
data/lib/purl/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Purl
4
- VERSION = "1.1.0"
4
+ VERSION = "1.1.1"
5
5
  end
data/lib/purl.rb CHANGED
@@ -5,7 +5,25 @@ require_relative "purl/errors"
5
5
  require_relative "purl/package_url"
6
6
  require_relative "purl/registry_url"
7
7
 
8
+ # The main PURL (Package URL) module providing functionality to parse,
9
+ # validate, and generate package URLs according to the PURL specification.
10
+ #
11
+ # A Package URL is a mostly universal standard to reference a software package
12
+ # in a uniform way across many tools, programming languages and ecosystems.
13
+ #
14
+ # @example Basic usage
15
+ # purl = Purl.parse("pkg:gem/rails@7.0.0")
16
+ # puts purl.type # "gem"
17
+ # puts purl.name # "rails"
18
+ # puts purl.version # "7.0.0"
19
+ #
20
+ # @example Registry URL conversion
21
+ # purl = Purl.from_registry_url("https://rubygems.org/gems/rails")
22
+ # puts purl.to_s # "pkg:gem/rails"
23
+ #
24
+ # @see https://github.com/package-url/purl-spec PURL Specification
8
25
  module Purl
26
+ # Base error class for all PURL-related errors
9
27
  class Error < StandardError; end
10
28
 
11
29
  # Load PURL types configuration from JSON file
@@ -21,6 +39,15 @@ module Purl
21
39
  KNOWN_TYPES = load_types_config["types"].keys.sort.freeze
22
40
 
23
41
  # Convenience method for parsing PURL strings
42
+ #
43
+ # @param purl_string [String] a PURL string starting with "pkg:"
44
+ # @return [PackageURL] parsed package URL object
45
+ # @raise [InvalidSchemeError] if string doesn't start with "pkg:"
46
+ # @raise [MalformedUrlError] if string is malformed
47
+ #
48
+ # @example
49
+ # purl = Purl.parse("pkg:gem/rails@7.0.0")
50
+ # puts purl.name # "rails"
24
51
  def self.parse(purl_string)
25
52
  PackageURL.parse(purl_string)
26
53
  end
@@ -33,26 +60,66 @@ module Purl
33
60
  end
34
61
 
35
62
  # Returns all known PURL types
63
+ #
64
+ # @return [Array<String>] sorted array of known PURL type names
65
+ #
66
+ # @example
67
+ # types = Purl.known_types
68
+ # puts types.include?("gem") # true
36
69
  def self.known_types
37
70
  KNOWN_TYPES.dup
38
71
  end
39
72
 
40
73
  # Returns types that have registry URL support
74
+ #
75
+ # @return [Array<String>] sorted array of types that can generate registry URLs
76
+ #
77
+ # @example
78
+ # types = Purl.registry_supported_types
79
+ # puts types.include?("npm") # true if npm has registry support
41
80
  def self.registry_supported_types
42
81
  RegistryURL.supported_types
43
82
  end
44
83
 
45
84
  # Returns types that support reverse parsing from registry URLs
85
+ #
86
+ # @return [Array<String>] sorted array of types that can parse registry URLs back to PURLs
87
+ #
88
+ # @example
89
+ # types = Purl.reverse_parsing_supported_types
90
+ # puts types.include?("gem") # true if gem has reverse parsing support
46
91
  def self.reverse_parsing_supported_types
47
92
  RegistryURL.supported_reverse_types
48
93
  end
49
94
 
50
95
  # Check if a type is known/valid
96
+ #
97
+ # @param type [String, Symbol] the type to check
98
+ # @return [Boolean] true if type is known, false otherwise
99
+ #
100
+ # @example
101
+ # Purl.known_type?("gem") # true
102
+ # Purl.known_type?("unknown") # false
51
103
  def self.known_type?(type)
52
104
  KNOWN_TYPES.include?(type.to_s.downcase)
53
105
  end
54
106
 
55
- # Get type information including registry support
107
+ # Get comprehensive type information including registry support
108
+ #
109
+ # @param type [String, Symbol] the type to get information for
110
+ # @return [Hash] hash containing type information with keys:
111
+ # - +:type+: normalized type name
112
+ # - +:known+: whether type is known
113
+ # - +:description+: human-readable description
114
+ # - +:default_registry+: default registry URL
115
+ # - +:examples+: array of example PURLs
116
+ # - +:registry_url_generation+: whether registry URL generation is supported
117
+ # - +:reverse_parsing+: whether reverse parsing is supported
118
+ # - +:route_patterns+: array of URL patterns for this type
119
+ #
120
+ # @example
121
+ # info = Purl.type_info("gem")
122
+ # puts info[:description] # "Ruby gems from RubyGems.org"
56
123
  def self.type_info(type)
57
124
  normalized_type = type.to_s.downcase
58
125
  {
@@ -68,6 +135,13 @@ module Purl
68
135
  end
69
136
 
70
137
  # Get comprehensive information about all types
138
+ #
139
+ # @return [Hash<String, Hash>] hash mapping type names to their information
140
+ # @see #type_info for structure of individual type information
141
+ #
142
+ # @example
143
+ # all_info = Purl.all_type_info
144
+ # gem_info = all_info["gem"]
71
145
  def self.all_type_info
72
146
  result = {}
73
147
 
@@ -87,6 +161,10 @@ module Purl
87
161
  end
88
162
 
89
163
  # Get type configuration from JSON
164
+ #
165
+ # @param type [String, Symbol] the type to get configuration for
166
+ # @return [Hash, nil] configuration hash or nil if type not found
167
+ # @api private
90
168
  def self.type_config(type)
91
169
  config = load_types_config["types"][type.to_s.downcase]
92
170
  return nil unless config
@@ -94,13 +172,27 @@ module Purl
94
172
  config.dup # Return a copy to prevent modification
95
173
  end
96
174
 
97
- # Get description for a type
175
+ # Get human-readable description for a type
176
+ #
177
+ # @param type [String, Symbol] the type to get description for
178
+ # @return [String, nil] description string or nil if not available
179
+ #
180
+ # @example
181
+ # desc = Purl.type_description("gem")
182
+ # puts desc # "Ruby gems from RubyGems.org"
98
183
  def self.type_description(type)
99
184
  config = type_config(type)
100
185
  config ? config["description"] : nil
101
186
  end
102
187
 
103
- # Get examples for a type
188
+ # Get example PURLs for a type
189
+ #
190
+ # @param type [String, Symbol] the type to get examples for
191
+ # @return [Array<String>] array of example PURL strings
192
+ #
193
+ # @example
194
+ # examples = Purl.type_examples("gem")
195
+ # puts examples.first # "pkg:gem/rails@7.0.0"
104
196
  def self.type_examples(type)
105
197
  config = type_config(type)
106
198
  return [] unless config
@@ -109,6 +201,10 @@ module Purl
109
201
  end
110
202
 
111
203
  # Get registry configuration for a type
204
+ #
205
+ # @param type [String, Symbol] the type to get registry config for
206
+ # @return [Hash, nil] registry configuration hash or nil if not available
207
+ # @api private
112
208
  def self.registry_config(type)
113
209
  config = type_config(type)
114
210
  return nil unless config
@@ -117,6 +213,13 @@ module Purl
117
213
  end
118
214
 
119
215
  # Get default registry URL for a type
216
+ #
217
+ # @param type [String, Symbol] the type to get default registry for
218
+ # @return [String, nil] default registry URL or nil if not available
219
+ #
220
+ # @example
221
+ # registry = Purl.default_registry("gem")
222
+ # puts registry # "https://rubygems.org"
120
223
  def self.default_registry(type)
121
224
  config = type_config(type)
122
225
  return nil unless config
@@ -125,6 +228,19 @@ module Purl
125
228
  end
126
229
 
127
230
  # Get metadata about the types configuration
231
+ #
232
+ # @return [Hash] metadata hash with keys:
233
+ # - +:version+: configuration version
234
+ # - +:description+: configuration description
235
+ # - +:source+: source of the configuration
236
+ # - +:last_updated+: when configuration was last updated
237
+ # - +:total_types+: total number of types
238
+ # - +:registry_supported_types+: number of types with registry support
239
+ # - +:types_with_default_registry+: number of types with default registry
240
+ #
241
+ # @example
242
+ # metadata = Purl.types_config_metadata
243
+ # puts "Total types: #{metadata[:total_types]}"
128
244
  def self.types_config_metadata
129
245
  config = load_types_config
130
246
  {
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: purl
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Nesbitt