raad-notams 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 3ad7f10b948f4896bdba3b4c377c4e307ec9a2ea2409d8405faccd29d9ea1798
4
+ data.tar.gz: 4a312b0b092f60cd90f45dda6fe1915143730dad9b3029f4f7f671b5dcb57fe1
5
+ SHA512:
6
+ metadata.gz: e0def67e4235df97cb1ea33353a62ff45543a3ec6b99b0c6e0046e096933db4fa1bc4223d57ab4df875e8703f8e944c6e842a002303dc8b2e9537396cafbd5dd
7
+ data.tar.gz: 44e28fb891645cadb27ea7f282d2dc85e6c1d9589dcb5315baf6c12bf873b6ab66fd16b3cd6e605c0d008f2ce370155352f6bd674dad6ce976a111aba14af68f
data/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ # Changelog
2
+
3
+ ## [0.1.0] - 2025-05-01
4
+
5
+ - Initial release of the FaaNotams gem
6
+ - Added support for all NOTAM API endpoints
7
+ - Implemented search, search_by_airport, search_by_location, and search_by_feature methods
8
+ - Added validation for API parameters
9
+ - Set up basic documentation
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Your Name
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 ADDED
@@ -0,0 +1,102 @@
1
+ # FaaNotams
2
+
3
+ A Ruby gem for interacting with the FAA's Notice to Airmen (NOTAM) API.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'faa_notams'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ ```bash
16
+ $ bundle install
17
+ ```
18
+
19
+ Or install it yourself as:
20
+
21
+ ```bash
22
+ $ gem install faa_notams
23
+ ```
24
+
25
+ ## Usage
26
+
27
+ First, obtain your API credentials from the [FAA External API Portal](https://external-api.faa.gov/).
28
+
29
+ ### Basic Usage
30
+
31
+ ```ruby
32
+ require 'faa_notams'
33
+
34
+ # Initialize with client credentials
35
+ client = FaaNotams.new(
36
+ 'your_client_id',
37
+ 'your_client_secret'
38
+ )
39
+
40
+ # Or use environment variables
41
+ # export FAA_NOTAM_CLIENT_ID=your_client_id
42
+ # export FAA_NOTAM_CLIENT_SECRET=your_client_secret
43
+ client = FaaNotams.new
44
+
45
+ # Search for NOTAMs
46
+ results = client.search(
47
+ icao_location: 'KIAD',
48
+ page_size: 50,
49
+ page_num: 1
50
+ )
51
+
52
+ # Search by airport
53
+ results = client.search_by_airport('KIAD')
54
+ # or domestic code
55
+ results = client.search_by_airport('IAD')
56
+
57
+ # Search by geographic location
58
+ results = client.search_by_location(38.9445, -77.4558, 50)
59
+
60
+ # Search by feature type
61
+ results = client.search_by_feature('RWY')
62
+ ```
63
+
64
+ ### Available Search Parameters
65
+
66
+ The `search` method accepts the following parameters:
67
+
68
+ - `:response_format` - Format of the response ('aixm', 'geoJson', or 'aidap')
69
+ - `:icao_location` - ICAO location code (e.g., 'KIAD' for Dulles)
70
+ - `:domestic_location` - Domestic location code (e.g., 'IAD' for Dulles)
71
+ - `:notam_type` - The NOTAM type ('N' for New, 'R' for Replaced, or 'C' for Canceled)
72
+ - `:classification` - NOTAM classification ('INTL', 'MIL', 'DOM', 'LMIL', or 'FDC')
73
+ - `:notam_number` - The NOTAM number (e.g., 'CK0000/01')
74
+ - `:effective_start_date` - The effective start date (ISO 8601 format)
75
+ - `:effective_end_date` - The effective end date (ISO 8601 format)
76
+ - `:feature_type` - Feature type (e.g., 'RWY', 'TWY', 'AIRSPACE', etc.)
77
+ - `:location_longitude` - Location longitude (e.g., -151.24)
78
+ - `:location_latitude` - Location latitude (e.g., 60.57)
79
+ - `:location_radius` - Location radius in nautical miles (max: 100nm)
80
+ - `:last_updated_date` - Last updated date (ISO 8601 format)
81
+ - `:sort_by` - Field to sort by (e.g., 'icaoLocation', 'effectiveStartDate')
82
+ - `:sort_order` - Sort order ('Asc' or 'Desc')
83
+ - `:page_size` - Number of results per page (max: 1000, default: 50)
84
+ - `:page_num` - Page number (default: 1)
85
+
86
+ ## Development
87
+
88
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
89
+
90
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
91
+
92
+ ## Contributing
93
+
94
+ Bug reports and pull requests are welcome on GitHub at https://github.com/yourusername/faa_notams. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/yourusername/faa_notams/blob/main/CODE_OF_CONDUCT.md).
95
+
96
+ ## License
97
+
98
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
99
+
100
+ ## Code of Conduct
101
+
102
+ Everyone interacting in the FaaNotams project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/yourusername/faa_notams/blob/main/CODE_OF_CONDUCT.md).
@@ -0,0 +1,255 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'net/http'
4
+ require 'uri'
5
+ require 'json'
6
+
7
+ module FaaNotams
8
+ # Service to interact with FAA's Notice to Airmen (NOTAM) API
9
+ # https://external-api.faa.gov/notamapi
10
+ #
11
+ # This service provides access to FAA's NOTAM API, which contains real-time notification
12
+ # of any change in the National Airspace System (NAS).
13
+ class Service
14
+ BASE_URL = "https://external-api.faa.gov/notamapi/v1"
15
+
16
+ attr_reader :client_id, :client_secret
17
+
18
+ # Initialize the service with FAA API credentials
19
+ # @param client_id [String] FAA API client ID
20
+ # @param client_secret [String] FAA API client secret
21
+ def initialize(client_id = nil, client_secret = nil)
22
+ @client_id = client_id || ENV['FAA_NOTAM_CLIENT_ID']
23
+ @client_secret = client_secret || ENV['FAA_NOTAM_CLIENT_SECRET']
24
+
25
+ raise ArgumentError, "FAA NOTAM client_id is required" unless @client_id
26
+ raise ArgumentError, "FAA NOTAM client_secret is required" unless @client_secret
27
+ end
28
+
29
+ # =========================================================================
30
+ # NOTAM API Endpoints
31
+ # =========================================================================
32
+
33
+ # Search for NOTAMs based on various criteria
34
+ # @param options [Hash] Search criteria parameters
35
+ # @option options [String] :response_format Format of the response ('aixm', 'geoJson', or 'aidap') (default: 'geoJson')
36
+ # @option options [String] :icao_location ICAO location code (e.g., 'KIAD' for Dulles)
37
+ # @option options [String] :domestic_location Domestic location code (e.g., 'IAD' for Dulles)
38
+ # @option options [String] :notam_type The NOTAM type ('N' for New, 'R' for Replaced, or 'C' for Canceled)
39
+ # @option options [String] :classification NOTAM classification ('INTL', 'MIL', 'DOM', 'LMIL', or 'FDC')
40
+ # @option options [String] :notam_number The NOTAM number (e.g., 'CK0000/01')
41
+ # @option options [String] :effective_start_date The effective start date (ISO 8601 format)
42
+ # @option options [String] :effective_end_date The effective end date (ISO 8601 format)
43
+ # @option options [String] :feature_type Feature type (e.g., 'RWY', 'TWY', 'AIRSPACE', etc.)
44
+ # @option options [Float] :location_longitude Location longitude (e.g., -151.24)
45
+ # @option options [Float] :location_latitude Location latitude (e.g., 60.57)
46
+ # @option options [Float] :location_radius Location radius in nautical miles (max: 100nm)
47
+ # @option options [String] :last_updated_date Last updated date (ISO 8601 format)
48
+ # @option options [String] :sort_by Field to sort by (e.g., 'icaoLocation', 'effectiveStartDate')
49
+ # @option options [String] :sort_order Sort order ('Asc' or 'Desc')
50
+ # @option options [Integer] :page_size Number of results per page (max: 1000, default: 50)
51
+ # @option options [Integer] :page_num Page number (default: 1)
52
+ # @return [Hash] NOTAM search results
53
+ def search(options = {})
54
+ # Convert snake_case option keys to camelCase for the API
55
+ params = {}
56
+
57
+ # Handle response format separately (API expects 'responseFormat')
58
+ if options[:response_format]
59
+ params[:responseFormat] = validate_response_format(options[:response_format])
60
+ end
61
+
62
+ # Map option keys to API parameter names
63
+ param_mapping = {
64
+ icao_location: :icaoLocation,
65
+ domestic_location: :domesticLocation,
66
+ notam_type: :notamType,
67
+ classification: :classification,
68
+ notam_number: :notamNumber,
69
+ effective_start_date: :effectiveStartDate,
70
+ effective_end_date: :effectiveEndDate,
71
+ feature_type: :featureType,
72
+ location_longitude: :locationLongitude,
73
+ location_latitude: :locationLatitude,
74
+ location_radius: :locationRadius,
75
+ last_updated_date: :lastUpdatedDate,
76
+ sort_by: :sortBy,
77
+ sort_order: :sortOrder,
78
+ page_size: :pageSize,
79
+ page_num: :pageNum
80
+ }
81
+
82
+ # Process each key and transform to camelCase for API
83
+ param_mapping.each do |option_key, param_key|
84
+ if options.key?(option_key)
85
+ # Special validation for some parameters
86
+ value = case option_key
87
+ when :feature_type
88
+ validate_feature_type(options[option_key])
89
+ when :location_radius
90
+ validate_range(options[option_key], 0.1, 100, 'location_radius')
91
+ when :page_size
92
+ validate_range(options[option_key], 1, 1000, 'page_size')
93
+ when :page_num
94
+ validate_range(options[option_key], 1, nil, 'page_num')
95
+ when :sort_order
96
+ validate_enum(options[option_key], %w[Asc Desc], 'sort_order')
97
+ else
98
+ options[option_key]
99
+ end
100
+
101
+ params[param_key] = value
102
+ end
103
+ end
104
+
105
+ get("/search", params)
106
+ end
107
+
108
+ # Convenience method to search NOTAMs by airport code (ICAO or domestic)
109
+ # @param airport_code [String] Airport code (e.g., 'KIAD' for ICAO or 'IAD' for domestic)
110
+ # @param options [Hash] Additional search criteria
111
+ # @return [Hash] NOTAM search results
112
+ def search_by_airport(airport_code, options = {})
113
+ airport_code = airport_code.to_s.upcase
114
+
115
+ if airport_code.length == 3
116
+ options[:domestic_location] = airport_code
117
+ else
118
+ options[:icao_location] = airport_code
119
+ end
120
+
121
+ search(options)
122
+ end
123
+
124
+ # Search NOTAMs by geographic location (latitude/longitude and radius)
125
+ # @param latitude [Float] Location latitude
126
+ # @param longitude [Float] Location longitude
127
+ # @param radius [Float] Search radius in nautical miles (default: 50, max: 100)
128
+ # @param options [Hash] Additional search criteria
129
+ # @return [Hash] NOTAM search results
130
+ def search_by_location(latitude, longitude, radius = 50, options = {})
131
+ options[:location_latitude] = latitude
132
+ options[:location_longitude] = longitude
133
+ options[:location_radius] = radius
134
+
135
+ search(options)
136
+ end
137
+
138
+ # Search for NOTAMs affecting a specific feature type
139
+ # @param feature_type [String] Feature type (e.g., 'RWY', 'TWY', 'AIRSPACE', etc.)
140
+ # @param options [Hash] Additional search criteria
141
+ # @return [Hash] NOTAM search results
142
+ def search_by_feature(feature_type, options = {})
143
+ options[:feature_type] = validate_feature_type(feature_type)
144
+ search(options)
145
+ end
146
+
147
+ # =========================================================================
148
+ # Helper Methods
149
+ # =========================================================================
150
+
151
+ private
152
+
153
+ # Make a GET request to the NOTAM API
154
+ # @param path [String] API endpoint path
155
+ # @param params [Hash] Query parameters
156
+ # @return [Hash] Parsed JSON response
157
+ def get(path, params = {})
158
+ uri = URI.parse("#{BASE_URL}#{path}")
159
+ uri.query = URI.encode_www_form(params) if params.any?
160
+
161
+ http = Net::HTTP.new(uri.host, uri.port)
162
+ http.use_ssl = true
163
+
164
+ request = Net::HTTP::Get.new(uri)
165
+ request['client_id'] = @client_id
166
+ request['client_secret'] = @client_secret
167
+ request['Accept'] = 'application/json'
168
+
169
+ response = http.request(request)
170
+ handle_response(response)
171
+ end
172
+
173
+ # Handle API response
174
+ # @param response [Net::HTTPResponse] HTTP response from the API
175
+ # @return [Hash] Parsed JSON response
176
+ # @raise [RuntimeError] If the response is not successful
177
+ def handle_response(response)
178
+ case response.code.to_i
179
+ when 200
180
+ JSON.parse(response.body)
181
+ when 400
182
+ raise "Bad request: #{response.body}"
183
+ when 401
184
+ raise "Unauthorized: Invalid API credentials"
185
+ when 404
186
+ raise "Not found: Requested resource not available"
187
+ when 500
188
+ raise "Internal server error: #{response.body}"
189
+ else
190
+ raise "Unexpected response (#{response.code}): #{response.body}"
191
+ end
192
+ end
193
+
194
+ # Validate response format
195
+ # @param format [String] Format value to validate
196
+ # @return [String] Validated format
197
+ # @raise [ArgumentError] If format is not valid
198
+ def validate_response_format(format)
199
+ valid_formats = %w[aixm geoJson aidap]
200
+ format = format.to_s.downcase
201
+
202
+ # Special handling for 'geojson' vs 'geoJson' formats
203
+ format = 'geoJson' if format == 'geojson'
204
+
205
+ unless valid_formats.include?(format)
206
+ raise ArgumentError, "Invalid response format. Must be one of: #{valid_formats.join(', ')}"
207
+ end
208
+
209
+ format
210
+ end
211
+
212
+ # Validate that a value is within a specific range
213
+ # @param value [Numeric] Value to validate
214
+ # @param min [Numeric] Minimum allowed value
215
+ # @param max [Numeric] Maximum allowed value (or nil for no upper limit)
216
+ # @param param_name [String] Parameter name for error messages
217
+ # @return [Numeric] Validated value
218
+ # @raise [ArgumentError] If value is not within range
219
+ def validate_range(value, min, max, param_name)
220
+ value = value.to_f
221
+ if value < min || (max && value > max)
222
+ max_msg = max ? " and #{max}" : ""
223
+ raise ArgumentError, "Invalid #{param_name}. Must be between #{min}#{max_msg}."
224
+ end
225
+ value
226
+ end
227
+
228
+ # Validate that a value is within an enumeration
229
+ # @param value [String] Value to validate
230
+ # @param allowed_values [Array<String>] Allowed values
231
+ # @param param_name [String] Parameter name for error messages
232
+ # @return [String] Validated value
233
+ # @raise [ArgumentError] If value is not in allowed values
234
+ def validate_enum(value, allowed_values, param_name)
235
+ value = value.to_s
236
+ unless allowed_values.include?(value)
237
+ raise ArgumentError, "Invalid #{param_name}. Must be one of: #{allowed_values.join(', ')}"
238
+ end
239
+ value
240
+ end
241
+
242
+ # Validate feature type
243
+ # @param feature_type [String] Feature type to validate
244
+ # @return [String] Validated feature type
245
+ # @raise [ArgumentError] If feature type is not valid
246
+ def validate_feature_type(feature_type)
247
+ allowed_feature_types = %w[
248
+ RWY TWY APRON AD OBST NAV COM SVC AIRSPACE ODP SID STAR
249
+ CHART DATA DVA IAP VFP ROUTE SPECIAL SECURITY MILITARY INTERNATIONAL
250
+ ]
251
+
252
+ validate_enum(feature_type, allowed_feature_types, 'feature_type')
253
+ end
254
+ end
255
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FaaNotams
4
+ VERSION = "0.1.0"
5
+ end
data/lib/faa_notams.rb ADDED
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "faa_notams/version"
4
+ require_relative "faa_notams/service"
5
+
6
+ # FaaNotams - Ruby gem to interact with FAA's Notice to Airmen (NOTAM) API
7
+ # https://external-api.faa.gov/notamapi
8
+ #
9
+ # This gem provides access to FAA's NOTAM API, which contains real-time notification
10
+ # of any change in the National Airspace System (NAS).
11
+ module FaaNotams
12
+ class Error < StandardError; end
13
+
14
+ # Convenience method to create a new service instance
15
+ # @param client_id [String] FAA API client ID
16
+ # @param client_secret [String] FAA API client secret
17
+ # @return [FaaNotams::Service] A new service instance
18
+ def self.new(client_id = nil, client_secret = nil)
19
+ Service.new(client_id, client_secret)
20
+ end
21
+ end
metadata ADDED
@@ -0,0 +1,151 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: raad-notams
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - JP Silvashy
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 2025-05-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: bundler
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '2.0'
19
+ type: :development
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '2.0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: rake
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '13.0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '13.0'
40
+ - !ruby/object:Gem::Dependency
41
+ name: rspec
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '3.0'
47
+ type: :development
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '3.0'
54
+ - !ruby/object:Gem::Dependency
55
+ name: rubocop
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '1.21'
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '1.21'
68
+ - !ruby/object:Gem::Dependency
69
+ name: yard
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '0.9'
75
+ type: :development
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '0.9'
82
+ - !ruby/object:Gem::Dependency
83
+ name: webmock
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '3.14'
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '3.14'
96
+ - !ruby/object:Gem::Dependency
97
+ name: vcr
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '6.0'
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '6.0'
110
+ description: A Ruby gem to interact with the FAA's NOTAM API, which provides real-time
111
+ notifications of changes in the National Airspace System (NAS).
112
+ email:
113
+ - jp@raad.com
114
+ - jpsilvashy@gmail.com
115
+ executables: []
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - CHANGELOG.md
120
+ - LICENSE
121
+ - README.md
122
+ - lib/faa_notams.rb
123
+ - lib/faa_notams/service.rb
124
+ - lib/faa_notams/version.rb
125
+ homepage: https://github.com/raad-labs/notams
126
+ licenses:
127
+ - MIT
128
+ metadata:
129
+ homepage_uri: https://github.com/raad-labs/notams
130
+ source_code_uri: https://github.com/raad-labs/notams
131
+ changelog_uri: https://github.com/raad-labs/notams/blob/main/CHANGELOG.md
132
+ documentation_uri: https://www.rubydoc.info/gems/raad-notams
133
+ allowed_push_host: https://rubygems.org
134
+ rdoc_options: []
135
+ require_paths:
136
+ - lib
137
+ required_ruby_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ version: 2.6.0
142
+ required_rubygems_version: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ requirements: []
148
+ rubygems_version: 3.6.3
149
+ specification_version: 4
150
+ summary: Ruby wrapper for the FAA Notice to Airmen (NOTAM) API
151
+ test_files: []