Skip to content

Commit 1fb92a6

Browse files
Merge pull request #4 from SinSo-API/dev
feat: new artist endpoint and openAPI documentation setup
2 parents aedcf79 + 47ac549 commit 1fb92a6

10 files changed

Lines changed: 421 additions & 28 deletions

File tree

doc/openapi.config.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { DOC_VERSION } from "../src/metadata";
2+
3+
export const openAPIConfig = {
4+
openapi: '3.0.0',
5+
info: {
6+
title: 'SinSo API Lite Documentation',
7+
version: DOC_VERSION,
8+
description: 'REST API documentation for SinSo API Lite',
9+
contact: {
10+
name: 'Vishal Rashmika',
11+
email: 'vishal@vishalrashmika.com',
12+
url: 'https://vishalrashmika.com',
13+
},
14+
license: {
15+
name: 'GNU General Public License v3.0',
16+
url: 'https://www.gnu.org/licenses/gpl-3.0.en.html',
17+
},
18+
},
19+
servers: [
20+
{
21+
url: 'https://sinso.vishalrashmika.com',
22+
description: 'Production Environment',
23+
},
24+
{
25+
url: 'http://localhost:8787',
26+
description: 'Local Development',
27+
},
28+
],
29+
};

doc/openapi.spec.ts

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
import { openAPIConfig } from './openapi.config';
2+
3+
export const generateOpenAPISpec = () => {
4+
return {
5+
...openAPIConfig,
6+
paths: {
7+
'/api/v1/songs': {
8+
get: {
9+
tags: ['Songs'],
10+
summary: 'Get all songs',
11+
description: 'Get a paginated list of all songs with optional filters',
12+
parameters: [
13+
{
14+
name: 'page',
15+
in: 'query',
16+
description: 'Page number',
17+
required: false,
18+
schema: { type: 'string', example: '1' }
19+
},
20+
{
21+
name: 'limit',
22+
in: 'query',
23+
description: 'Items per page',
24+
required: false,
25+
schema: { type: 'string', example: '10' }
26+
},
27+
{
28+
name: 'artistId',
29+
in: 'query',
30+
description: 'Filter by artist ID (example: ART-00001)',
31+
required: false,
32+
schema: { type: 'string' }
33+
},
34+
{
35+
name: 'releaseYear',
36+
in: 'query',
37+
description: 'Filter by release year (example: 2024)',
38+
required: false,
39+
schema: { type: 'string' }
40+
},
41+
{
42+
name: 'search',
43+
in: 'query',
44+
description: 'Search in song names (example: love)',
45+
required: false,
46+
schema: { type: 'string' }
47+
},
48+
{
49+
name: 'sortBy',
50+
in: 'query',
51+
description: 'Sort field (example: ViewCount)',
52+
required: false,
53+
schema: { type: 'string' }
54+
},
55+
{
56+
name: 'sortOrder',
57+
in: 'query',
58+
description: 'Sort order (example: asc/desc)',
59+
required: false,
60+
schema: { type: 'string' }
61+
}
62+
],
63+
responses: {
64+
'200': {
65+
description: 'Songs retrieved successfully',
66+
content: {
67+
'application/json': {
68+
schema: {
69+
type: 'object',
70+
properties: {
71+
success: { type: 'boolean', example: true },
72+
data: {
73+
type: 'array',
74+
items: { type: 'object' }
75+
},
76+
pagination: {
77+
type: 'object',
78+
properties: {
79+
page: { type: 'number', example: 1 },
80+
limit: { type: 'number', example: 10 },
81+
total: { type: 'number', example: 100 },
82+
totalPages: { type: 'number', example: 10 }
83+
}
84+
}
85+
}
86+
}
87+
}
88+
}
89+
},
90+
'500': {
91+
description: 'Internal server error',
92+
content: {
93+
'application/json': {
94+
schema: { $ref: '#/components/schemas/ErrorResponse' }
95+
}
96+
}
97+
}
98+
}
99+
}
100+
},
101+
'/api/v1/songs/health': {
102+
get: {
103+
tags: ['Songs'],
104+
summary: 'Check songs service health',
105+
description: 'Health check endpoint for the songs service',
106+
responses: {
107+
'200': {
108+
description: 'Service is healthy',
109+
content: {
110+
'application/json': {
111+
schema: {
112+
type: 'object',
113+
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' }
118+
}
119+
}
120+
}
121+
}
122+
}
123+
}
124+
}
125+
}
126+
},
127+
components: {
128+
schemas: {
129+
ErrorResponse: {
130+
type: 'object',
131+
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' }
138+
}
139+
}
140+
}
141+
}
142+
};
143+
};

package-lock.json

Lines changed: 90 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@
99
"db:migrate:local": "wrangler d1 execute sinso-api-db --local --file=./schema.sql"
1010
},
1111
"dependencies": {
12+
"@hono/swagger-ui": "^0.5.2",
13+
"@hono/zod-openapi": "^0.8.5",
1214
"drizzle-orm": "^0.44.6",
13-
"hono": "^4.9.11",
14-
"vite": "^7.1.9"
15+
"hono": "^4.10.4",
16+
"vite": "^7.1.9",
17+
"zod": "^3.25.76"
1518
},
1619
"devDependencies": {
1720
"@cloudflare/vite-plugin": "^1.2.3",
@@ -21,5 +24,4 @@
2124
"wrangler": "^4.42.2"
2225
},
2326
"build": "wrangler deploy"
24-
25-
}
27+
}

0 commit comments

Comments
 (0)