@@ -50,14 +50,14 @@ export const generateOpenAPISpec = () => {
5050 in : 'query' ,
5151 description : 'Sort field (example: ViewCount)' ,
5252 required : false ,
53- schema : { type : 'string' }
53+ schema : { type : 'string' , default : 'ViewCount' }
5454 } ,
5555 {
5656 name : 'sortOrder' ,
5757 in : 'query' ,
58- description : 'Sort order (example: asc/desc)' ,
58+ description : 'Sort order (asc/desc)' ,
5959 required : false ,
60- schema : { type : 'string' }
60+ schema : { type : 'string' , enum : [ 'asc' , 'desc' ] , default : 'desc' }
6161 }
6262 ] ,
6363 responses : {
@@ -71,7 +71,7 @@ export const generateOpenAPISpec = () => {
7171 success : { type : 'boolean' , example : true } ,
7272 data : {
7373 type : 'array' ,
74- items : { type : 'object ' }
74+ items : { $ref : '#/components/schemas/Song ' }
7575 } ,
7676 pagination : {
7777 type : 'object' ,
@@ -98,6 +98,60 @@ export const generateOpenAPISpec = () => {
9898 }
9999 }
100100 } ,
101+ '/api/v1/songs/{id}' : {
102+ get : {
103+ tags : [ 'Songs' ] ,
104+ summary : 'Get song by ID' ,
105+ description : 'Get the details of a specific song including lyrics using the SongID. Increments the ViewCount.' ,
106+ parameters : [
107+ {
108+ name : 'id' ,
109+ in : 'path' ,
110+ description : 'Song ID (example: SNG-0000025)' ,
111+ required : true ,
112+ schema : { type : 'string' }
113+ }
114+ ] ,
115+ responses : {
116+ '200' : {
117+ description : 'Song retrieved successfully' ,
118+ content : {
119+ 'application/json' : {
120+ schema : {
121+ type : 'object' ,
122+ properties : {
123+ success : { type : 'boolean' , example : true } ,
124+ data : { $ref : '#/components/schemas/FullSong' }
125+ }
126+ }
127+ }
128+ }
129+ } ,
130+ '404' : {
131+ description : 'Song not found' ,
132+ content : {
133+ 'application/json' : {
134+ schema : {
135+ type : 'object' ,
136+ properties : {
137+ success : { type : 'boolean' , example : false } ,
138+ message : { type : 'string' , example : 'Song not found' }
139+ }
140+ }
141+ }
142+ }
143+ } ,
144+ '500' : {
145+ description : 'Internal server error' ,
146+ content : {
147+ 'application/json' : {
148+ schema : { $ref : '#/components/schemas/ErrorResponse' }
149+ }
150+ }
151+ }
152+ }
153+ }
154+ } ,
101155 '/api/v1/songs/health' : {
102156 get : {
103157 tags : [ 'Songs' ] ,
@@ -106,35 +160,245 @@ export const generateOpenAPISpec = () => {
106160 responses : {
107161 '200' : {
108162 description : 'Service is healthy' ,
163+ content : {
164+ 'application/json' : {
165+ schema : { $ref : '#/components/schemas/HealthCheck' }
166+ }
167+ }
168+ }
169+ }
170+ }
171+ } ,
172+ '/api/v1/artists' : {
173+ get : {
174+ tags : [ 'Artists' ] ,
175+ summary : 'Get all artists' ,
176+ description : 'Get a paginated list of all artists with optional filters' ,
177+ parameters : [
178+ {
179+ name : 'page' ,
180+ in : 'query' ,
181+ description : 'Page number' ,
182+ required : false ,
183+ schema : { type : 'string' , example : '1' }
184+ } ,
185+ {
186+ name : 'limit' ,
187+ in : 'query' ,
188+ description : 'Items per page' ,
189+ required : false ,
190+ schema : { type : 'string' , example : '10' }
191+ } ,
192+ {
193+ name : 'artistId' ,
194+ in : 'query' ,
195+ description : 'Filter by artist ID (example: ART-00001)' ,
196+ required : false ,
197+ schema : { type : 'string' }
198+ } ,
199+ {
200+ name : 'search' ,
201+ in : 'query' ,
202+ description : 'Search in artist names (English or Sinhala)' ,
203+ required : false ,
204+ schema : { type : 'string' }
205+ }
206+ ] ,
207+ responses : {
208+ '200' : {
209+ description : 'Artists retrieved successfully' ,
109210 content : {
110211 'application/json' : {
111212 schema : {
112213 type : 'object' ,
113214 properties : {
114- status : { type : 'string' , example : 'OK' } ,
115- timestamp : { type : 'string' , example : '2025-11-08T10:30:00.000Z' } ,
116- environment : { type : 'string' , example : 'Production' } ,
117- version : { type : 'string' , example : '1.0.0' }
215+ success : { type : 'boolean' , example : true } ,
216+ data : {
217+ type : 'array' ,
218+ items : { $ref : '#/components/schemas/Artist' }
219+ } ,
220+ pagination : {
221+ type : 'object' ,
222+ properties : {
223+ page : { type : 'number' , example : 1 } ,
224+ limit : { type : 'number' , example : 10 } ,
225+ total : { type : 'number' , example : 50 } ,
226+ totalPages : { type : 'number' , example : 5 }
227+ }
228+ }
229+ }
230+ }
231+ }
232+ }
233+ } ,
234+ '500' : {
235+ description : 'Internal server error' ,
236+ content : {
237+ 'application/json' : {
238+ schema : { $ref : '#/components/schemas/ErrorResponse' }
239+ }
240+ }
241+ }
242+ }
243+ }
244+ } ,
245+ '/api/v1/artists/health' : {
246+ get : {
247+ tags : [ 'Artists' ] ,
248+ summary : 'Check artists service health' ,
249+ description : 'Health check endpoint for the artists service' ,
250+ responses : {
251+ '200' : {
252+ description : 'Service is healthy' ,
253+ content : {
254+ 'application/json' : {
255+ schema : { $ref : '#/components/schemas/HealthCheck' }
256+ }
257+ }
258+ }
259+ }
260+ }
261+ } ,
262+ '/api/v1/lyrics/{id}' : {
263+ get : {
264+ tags : [ 'Lyrics' ] ,
265+ summary : 'Get lyrics by ID' ,
266+ description : 'Get the lyrics for a specific song using the LyricID' ,
267+ parameters : [
268+ {
269+ name : 'id' ,
270+ in : 'path' ,
271+ description : 'Lyric ID (example: LYR-0000025)' ,
272+ required : true ,
273+ schema : { type : 'string' }
274+ }
275+ ] ,
276+ responses : {
277+ '200' : {
278+ description : 'Lyrics retrieved successfully' ,
279+ content : {
280+ 'application/json' : {
281+ schema : {
282+ type : 'object' ,
283+ properties : {
284+ success : { type : 'boolean' , example : true } ,
285+ data : { $ref : '#/components/schemas/Lyric' }
118286 }
119287 }
120288 }
121289 }
290+ } ,
291+ '404' : {
292+ description : 'Lyrics not found' ,
293+ content : {
294+ 'application/json' : {
295+ schema : {
296+ type : 'object' ,
297+ properties : {
298+ success : { type : 'boolean' , example : false } ,
299+ message : { type : 'string' , example : 'Lyrics not found' }
300+ }
301+ }
302+ }
303+ }
304+ } ,
305+ '500' : {
306+ description : 'Internal server error' ,
307+ content : {
308+ 'application/json' : {
309+ schema : { $ref : '#/components/schemas/ErrorResponse' }
310+ }
311+ }
312+ }
313+ }
314+ }
315+ } ,
316+ '/api/v1/lyrics/health' : {
317+ get : {
318+ tags : [ 'Lyrics' ] ,
319+ summary : 'Check lyrics service health' ,
320+ description : 'Health check endpoint for the lyrics service' ,
321+ responses : {
322+ '200' : {
323+ description : 'Service is healthy' ,
324+ content : {
325+ 'application/json' : {
326+ schema : { $ref : '#/components/schemas/HealthCheck' }
327+ }
328+ }
122329 }
123330 }
124331 }
125332 }
126333 } ,
127334 components : {
128335 schemas : {
336+ Song : {
337+ type : 'object' ,
338+ properties : {
339+ ID : { type : 'number' , example : 1 } ,
340+ SongID : { type : 'string' , example : 'SNG-00001' } ,
341+ SongName : { type : 'string' , example : 'Beautiful Song' } ,
342+ SongNameSinhala : { type : 'string' , example : 'ලස්සන ගීතය' } ,
343+ ArtistID : { type : 'string' , example : 'ART-00001' } ,
344+ Duration : { type : 'number' , example : 240 } ,
345+ ReleaseYear : { type : 'number' , example : 2024 } ,
346+ Composer : { type : 'string' , example : 'John Doe' } ,
347+ Lyricist : { type : 'string' , example : 'Jane Smith' } ,
348+ ViewCount : { type : 'number' , example : 1000 }
349+ }
350+ } ,
351+ FullSong : {
352+ type : 'object' ,
353+ properties : {
354+ ID : { type : 'number' , example : 1 } ,
355+ SongID : { type : 'string' , example : 'SNG-00001' } ,
356+ SongName : { type : 'string' , example : 'Beautiful Song' } ,
357+ SongNameSinhala : { type : 'string' , example : 'ලස්සන ගීතය' } ,
358+ ArtistID : { type : 'string' , example : 'ART-00001' } ,
359+ Duration : { type : 'number' , example : 240 } ,
360+ ReleaseYear : { type : 'number' , example : 2024 } ,
361+ Composer : { type : 'string' , example : 'John Doe' } ,
362+ Lyricist : { type : 'string' , example : 'Jane Smith' } ,
363+ LyricsContent : { type : 'string' , example : 'Full lyrics in English...' } ,
364+ LyricsContentSinhala : { type : 'string' , example : 'සම්පූර්ණ ගී පද...' } ,
365+ ViewCount : { type : 'number' , example : 1000 }
366+ }
367+ } ,
368+ Artist : {
369+ type : 'object' ,
370+ properties : {
371+ ID : { type : 'number' , example : 1 } ,
372+ ArtistID : { type : 'string' , example : 'ART-00001' } ,
373+ ArtistName : { type : 'string' , example : 'John Doe' } ,
374+ ArtistNameSinhala : { type : 'string' , example : 'ජෝන් ඩෝ' }
375+ }
376+ } ,
377+ Lyric : {
378+ type : 'object' ,
379+ properties : {
380+ ID : { type : 'number' , example : 1 } ,
381+ LyricID : { type : 'string' , example : 'LYR-00001' } ,
382+ SongID : { type : 'string' , example : 'SNG-00001' } ,
383+ LyricContent : { type : 'string' , example : 'Full lyrics in English...' } ,
384+ LyricContentSinhala : { type : 'string' , example : 'සම්පූර්ණ ගී පද...' }
385+ }
386+ } ,
387+ HealthCheck : {
388+ type : 'object' ,
389+ properties : {
390+ status : { type : 'string' , example : 'OK' } ,
391+ timestamp : { type : 'string' , example : '2025-11-08T10:30:00.000Z' } ,
392+ environment : { type : 'string' , example : 'Production' } ,
393+ version : { type : 'string' , example : '1.0.0' }
394+ }
395+ } ,
129396 ErrorResponse : {
130397 type : 'object' ,
131398 properties : {
132- status : { type : 'number' , example : 404 } ,
133- code : { type : 'string' , example : 'SONG_NOT_FOUND' } ,
134- message : { type : 'string' , example : 'Song not found' } ,
135- details : { type : 'string' , example : 'Song with ID SNG-9999999 does not exist' } ,
136- path : { type : 'string' , example : '/api/v1/songs/SNG-9999999' } ,
137- timestamp : { type : 'string' , example : '2025-11-08T10:30:00' }
399+ success : { type : 'boolean' , example : false } ,
400+ message : { type : 'string' , example : 'Error message' } ,
401+ error : { type : 'string' , example : 'Detailed error information' }
138402 }
139403 }
140404 }
0 commit comments