w3c_api 0.1.2 → 0.1.3

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.
data/lib/w3c_api/cli.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'thor'
4
4
  require_relative 'commands/specification'
5
+ require_relative 'commands/specification_version'
5
6
  require_relative 'commands/group'
6
7
  require_relative 'commands/user'
7
8
  require_relative 'commands/translation'
@@ -17,6 +18,9 @@ module W3cApi
17
18
  desc 'specification SUBCOMMAND ...ARGS', 'Work with W3C specifications'
18
19
  subcommand 'specification', Commands::Specification
19
20
 
21
+ desc 'specification_version SUBCOMMAND ...ARGS', 'Work with W3C specification versions'
22
+ subcommand 'specification_version', Commands::SpecificationVersion
23
+
20
24
  desc 'group SUBCOMMAND ...ARGS', 'Work with W3C groups'
21
25
  subcommand 'group', Commands::Group
22
26
 
@@ -22,8 +22,12 @@ module W3cApi
22
22
  end
23
23
 
24
24
  def specification_version(shortname, version, options = {})
25
- fetch_resource(:specification_resource_version_resource,
26
- shortname: shortname, version: version, **options)
25
+ fetch_resource(
26
+ :specification_resource_version_resource,
27
+ shortname: shortname,
28
+ version: version,
29
+ **options
30
+ )
27
31
  end
28
32
 
29
33
  def specifications_by_status(status, options = {})
@@ -37,6 +41,16 @@ module W3cApi
37
41
  end
38
42
  end
39
43
 
44
+ def specification_version_editors(shortname, version, options = {})
45
+ fetch_resource(:specification_version_editors_index,
46
+ shortname: shortname, version: version, **options)
47
+ end
48
+
49
+ def specification_version_deliverers(shortname, version, options = {})
50
+ fetch_resource(:specification_version_deliverers_index,
51
+ shortname: shortname, version: version, **options)
52
+ end
53
+
40
54
  # Series methods
41
55
  def series(options = {})
42
56
  fetch_resource(:serie_index, **options)
@@ -51,6 +65,11 @@ module W3cApi
51
65
  shortname: shortname, **options)
52
66
  end
53
67
 
68
+ def series_current_specification(shortname, options = {})
69
+ fetch_resource(:serie_current_specification_resource,
70
+ shortname: shortname, **options)
71
+ end
72
+
54
73
  # Group methods
55
74
  def groups(options = {})
56
75
  fetch_resource(:group_index, **options)
@@ -107,8 +126,8 @@ module W3cApi
107
126
  fetch_resource(:ecosystem_index, **options)
108
127
  end
109
128
 
110
- def ecosystem(id, options = {})
111
- fetch_resource(:ecosystem_resource, id: id, **options)
129
+ def ecosystem(shortname, options = {})
130
+ fetch_resource(:ecosystem_resource, shortname: shortname, **options)
112
131
  end
113
132
 
114
133
  %w[groups evangelists member_organizations].each do |resource|
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'thor'
4
+ require_relative 'output_formatter'
5
+
6
+ module W3cApi
7
+ module Commands
8
+ class SpecificationVersion < Thor
9
+ include OutputFormatter
10
+
11
+ desc 'editors', 'Fetch editors of a specification version'
12
+ option :shortname, type: :string, required: true, desc: 'Specification shortname'
13
+ option :version, type: :string, required: true, desc: 'Specification version'
14
+ option :format, type: :string, default: 'yaml', enum: %w[json yaml], desc: 'Output format'
15
+ def editors
16
+ client = W3cApi::Client.new
17
+ result = client.specification_version_editors(options[:shortname], options[:version])
18
+ output_results(result, options[:format])
19
+ rescue StandardError => e
20
+ puts "Error: #{e.message}"
21
+ exit 1
22
+ end
23
+
24
+ desc 'deliverers', 'Fetch deliverers (working groups) of a specification version'
25
+ option :shortname, type: :string, required: true, desc: 'Specification shortname'
26
+ option :version, type: :string, required: true, desc: 'Specification version'
27
+ option :format, type: :string, default: 'yaml', enum: %w[json yaml], desc: 'Output format'
28
+ def deliverers
29
+ client = W3cApi::Client.new
30
+ result = client.specification_version_deliverers(options[:shortname], options[:version])
31
+ output_results(result, options[:format])
32
+ rescue StandardError => e
33
+ puts "Error: #{e.message}"
34
+ exit 1
35
+ end
36
+ end
37
+ end
38
+ end
data/lib/w3c_api/hal.rb CHANGED
@@ -30,8 +30,10 @@ module W3cApi
30
30
  private
31
31
 
32
32
  # Common pagination query parameters
33
- PAGINATION_PARAMS = { 'page' => '{page}',
34
- 'items' => '{items}' }.freeze
33
+ PAGINATION_PARAMS = {
34
+ 'page' => '{page}',
35
+ 'items' => '{items}'
36
+ }.freeze
35
37
 
36
38
  # Helper method to add index endpoints with pagination
37
39
  def add_index_endpoint(id, url, model, query_params = PAGINATION_PARAMS)
@@ -46,126 +48,107 @@ module W3cApi
46
48
 
47
49
  # Helper method to add resource endpoints
48
50
  def add_resource_endpoint(id, url, model)
49
- register.add_endpoint(id: id, type: :resource, url: url, model: model)
51
+ register.add_endpoint(
52
+ id: id,
53
+ type: :resource,
54
+ url: url,
55
+ model: model
56
+ )
50
57
  end
51
58
 
52
- # Helper method to add nested index endpoints for a parent resource
53
- def add_nested_index_endpoints(parent, parent_id_param, nested_configs)
54
- nested_configs.each do |config|
55
- # Convert plural parent to singular for endpoint naming
56
- singular_parent = parent.end_with?('s') ? parent[0..-2] : parent
57
- id = "#{singular_parent}_#{config[:name]}_index".to_sym
58
- url = "/#{parent}/#{parent_id_param}/#{config[:path]}"
59
- add_index_endpoint(id, url, config[:model])
59
+ # Helper method to add nested index endpoints
60
+ def add_nested_index_endpoints(parent_resource, parent_id_param, endpoints)
61
+ endpoints.each do |endpoint|
62
+ add_index_endpoint(
63
+ :"#{parent_resource}_#{endpoint[:name]}_index",
64
+ "/#{parent_resource}/#{parent_id_param}/#{endpoint[:path]}",
65
+ endpoint[:model]
66
+ )
60
67
  end
61
68
  end
62
69
 
70
+ # Helper method to add individual nested endpoints
71
+ def add_nested_endpoint(parent_resource, parent_id_param, endpoint_name, endpoint_path, model)
72
+ add_index_endpoint(
73
+ :"#{parent_resource}_#{endpoint_name}_index",
74
+ "/#{parent_resource}/#{parent_id_param}/#{endpoint_path}",
75
+ model
76
+ )
77
+ end
78
+
63
79
  def setup
64
- # Affiliation endpoints
80
+ # Specification endpoints
65
81
  add_index_endpoint(
66
- :affiliation_index,
67
- '/affiliations',
68
- Models::AffiliationIndex
82
+ :specification_index,
83
+ '/specifications',
84
+ Models::SpecificationIndex
69
85
  )
70
86
  add_resource_endpoint(
71
- :affiliation_resource,
72
- '/affiliations/{id}',
73
- Models::Affiliation
74
- )
75
- add_index_endpoint(
76
- :affiliation_participants_index,
77
- '/affiliations/{id}/participants',
78
- Models::ParticipantIndex
87
+ :specification_resource,
88
+ '/specifications/{shortname}',
89
+ Models::Specification
79
90
  )
80
91
  add_index_endpoint(
81
- :affiliation_participations_index,
82
- '/affiliations/{id}/participations',
83
- Models::ParticipationIndex
92
+ :specification_by_status_index,
93
+ '/specifications',
94
+ Models::SpecificationIndex,
95
+ { 'status' => '{status}', **PAGINATION_PARAMS }
84
96
  )
85
97
 
86
- # register.add_endpoint(
87
- # id: :charter_resource,
88
- # type: :resource,
89
- # url: '/charters/{id}',
90
- # model: Models::Charter
91
- # )
92
-
93
- # Ecosystem endpoints
98
+ # Specification version endpoints
94
99
  add_index_endpoint(
95
- :ecosystem_index,
96
- '/ecosystems',
97
- Models::EcosystemIndex
100
+ :specification_resource_version_index,
101
+ '/specifications/{shortname}/versions',
102
+ Models::SpecVersionIndex
98
103
  )
99
104
  add_resource_endpoint(
100
- :ecosystem_resource,
101
- '/ecosystems/{id}',
102
- Models::Ecosystem
103
- )
104
- add_index_endpoint(
105
- :ecosystem_evangelists_index,
106
- '/ecosystems/{shortname}/evangelists',
107
- Models::EvangelistIndex
105
+ :specification_resource_version_resource,
106
+ '/specifications/{shortname}/versions/{version}',
107
+ Models::SpecVersion
108
108
  )
109
+
110
+ # Specification version editors and deliverers
109
111
  add_index_endpoint(
110
- :ecosystem_groups_index,
111
- '/ecosystems/{shortname}/groups',
112
- Models::GroupIndex
112
+ :specification_version_editors_index,
113
+ '/specifications/{shortname}/versions/{version}/editors',
114
+ Models::EditorIndex
113
115
  )
114
116
  add_index_endpoint(
115
- :ecosystem_member_organizations_index,
116
- '/ecosystems/{shortname}/member-organizations',
117
- Models::AffiliationIndex
117
+ :specification_version_deliverers_index,
118
+ '/specifications/{shortname}/versions/{version}/deliverers',
119
+ Models::DelivererIndex
118
120
  )
119
121
 
120
- # Group endpoints
122
+ # Specification version predecessors and successors
121
123
  add_index_endpoint(
122
- :group_index,
123
- '/groups',
124
- Models::GroupIndex
125
- )
126
- add_resource_endpoint(
127
- :group_resource,
128
- '/groups/{id}',
129
- Models::Group
124
+ :specification_version_predecessors_index,
125
+ '/specifications/{shortname}/versions/{version}/predecessors',
126
+ Models::SpecVersionPredecessorIndex
130
127
  )
131
- add_nested_index_endpoints(
132
- 'groups',
133
- '{id}', [
134
- { name: 'specifications', path: 'specifications',
135
- model: Models::SpecificationIndex },
136
- { name: 'charters', path: 'charters',
137
- model: Models::CharterIndex },
138
- { name: 'users', path: 'users',
139
- model: Models::UserIndex },
140
- { name: 'chairs', path: 'chairs',
141
- model: Models::ChairIndex },
142
- { name: 'team_contacts', path: 'teamcontacts',
143
- model: Models::TeamContactIndex },
144
- { name: 'participations', path: 'participations',
145
- model: Models::ParticipationIndex }
146
- ]
128
+ add_index_endpoint(
129
+ :specification_version_successors_index,
130
+ '/specifications/{shortname}/versions/{version}/successors',
131
+ Models::SpecVersionSuccessorIndex
147
132
  )
148
133
 
149
- # Participation endpoints
134
+ # Specification related endpoints
135
+ %w[supersedes superseded_by editors deliverers].each do |relation|
136
+ add_index_endpoint(
137
+ :"specification_#{relation}_index",
138
+ "/specifications/{shortname}/#{relation.tr('_', '-')}",
139
+ relation.include?('editor') ? Models::UserIndex : Models::GroupIndex
140
+ )
141
+ end
142
+
143
+ # TODO: Why is this endpoint needed? There already is /specifications/{shortname}...
150
144
  # register.add_endpoint(
151
- # id: :participation_index,
145
+ # id: :specification_by_shortname_index,
152
146
  # type: :index,
153
- # url: '/participations',
154
- # model: Models::ParticipationIndex
147
+ # url: '/specifications-by-shortname/{shortname}',
148
+ # model: Models::SpecificationIndex
155
149
  # )
156
150
 
157
- add_resource_endpoint(
158
- :participation_resource,
159
- '/participations/{id}',
160
- Models::Participation
161
- )
162
- add_index_endpoint(
163
- :participation_participants_index,
164
- '/participations/{id}/participants',
165
- Models::ParticipantIndex
166
- )
167
-
168
- # Serie endpoints
151
+ # Series endpoints
169
152
  add_index_endpoint(
170
153
  :serie_index,
171
154
  '/specification-series',
@@ -182,71 +165,59 @@ module W3cApi
182
165
  Models::SpecificationIndex
183
166
  )
184
167
 
185
- # Specification endpoints
168
+ # Group endpoints
186
169
  add_index_endpoint(
187
- :specification_index,
188
- '/specifications',
189
- Models::SpecificationIndex
170
+ :group_index,
171
+ '/groups',
172
+ Models::GroupIndex
190
173
  )
191
174
  add_resource_endpoint(
192
- :specification_resource,
193
- '/specifications/{shortname}',
194
- Models::Specification
195
- )
196
- add_index_endpoint(
197
- :specification_resource_version_index,
198
- '/specifications/{shortname}/versions',
199
- Models::SpecVersionIndex
175
+ :group_resource,
176
+ '/groups/{id}',
177
+ Models::Group
200
178
  )
201
179
  add_resource_endpoint(
202
- :specification_resource_version_resource,
203
- '/specifications/{shortname}/versions/{version}',
204
- Models::SpecVersion
180
+ :group_by_type_shortname_resource,
181
+ '/groups/{type}/{shortname}',
182
+ Models::Group
205
183
  )
206
184
  add_index_endpoint(
207
- :specification_version_predecessors_index,
208
- '/specifications/{shortname}/versions/{version}/predecessors',
209
- Models::SpecVersionIndex
185
+ :group_by_type_index,
186
+ '/groups/{type}',
187
+ Models::GroupIndex
210
188
  )
189
+ # Group nested endpoints
211
190
  add_index_endpoint(
212
- :specification_version_successors_index,
213
- '/specifications/{shortname}/versions/{version}/successors',
214
- Models::SpecVersionIndex
191
+ :group_specifications_index,
192
+ '/groups/{id}/specifications',
193
+ Models::SpecificationIndex
215
194
  )
216
195
  add_index_endpoint(
217
- :specification_by_status_index,
218
- '/specifications-by-status/{status}',
219
- Models::SpecificationIndex
196
+ :group_users_index,
197
+ '/groups/{id}/users',
198
+ Models::UserIndex
220
199
  )
221
200
  add_index_endpoint(
222
- :specification_supersedes_index,
223
- '/specifications/{shortname}/supersedes',
224
- Models::SpecificationIndex
201
+ :group_charters_index,
202
+ '/groups/{id}/charters',
203
+ Models::CharterIndex
225
204
  )
226
205
  add_index_endpoint(
227
- :specification_superseded_by_index,
228
- '/specifications/{shortname}/superseded',
229
- Models::SpecificationIndex
206
+ :group_chairs_index,
207
+ '/groups/{id}/chairs',
208
+ Models::ChairIndex
230
209
  )
231
210
  add_index_endpoint(
232
- :specification_version_editors_index,
233
- '/specifications/{shortname}/version/{version}/editors',
234
- Models::UserIndex
211
+ :group_team_contacts_index,
212
+ '/groups/{id}/teamcontacts',
213
+ Models::TeamContactIndex
235
214
  )
236
215
  add_index_endpoint(
237
- :specification_version_deliverers_index,
238
- '/specifications/{shortname}/version/{version}/deliverers',
239
- Models::UserIndex
216
+ :group_participations_index,
217
+ '/groups/{id}/participations',
218
+ Models::ParticipationIndex
240
219
  )
241
220
 
242
- # TODO: Why is this endpoint needed? There already is /specifications/{shortname}...
243
- # register.add_endpoint(
244
- # id: :specification_by_shortname_index,
245
- # type: :index,
246
- # url: '/specifications-by-shortname/{shortname}',
247
- # model: Models::SpecificationIndex
248
- # )
249
-
250
221
  # Translation endpoints
251
222
  add_index_endpoint(
252
223
  :translation_index,
@@ -272,22 +243,102 @@ module W3cApi
272
243
  '/users/{hash}',
273
244
  Models::User
274
245
  )
275
- add_nested_index_endpoints(
276
- 'users',
277
- '{hash}', [
278
- { name: 'groups', path: 'groups',
279
- model: Models::GroupIndex },
280
- { name: 'affiliations', path: 'affiliations',
281
- model: Models::AffiliationIndex },
282
- { name: 'participations', path: 'participations',
283
- model: Models::ParticipationIndex },
284
- { name: 'chair_of_groups', path: 'chair-of-groups',
285
- model: Models::GroupIndex },
286
- { name: 'team_contact_of_groups', path: 'team-contact-of-groups',
287
- model: Models::GroupIndex },
288
- { name: 'specifications', path: 'specifications',
289
- model: Models::SpecificationIndex }
290
- ]
246
+
247
+ # User nested endpoints
248
+ add_index_endpoint(
249
+ :user_groups_index,
250
+ '/users/{hash}/groups',
251
+ Models::GroupIndex
252
+ )
253
+ add_index_endpoint(
254
+ :user_affiliations_index,
255
+ '/users/{hash}/affiliations',
256
+ Models::AffiliationIndex
257
+ )
258
+ add_index_endpoint(
259
+ :user_participations_index,
260
+ '/users/{hash}/participations',
261
+ Models::ParticipationIndex
262
+ )
263
+ add_index_endpoint(
264
+ :user_chair_of_groups_index,
265
+ '/users/{hash}/chair-of-groups',
266
+ Models::GroupIndex
267
+ )
268
+ add_index_endpoint(
269
+ :user_team_contact_of_groups_index,
270
+ '/users/{hash}/team-contact-of-groups',
271
+ Models::GroupIndex
272
+ )
273
+ add_index_endpoint(
274
+ :user_specifications_index,
275
+ '/users/{hash}/specifications',
276
+ Models::SpecificationIndex
277
+ )
278
+
279
+ # Affiliation endpoints
280
+ add_index_endpoint(
281
+ :affiliation_index,
282
+ '/affiliations',
283
+ Models::AffiliationIndex
284
+ )
285
+ add_resource_endpoint(
286
+ :affiliation_resource,
287
+ '/affiliations/{id}',
288
+ Models::Affiliation
289
+ )
290
+
291
+ # Affiliation nested endpoints
292
+ add_index_endpoint(
293
+ :affiliation_participants_index,
294
+ '/affiliations/{id}/participants',
295
+ Models::ParticipantIndex
296
+ )
297
+ add_index_endpoint(
298
+ :affiliation_participations_index,
299
+ '/affiliations/{id}/participations',
300
+ Models::ParticipationIndex
301
+ )
302
+
303
+ # Ecosystem endpoints
304
+ add_index_endpoint(
305
+ :ecosystem_index,
306
+ '/ecosystems',
307
+ Models::EcosystemIndex
308
+ )
309
+ add_resource_endpoint(
310
+ :ecosystem_resource,
311
+ '/ecosystems/{shortname}',
312
+ Models::Ecosystem
313
+ )
314
+
315
+ # Ecosystem nested endpoints
316
+ add_index_endpoint(
317
+ :ecosystem_groups_index,
318
+ '/ecosystems/{shortname}/groups',
319
+ Models::GroupIndex
320
+ )
321
+ add_index_endpoint(
322
+ :ecosystem_evangelists_index,
323
+ '/ecosystems/{shortname}/evangelists',
324
+ Models::EvangelistIndex
325
+ )
326
+ add_index_endpoint(
327
+ :ecosystem_member_organizations_index,
328
+ '/ecosystems/{shortname}/member-organizations',
329
+ Models::AffiliationIndex
330
+ )
331
+
332
+ # Participation endpoints
333
+ add_resource_endpoint(
334
+ :participation_resource,
335
+ '/participations/{id}',
336
+ Models::Participation
337
+ )
338
+ add_index_endpoint(
339
+ :participation_participants_index,
340
+ '/participations/{id}/participants',
341
+ Models::ParticipantIndex
291
342
  )
292
343
  end
293
344
  end
@@ -70,6 +70,18 @@ module W3cApi
70
70
  map key.to_s.tr('_', '-'), to: key
71
71
  end
72
72
  end
73
+
74
+ def participants(client = nil)
75
+ return nil unless client
76
+
77
+ client.affiliation_participants(id)
78
+ end
79
+
80
+ def participations(client = nil)
81
+ return nil unless client
82
+
83
+ client.affiliation_participations(id)
84
+ end
73
85
  end
74
86
  end
75
87
  end
@@ -4,6 +4,7 @@ require_relative 'affiliation'
4
4
 
5
5
  module W3cApi
6
6
  module Models
7
+ # Represents a collection of W3C affiliations.
7
8
  class AffiliationIndex < Lutaml::Hal::Page
8
9
  hal_link :affiliations, key: 'affiliations', realize_class: 'Affiliation', collection: true
9
10
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'group'
4
+
5
+ module W3cApi
6
+ module Models
7
+ # Collection of deliverers (working groups)
8
+ class DelivererIndex < Lutaml::Hal::Page
9
+ hal_link :deliverers, key: 'deliverers', realize_class: 'Group', collection: true
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'user'
4
+
5
+ module W3cApi
6
+ module Models
7
+ # Collection of editors
8
+ class EditorIndex < Lutaml::Hal::Page
9
+ hal_link :editors, key: 'editors', realize_class: 'User', collection: true
10
+ end
11
+ end
12
+ end
@@ -55,7 +55,7 @@ module W3cApi
55
55
  module Models
56
56
  # Group model representing a W3C working group
57
57
  class Group < Lutaml::Hal::Resource
58
- attribute :id, :string
58
+ attribute :id, :integer
59
59
  attribute :type, :string
60
60
  attribute :name, :string
61
61
  attribute :is_closed, :boolean
@@ -89,6 +89,30 @@ module W3cApi
89
89
  map key.to_s.tr('_', '-'), to: key
90
90
  end
91
91
  end
92
+
93
+ def users(client = nil)
94
+ return nil unless client
95
+
96
+ client.group_users(id)
97
+ end
98
+
99
+ def specifications(client = nil)
100
+ return nil unless client
101
+
102
+ client.group_specifications(id)
103
+ end
104
+
105
+ def chairs(client = nil)
106
+ return nil unless client
107
+
108
+ client.group_chairs(id)
109
+ end
110
+
111
+ def team_contacts(client = nil)
112
+ return nil unless client
113
+
114
+ client.group_team_contacts(id)
115
+ end
92
116
  end
93
117
  end
94
118
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module W3cApi
4
+ module Models
5
+ # Collection wrapper for groups
6
+ class Groups
7
+ include Enumerable
8
+
9
+ attr_accessor :groups
10
+
11
+ def initialize(groups = [])
12
+ @groups = groups
13
+ end
14
+
15
+ def each(&block)
16
+ @groups.each(&block)
17
+ end
18
+
19
+ def first
20
+ @groups.first
21
+ end
22
+
23
+ def size
24
+ @groups.size
25
+ end
26
+
27
+ def empty?
28
+ @groups.empty?
29
+ end
30
+ end
31
+ end
32
+ end