purl 0.1.0 → 1.0.0
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/CHANGELOG.md +43 -2
- data/CODE_OF_CONDUCT.md +1 -1
- data/LICENSE +21 -0
- data/README.md +273 -13
- data/Rakefile +385 -0
- data/lib/purl/errors.rb +64 -0
- data/lib/purl/package_url.rb +512 -0
- data/lib/purl/registry_url.rb +309 -0
- data/lib/purl/version.rb +1 -1
- data/lib/purl.rb +111 -1
- data/purl-types.json +358 -0
- data/test-suite-data.json +710 -0
- metadata +7 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7b04edce0acf5c2872aea527f2b3845dcff94e8079d23ed394abd688779e335e
|
|
4
|
+
data.tar.gz: 504d83a02eb4b6574b42bbc790820c1f22335f594667d2e239e1edf2569d5300
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5a7e76a9dfb4042cece6132a19c390c0ab648335d2d4e9a5acb519310c1475c37030c9c20c7f4ef43f6027805c53d713a3e58c1b391bbea592f92f1bfefc3736
|
|
7
|
+
data.tar.gz: 1c8c1662e1f893b7f62278951778a59e3af27df05d2b61a54fb8b7cbb3b418ee00815f0996bcd4c93ae28290bd457c0c2cd0010327fb39cb886704444a573eb7
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,46 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
1
8
|
## [Unreleased]
|
|
2
9
|
|
|
3
|
-
## [
|
|
10
|
+
## [1.0.0] - 2025-01-24
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- 🎯 Comprehensive PURL parsing and validation with all 32 official package types
|
|
14
|
+
- 🔥 Namespaced error handling with contextual information (`InvalidSchemeError`, `InvalidTypeError`, `ValidationError`, etc.)
|
|
15
|
+
- 🔄 Bidirectional registry URL conversion - generate registry URLs from PURLs and parse PURLs from registry URLs
|
|
16
|
+
- 🌐 Registry URL generation for 13+ package ecosystems (npm, gem, maven, pypi, cargo, golang, etc.)
|
|
17
|
+
- 🎨 Rails-style route patterns for registry URL templates
|
|
18
|
+
- 📋 Type-specific validation for conan, cran, and swift packages
|
|
19
|
+
- 🤝 Cross-language compatibility with JSON-based configuration in `purl-types.json`
|
|
20
|
+
- 📊 69.5% compliance with official PURL specification test suite (41/59 tests passing)
|
|
21
|
+
- 🛠️ Comprehensive rake tasks for spec compliance testing and type management
|
|
22
|
+
- 📚 Full documentation and usage examples
|
|
23
|
+
|
|
24
|
+
### Features
|
|
25
|
+
- Parse PURL strings with full component extraction (type, namespace, name, version, qualifiers, subpath)
|
|
26
|
+
- Create PURL objects programmatically with validation
|
|
27
|
+
- Generate registry URLs for supported package types
|
|
28
|
+
- Reverse parse registry URLs back to PURL objects
|
|
29
|
+
- Query package type information and capabilities
|
|
30
|
+
- Validate PURLs according to type-specific rules
|
|
31
|
+
- Support for all official PURL types from the specification
|
|
32
|
+
|
|
33
|
+
### Supported Package Types
|
|
34
|
+
- **Registry URL Generation (13 types):** cargo, cocoapods, composer, conda, gem, golang, hex, maven, npm, nuget, pub, pypi, swift
|
|
35
|
+
- **Reverse Parsing (6 types):** cargo, gem, golang, maven, npm, pypi
|
|
36
|
+
- **All 32 Official Types:** alpm, apk, bitbucket, bitnami, cargo, cocoapods, composer, conan, conda, cpan, cran, deb, docker, gem, generic, github, golang, hackage, hex, huggingface, luarocks, maven, mlflow, npm, nuget, oci, pub, pypi, qpkg, rpm, swid, swift
|
|
37
|
+
|
|
38
|
+
### Development Tools
|
|
39
|
+
- `rake spec:update` - Fetch latest test cases from official PURL spec repository
|
|
40
|
+
- `rake spec:compliance` - Run compliance tests against official test suite
|
|
41
|
+
- `rake spec:types` - Show information about all PURL types and their support
|
|
42
|
+
- `rake spec:verify_types` - Verify types list against official specification
|
|
43
|
+
- `rake spec:debug` - Show detailed info about failing test cases
|
|
4
44
|
|
|
5
|
-
-
|
|
45
|
+
### Major Release - Production Ready
|
|
46
|
+
This marks the first major release of the Purl gem, indicating API stability and production readiness. The library provides comprehensive PURL parsing with better error handling and more features than existing PURL libraries for Ruby, including bidirectional registry URL conversion and cross-language JSON configuration compatibility.
|
data/CODE_OF_CONDUCT.md
CHANGED
|
@@ -60,7 +60,7 @@ representative at an online or offline event.
|
|
|
60
60
|
|
|
61
61
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
62
62
|
reported to the community leaders responsible for enforcement at
|
|
63
|
-
[
|
|
63
|
+
[andrew@ecosyste.ms](mailto:andrew@ecosyste.ms).
|
|
64
64
|
All complaints will be reviewed and investigated promptly and fairly.
|
|
65
65
|
|
|
66
66
|
All community leaders are obligated to respect the privacy and security of the
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Andrew Nesbitt
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
CHANGED
|
@@ -1,39 +1,299 @@
|
|
|
1
|
-
# Purl
|
|
1
|
+
# Purl - Package URL Parser for Ruby
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A comprehensive Ruby library for parsing, validating, and working with Package URLs (PURLs) as defined by the [PURL specification](https://github.com/package-url/purl-spec).
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
This library provides better error handling than existing solutions with namespaced error types, bidirectional registry URL conversion, and JSON-based configuration for cross-language compatibility.
|
|
6
|
+
|
|
7
|
+
[](https://www.ruby-lang.org/)
|
|
8
|
+
[](https://rubygems.org/gems/purl)
|
|
9
|
+
[](https://opensource.org/licenses/MIT)
|
|
10
|
+
|
|
11
|
+
**🔗 [Available on RubyGems](https://rubygems.org/gems/purl)**
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- 🎯 **Comprehensive PURL parsing and validation** with 37 package types (32 official + 5 additional ecosystems)
|
|
16
|
+
- 🔥 **Better error handling** with namespaced error classes and contextual information
|
|
17
|
+
- 🔄 **Bidirectional registry URL conversion** - generate registry URLs from PURLs and parse PURLs from registry URLs
|
|
18
|
+
- 📋 **Type-specific validation** for conan, cran, and swift packages
|
|
19
|
+
- 🌐 **Registry URL generation** for 20 package ecosystems (npm, gem, maven, pypi, etc.)
|
|
20
|
+
- 🎨 **Rails-style route patterns** for registry URL templates
|
|
21
|
+
- 📊 **100% compliance** with official PURL specification test suite (59/59 tests passing)
|
|
22
|
+
- 🤝 **Cross-language compatibility** with JSON-based configuration
|
|
23
|
+
- 📚 **Comprehensive documentation** and examples
|
|
6
24
|
|
|
7
25
|
## Installation
|
|
8
26
|
|
|
9
|
-
|
|
27
|
+
Add this line to your application's Gemfile:
|
|
10
28
|
|
|
11
|
-
|
|
29
|
+
```ruby
|
|
30
|
+
gem 'purl'
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
And then execute:
|
|
12
34
|
|
|
13
35
|
```bash
|
|
14
|
-
bundle
|
|
36
|
+
bundle install
|
|
15
37
|
```
|
|
16
38
|
|
|
17
|
-
|
|
39
|
+
Or install it yourself as:
|
|
18
40
|
|
|
19
41
|
```bash
|
|
20
|
-
gem install
|
|
42
|
+
gem install purl
|
|
21
43
|
```
|
|
22
44
|
|
|
23
45
|
## Usage
|
|
24
46
|
|
|
25
|
-
|
|
47
|
+
### Basic PURL Parsing
|
|
48
|
+
|
|
49
|
+
```ruby
|
|
50
|
+
require 'purl'
|
|
51
|
+
|
|
52
|
+
# Parse a PURL string
|
|
53
|
+
purl = Purl.parse("pkg:gem/rails@7.0.0")
|
|
54
|
+
puts purl.type # => "gem"
|
|
55
|
+
puts purl.name # => "rails"
|
|
56
|
+
puts purl.version # => "7.0.0"
|
|
57
|
+
puts purl.namespace # => nil
|
|
58
|
+
|
|
59
|
+
# Parse with namespace and qualifiers
|
|
60
|
+
purl = Purl.parse("pkg:npm/@babel/core@7.0.0?arch=x86_64")
|
|
61
|
+
puts purl.type # => "npm"
|
|
62
|
+
puts purl.namespace # => "@babel"
|
|
63
|
+
puts purl.name # => "core"
|
|
64
|
+
puts purl.version # => "7.0.0"
|
|
65
|
+
puts purl.qualifiers # => {"arch" => "x86_64"}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Creating PURLs
|
|
69
|
+
|
|
70
|
+
```ruby
|
|
71
|
+
# Create a PURL object
|
|
72
|
+
purl = Purl::PackageURL.new(
|
|
73
|
+
type: "maven",
|
|
74
|
+
namespace: "org.apache.commons",
|
|
75
|
+
name: "commons-lang3",
|
|
76
|
+
version: "3.12.0"
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
puts purl.to_s # => "pkg:maven/org.apache.commons/commons-lang3@3.12.0"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Registry URL Generation
|
|
83
|
+
|
|
84
|
+
```ruby
|
|
85
|
+
# Generate registry URLs from PURLs
|
|
86
|
+
purl = Purl.parse("pkg:gem/rails@7.0.0")
|
|
87
|
+
puts purl.registry_url # => "https://rubygems.org/gems/rails"
|
|
88
|
+
puts purl.registry_url_with_version # => "https://rubygems.org/gems/rails/versions/7.0.0"
|
|
89
|
+
|
|
90
|
+
# Check if registry URL generation is supported
|
|
91
|
+
puts purl.supports_registry_url? # => true
|
|
92
|
+
|
|
93
|
+
# NPM with scoped packages
|
|
94
|
+
purl = Purl.parse("pkg:npm/@babel/core@7.0.0")
|
|
95
|
+
puts purl.registry_url # => "https://www.npmjs.com/package/@babel/core"
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Reverse Parsing: Registry URLs to PURLs
|
|
99
|
+
|
|
100
|
+
```ruby
|
|
101
|
+
# Parse registry URLs back to PURLs
|
|
102
|
+
purl = Purl.from_registry_url("https://rubygems.org/gems/rails/versions/7.0.0")
|
|
103
|
+
puts purl.to_s # => "pkg:gem/rails@7.0.0"
|
|
104
|
+
|
|
105
|
+
# Works with various registries
|
|
106
|
+
purl = Purl.from_registry_url("https://www.npmjs.com/package/@babel/core")
|
|
107
|
+
puts purl.to_s # => "pkg:npm/@babel/core"
|
|
108
|
+
|
|
109
|
+
purl = Purl.from_registry_url("https://pypi.org/project/django/4.0.0/")
|
|
110
|
+
puts purl.to_s # => "pkg:pypi/django@4.0.0"
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Route Patterns
|
|
114
|
+
|
|
115
|
+
```ruby
|
|
116
|
+
# Get route patterns for a package type (Rails-style)
|
|
117
|
+
patterns = Purl::RegistryURL.route_patterns_for("gem")
|
|
118
|
+
# => ["https://rubygems.org/gems/:name", "https://rubygems.org/gems/:name/versions/:version"]
|
|
119
|
+
|
|
120
|
+
# Get all route patterns
|
|
121
|
+
all_patterns = Purl::RegistryURL.all_route_patterns
|
|
122
|
+
puts all_patterns["npm"]
|
|
123
|
+
# => ["https://www.npmjs.com/package/:namespace/:name", "https://www.npmjs.com/package/:name", ...]
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Package Type Information
|
|
127
|
+
|
|
128
|
+
```ruby
|
|
129
|
+
# Get all known PURL types
|
|
130
|
+
puts Purl.known_types.length # => 32
|
|
131
|
+
puts Purl.known_types.include?("gem") # => true
|
|
132
|
+
|
|
133
|
+
# Check type support
|
|
134
|
+
puts Purl.known_type?("gem") # => true
|
|
135
|
+
puts Purl.registry_supported_types # => ["cargo", "gem", "maven", "npm", ...]
|
|
136
|
+
puts Purl.reverse_parsing_supported_types # => ["cargo", "gem", "maven", "npm", ...]
|
|
137
|
+
|
|
138
|
+
# Get detailed type information
|
|
139
|
+
info = Purl.type_info("gem")
|
|
140
|
+
puts info[:known] # => true
|
|
141
|
+
puts info[:registry_url_generation] # => true
|
|
142
|
+
puts info[:reverse_parsing] # => true
|
|
143
|
+
puts info[:route_patterns] # => ["https://rubygems.org/gems/:name", ...]
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Error Handling
|
|
147
|
+
|
|
148
|
+
```ruby
|
|
149
|
+
# Detailed error types with context
|
|
150
|
+
begin
|
|
151
|
+
Purl.parse("invalid-purl")
|
|
152
|
+
rescue Purl::InvalidSchemeError => e
|
|
153
|
+
puts "Scheme error: #{e.message}"
|
|
154
|
+
rescue Purl::ParseError => e
|
|
155
|
+
puts "Parse error: #{e.message}"
|
|
156
|
+
puts "Component: #{e.component}"
|
|
157
|
+
puts "Value: #{e.value}"
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# Type-specific validation errors
|
|
161
|
+
begin
|
|
162
|
+
Purl::PackageURL.new(type: "swift", name: "Alamofire") # Swift requires namespace
|
|
163
|
+
rescue Purl::ValidationError => e
|
|
164
|
+
puts e.message # => "Swift PURLs require a namespace to be unambiguous"
|
|
165
|
+
end
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Supported Package Types
|
|
169
|
+
|
|
170
|
+
The library supports 37 package types (32 official + 5 additional ecosystems):
|
|
171
|
+
|
|
172
|
+
**Registry URL Generation (20 types):**
|
|
173
|
+
- `bioconductor` (R/Bioconductor) - bioconductor.org
|
|
174
|
+
- `cargo` (Rust) - crates.io
|
|
175
|
+
- `clojars` (Clojure) - clojars.org
|
|
176
|
+
- `cocoapods` (iOS) - cocoapods.org
|
|
177
|
+
- `composer` (PHP) - packagist.org
|
|
178
|
+
- `conda` (Python) - anaconda.org
|
|
179
|
+
- `cpan` (Perl) - metacpan.org
|
|
180
|
+
- `deno` (Deno) - deno.land/x
|
|
181
|
+
- `elm` (Elm) - package.elm-lang.org
|
|
182
|
+
- `gem` (Ruby) - rubygems.org
|
|
183
|
+
- `golang` (Go) - pkg.go.dev
|
|
184
|
+
- `hackage` (Haskell) - hackage.haskell.org
|
|
185
|
+
- `hex` (Elixir) - hex.pm
|
|
186
|
+
- `homebrew` (macOS) - formulae.brew.sh
|
|
187
|
+
- `maven` (Java) - mvnrepository.com
|
|
188
|
+
- `npm` (Node.js) - npmjs.com
|
|
189
|
+
- `nuget` (.NET) - nuget.org
|
|
190
|
+
- `pub` (Dart) - pub.dev
|
|
191
|
+
- `pypi` (Python) - pypi.org
|
|
192
|
+
- `swift` (Swift) - swiftpackageindex.com
|
|
193
|
+
|
|
194
|
+
**Reverse Parsing (10 types):**
|
|
195
|
+
- `cargo`, `deno`, `elm`, `gem`, `golang`, `hackage`, `homebrew`, `maven`, `npm`, `pypi`
|
|
196
|
+
|
|
197
|
+
**All 37 Supported Types:**
|
|
198
|
+
`alpm`, `apk`, `bioconductor`, `bitbucket`, `bitnami`, `cargo`, `clojars`, `cocoapods`, `composer`, `conan`, `conda`, `cpan`, `cran`, `deb`, `deno`, `docker`, `elm`, `gem`, `generic`, `github`, `golang`, `hackage`, `hex`, `homebrew`, `huggingface`, `luarocks`, `maven`, `mlflow`, `npm`, `nuget`, `oci`, `pub`, `pypi`, `qpkg`, `rpm`, `swid`, `swift`
|
|
199
|
+
|
|
200
|
+
## Specification Compliance
|
|
201
|
+
|
|
202
|
+
- **100% compliance** with the official PURL specification test suite (59/59 tests passing)
|
|
203
|
+
- **All 32 official package types** plus 5 additional ecosystem types supported
|
|
204
|
+
- **Type-specific validation** for conan, cran, swift, cpan, and mlflow packages
|
|
205
|
+
- **Proper error handling** for invalid PURLs that should be rejected
|
|
206
|
+
|
|
207
|
+
## JSON Configuration
|
|
208
|
+
|
|
209
|
+
Package types and registry patterns are stored in `purl-types.json` for easy contribution and cross-language compatibility:
|
|
210
|
+
|
|
211
|
+
```json
|
|
212
|
+
{
|
|
213
|
+
"version": "1.0.0",
|
|
214
|
+
"description": "PURL types and registry URL patterns for package ecosystems",
|
|
215
|
+
"types": {
|
|
216
|
+
"gem": {
|
|
217
|
+
"description": "RubyGems",
|
|
218
|
+
"registry_support": true,
|
|
219
|
+
"registry_config": {
|
|
220
|
+
"base_url": "https://rubygems.org/gems",
|
|
221
|
+
"route_patterns": ["https://rubygems.org/gems/:name"],
|
|
222
|
+
"reverse_parsing": true
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
```
|
|
26
228
|
|
|
27
229
|
## Development
|
|
28
230
|
|
|
29
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then
|
|
231
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then:
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
# Run tests
|
|
235
|
+
rake test
|
|
236
|
+
|
|
237
|
+
# Run specification compliance tests
|
|
238
|
+
rake spec:compliance
|
|
30
239
|
|
|
31
|
-
|
|
240
|
+
# Update test cases from official PURL spec
|
|
241
|
+
rake spec:update
|
|
242
|
+
|
|
243
|
+
# Show type information
|
|
244
|
+
rake spec:types
|
|
245
|
+
|
|
246
|
+
# Verify types against official specification
|
|
247
|
+
rake spec:verify_types
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Rake Tasks
|
|
251
|
+
|
|
252
|
+
- `rake spec:update` - Fetch latest test cases from official PURL spec repository
|
|
253
|
+
- `rake spec:compliance` - Run compliance tests against official test suite
|
|
254
|
+
- `rake spec:types` - Show information about all PURL types and their support
|
|
255
|
+
- `rake spec:verify_types` - Verify our types list against official specification
|
|
256
|
+
- `rake spec:debug` - Show detailed info about failing test cases
|
|
257
|
+
|
|
258
|
+
## Funding
|
|
259
|
+
|
|
260
|
+
If you find this project useful, please consider supporting its development:
|
|
261
|
+
|
|
262
|
+
- 💝 [GitHub Sponsors](https://github.com/sponsors/andrew)
|
|
263
|
+
- ☕ [Buy me a coffee](https://www.buymeacoffee.com/andrew)
|
|
264
|
+
|
|
265
|
+
Your support helps maintain and improve this library for the entire Ruby community.
|
|
32
266
|
|
|
33
267
|
## Contributing
|
|
34
268
|
|
|
35
|
-
Bug reports and pull requests are welcome on GitHub
|
|
269
|
+
Bug reports and pull requests are welcome on GitHub. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
|
270
|
+
|
|
271
|
+
1. Fork it
|
|
272
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
273
|
+
3. Make your changes
|
|
274
|
+
4. Add tests for your changes
|
|
275
|
+
5. Ensure all tests pass (`rake test`)
|
|
276
|
+
6. Commit your changes (`git commit -am 'Add some feature'`)
|
|
277
|
+
7. Push to the branch (`git push origin my-new-feature`)
|
|
278
|
+
8. Create new Pull Request
|
|
279
|
+
|
|
280
|
+
### Adding New Package Types
|
|
281
|
+
|
|
282
|
+
To add support for a new package type:
|
|
283
|
+
|
|
284
|
+
1. Update `purl-types.json` with the new type configuration
|
|
285
|
+
2. Add registry URL patterns if applicable
|
|
286
|
+
3. Add type-specific validation rules if needed in `lib/purl/package_url.rb`
|
|
287
|
+
4. Add tests for the new functionality
|
|
288
|
+
|
|
289
|
+
## License
|
|
290
|
+
|
|
291
|
+
This gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
292
|
+
|
|
293
|
+
## Changelog
|
|
294
|
+
|
|
295
|
+
See [CHANGELOG.md](CHANGELOG.md) for a detailed history of changes and releases.
|
|
36
296
|
|
|
37
297
|
## Code of Conduct
|
|
38
298
|
|
|
39
|
-
Everyone interacting in the Purl project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [
|
|
299
|
+
Everyone interacting in the Purl project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [Contributor Covenant Code of Conduct](CODE_OF_CONDUCT.md).
|