Skip to content

Commit 2d8d779

Browse files
committed
feat(docs): add api documentation with swagger and scalar
- Integrates @fastify/swagger and @scalar/fastify-api-reference to generate API documentation in development - Adds a new /docs endpoint for the documentation - Uses tsx for development and starting the server, replacing ts-node and nodemon - Updates tsconfig.json to use NodeNext module resolution - Adds tags to each route for better organization in the documentation
1 parent 29a2e30 commit 2d8d779

34 files changed

+341
-150
lines changed

package.json

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
"version": "1.0.0",
44
"main": "src/main.ts",
55
"scripts": {
6-
"start": "ts-node src/main.ts",
7-
"dev": "nodemon src/main.ts",
6+
"start": "tsx src/main.ts",
7+
"dev": "tsx --watch src/main.ts",
88
"build": "tsc",
99
"lint": "prettier --write \"src/**/*.ts\""
1010
},
@@ -25,21 +25,24 @@
2525
"dependencies": {
2626
"@consumet/extensions": "github:consumet/consumet.ts",
2727
"@fastify/cors": "^8.5.0",
28-
"@types/node": "^18.11.17",
29-
"@types/ws": "^8.5.3",
3028
"axios": "^1.0.0",
31-
"chalk": "4.1.2",
29+
"chalk": "^5.6.2",
3230
"cheerio": "1.0.0-rc.12",
3331
"dotenv": "^16.0.3",
3432
"fastify": "^4.10.2",
3533
"ioredis": "^5.2.4",
3634
"reconnecting-websocket": "^4.4.0",
37-
"ts-node": "^10.9.1",
3835
"ws": "^8.8.1"
3936
},
4037
"devDependencies": {
41-
"nodemon": "3.0.1",
38+
"@fastify/swagger": "^8.14.0",
39+
"@scalar/fastify-api-reference": "^1.40.1",
40+
"@types/chalk": "^0.4.31",
41+
"@types/node": "^18.11.17",
42+
"@types/ws": "^8.5.3",
4243
"prettier": "^3.0.0",
44+
"ts-node": "^10.9.1",
45+
"tsx": "^4.21.0",
4346
"typescript": "5.3.3"
4447
}
4548
}

src/main.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,59 @@ export const tmdbApi = process.env.TMDB_KEY && process.env.TMDB_KEY;
3939
methods: 'GET',
4040
});
4141

42+
// Only register Swagger and docs in development
43+
if (process.env.NODE_ENV !== 'production') {
44+
await fastify.register((await import('@fastify/swagger')).default, {
45+
openapi: {
46+
info: {
47+
title: 'Consumet API',
48+
description: 'A REST API for fetching data from various entertainment sources.',
49+
version: '1.0.0',
50+
},
51+
servers: [
52+
{
53+
url: `http://localhost:${PORT}`,
54+
description: 'Local server',
55+
},
56+
],
57+
'x-tagGroups': [
58+
{
59+
name: 'Anime',
60+
tags: [
61+
'hianime',
62+
'animekai',
63+
'animepahe',
64+
'animesaturn',
65+
'animeunity',
66+
'kickassanime',
67+
],
68+
},
69+
{ name: 'Movies', tags: ['flixhq', 'dramacool', 'goku', 'sflix', 'himovies'] },
70+
{ name: 'Manga', tags: ['mangadex', 'mangahere', 'mangapill', 'mangareader'] },
71+
{ name: 'Meta', tags: ['anilist', 'anilist-manga', 'mal', 'tmdb'] },
72+
// { name: 'Books', tags: ['books'] },
73+
// { name: 'Comics', tags: ['getcomics'] },
74+
// { name: 'Light Novels', tags: ['light-novels'] },
75+
{ name: 'News', tags: ['ann'] },
76+
],
77+
} as any,
78+
});
79+
80+
await fastify.register((await import('@scalar/fastify-api-reference')).default, {
81+
routePrefix: '/docs',
82+
configuration: {
83+
title: 'Consumet API Documentation',
84+
theme: 'bluePlanet',
85+
defaultOpenAllTags: false,
86+
hideModels: true,
87+
tagsSorter: 'alpha',
88+
sidebar: {
89+
showOperations: true,
90+
},
91+
} as any,
92+
});
93+
}
94+
4295
if (process.env.NODE_ENV === 'DEMO') {
4396
console.log(chalk.yellowBright('DEMO MODE ENABLED'));
4497

src/routes/anime/animekai.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ import { Redis } from 'ioredis';
99
const routes = async (fastify: FastifyInstance, options: RegisterOptions) => {
1010
const animekai = new ANIME.AnimeKai();
1111

12+
fastify.addHook('onRoute', (routeOptions) => {
13+
routeOptions.schema = routeOptions.schema || {};
14+
routeOptions.schema.tags = ['animekai'];
15+
});
16+
1217
fastify.get('/', (_, rp) => {
1318
rp.status(200).send({
1419
intro: `Welcome to the animekai provider: check out the provider's website @ ${animekai.toString.baseUrl}`,

src/routes/anime/animepahe.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ import { Redis } from 'ioredis';
88
const routes = async (fastify: FastifyInstance, options: RegisterOptions) => {
99
const animepahe = new ANIME.AnimePahe();
1010

11+
fastify.addHook('onRoute', (routeOptions) => {
12+
routeOptions.schema = routeOptions.schema || {};
13+
routeOptions.schema.tags = ['animepahe'];
14+
});
15+
1116
fastify.get('/', (_, rp) => {
1217
rp.status(200).send({
1318
intro: `Welcome to the animepahe provider: check out the provider's website @ ${animepahe.toString.baseUrl}`,

src/routes/anime/animesaturn.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ import cache from '../../utils/cache';
77
const routes = async (fastify: FastifyInstance, options: RegisterOptions) => {
88
const animesaturn = new ANIME.AnimeSaturn();
99

10+
fastify.addHook('onRoute', (routeOptions) => {
11+
routeOptions.schema = routeOptions.schema || {};
12+
routeOptions.schema.tags = ['animesaturn'];
13+
});
14+
1015
fastify.get('/', (_, rp) => {
1116
rp.status(200).send({
1217
intro:

src/routes/anime/animeunity.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ import { Redis } from 'ioredis';
88
const routes = async (fastify: FastifyInstance, options: RegisterOptions) => {
99
const animeunity = new ANIME.AnimeUnity();
1010

11+
fastify.addHook('onRoute', (routeOptions) => {
12+
routeOptions.schema = routeOptions.schema || {};
13+
routeOptions.schema.tags = ['animeunity'];
14+
});
15+
1116
fastify.get('/', (_, rp) => {
1217
rp.status(200).send({
1318
intro: `Welcome to the animeunity provider: check out the provider's website @ ${animeunity.toString.baseUrl}`,

src/routes/anime/hianime.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ import { Redis } from 'ioredis';
99
const routes = async (fastify: FastifyInstance, options: RegisterOptions) => {
1010
const hianime = new ANIME.Hianime();
1111

12+
fastify.addHook('onRoute', (routeOptions) => {
13+
routeOptions.schema = routeOptions.schema || {};
14+
routeOptions.schema.tags = ['hianime'];
15+
});
16+
1217
fastify.get('/', (_, rp) => {
1318
rp.status(200).send({
1419
intro: `Welcome to the hianime provider: check out the provider's website @ ${hianime.toString.baseUrl}`,

src/routes/anime/index.ts

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,40 +16,44 @@ const routes = async (fastify: FastifyInstance, options: RegisterOptions) => {
1616
await fastify.register(animesaturn, { prefix: '/animesaturn' });
1717
await fastify.register(kickassanime, { prefix: '/kickassanime' });
1818

19-
fastify.get('/', async (request: any, reply: any) => {
19+
fastify.get('/', { schema: { hide: true } }, async (request: any, reply: any) => {
2020
reply.status(200).send('Welcome to Consumet Anime 🗾');
2121
});
2222

23-
fastify.get('/:animeProvider', async (request: FastifyRequest, reply: FastifyReply) => {
24-
const queries: { animeProvider: string; page: number } = {
25-
animeProvider: '',
26-
page: 1,
27-
};
28-
29-
queries.animeProvider = decodeURIComponent(
30-
(request.params as { animeProvider: string; page: number }).animeProvider,
31-
);
32-
33-
queries.page = (request.query as { animeProvider: string; page: number }).page;
34-
35-
if (queries.page! < 1) queries.page = 1;
36-
37-
const provider = PROVIDERS_LIST.ANIME.find(
38-
(provider: any) => provider.toString.name === queries.animeProvider,
39-
);
40-
41-
try {
42-
if (provider) {
43-
reply.redirect(`/anime/${provider.toString.name}`);
44-
} else {
45-
reply
46-
.status(404)
47-
.send({ message: 'Provider not found, please check the providers list.' });
23+
fastify.get(
24+
'/:animeProvider',
25+
{ schema: { hide: true } },
26+
async (request: FastifyRequest, reply: FastifyReply) => {
27+
const queries: { animeProvider: string; page: number } = {
28+
animeProvider: '',
29+
page: 1,
30+
};
31+
32+
queries.animeProvider = decodeURIComponent(
33+
(request.params as { animeProvider: string; page: number }).animeProvider,
34+
);
35+
36+
queries.page = (request.query as { animeProvider: string; page: number }).page;
37+
38+
if (queries.page! < 1) queries.page = 1;
39+
40+
const provider = PROVIDERS_LIST.ANIME.find(
41+
(provider: any) => provider.toString.name === queries.animeProvider,
42+
);
43+
44+
try {
45+
if (provider) {
46+
reply.redirect(`/anime/${provider.toString.name}`);
47+
} else {
48+
reply
49+
.status(404)
50+
.send({ message: 'Provider not found, please check the providers list.' });
51+
}
52+
} catch (err) {
53+
reply.status(500).send('Something went wrong. Please try again later.');
4854
}
49-
} catch (err) {
50-
reply.status(500).send('Something went wrong. Please try again later.');
51-
}
52-
});
55+
},
56+
);
5357
};
5458

5559
export default routes;

src/routes/anime/kickassanime.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ import { Redis } from 'ioredis';
99
const routes = async (fastify: FastifyInstance, options: RegisterOptions) => {
1010
const kickassanime = new ANIME.KickAssAnime();
1111

12+
fastify.addHook('onRoute', (routeOptions) => {
13+
routeOptions.schema = routeOptions.schema || {};
14+
routeOptions.schema.tags = ['kickassanime'];
15+
});
16+
1217
fastify.get('/', (_, rp) => {
1318
rp.status(200).send({
1419
intro: `Welcome to the kickassanime provider: check out the provider's website @ ${kickassanime.toString.baseUrl}`,

src/routes/books/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { FastifyInstance, RegisterOptions } from 'fastify';
22

33
const routes = async (fastify: FastifyInstance, options: RegisterOptions) => {
4-
fastify.get('/', async (request: any, reply: any) => {
4+
fastify.get('/', { schema: { hide: true } }, async (request: any, reply: any) => {
55
reply.status(200).send('Welcome to Consumet Books 📚');
66
});
77
};

0 commit comments

Comments
 (0)