This repository has been archived by the owner on Aug 13, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathmain.ts
142 lines (115 loc) · 6.08 KB
/
main.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import { NestFactory } from "@nestjs/core";
import {
FastifyAdapter,
NestFastifyApplication,
} from "@nestjs/platform-fastify";
import { SwaggerModule, DocumentBuilder, SwaggerCustomOptions } from "@nestjs/swagger";
import { ValidationPipe, VersioningType } from "@nestjs/common";
import fastifyHelmet from "@fastify/helmet";
import { ConfigService } from "@nestjs/config";
import { Logger } from "nestjs-pino";
import fastifyRateLimit from "@fastify/rate-limit";
import path from "node:path";
import { writeFile } from "node:fs/promises";
import { major } from "semver";
import { AppModule } from "./app.module";
async function bootstrap () {
const app = await NestFactory.create<NestFastifyApplication>(
AppModule,
new FastifyAdapter({ logger: false }),
{ bufferLogs: true, rawBody: true },
);
const configService = app.get(ConfigService);
const apiDomain = String(configService.get("api.domain"));
const markdownDescription = `
## Swagger-UI API Documentation
This REST API can be used to create, read, update or delete data from the Open Sauced community platform.
The Swagger-UI provides useful information to get started and an overview of all available resources.
Each API route is clickable and has their own detailed description on how to use it.
The base URL for the API is [${apiDomain}](https://${apiDomain}).
[comment]: # (TODO: add bearer auth information)
## Rate limiting
Every IP address is allowed to perform 5000 requests per hour.
This is measured by saving the date of the initial request and counting all requests in the next hour.
When an IP address goes over the limit, HTTP status code 429 is returned.
The returned HTTP headers of any API request show the current rate limit status:
header | description
--- | ---
\`X-RateLimit-Limit\` | The maximum number of requests allowed per hour
\`X-RateLimit-Remaining\` | The number of requests remaining in the current rate limit window
\`X-RateLimit-Reset\` | The date and time at which the current rate limit window resets in [UTC epoch seconds](https://en.wikipedia.org/wiki/Unix_time)
[comment]: # (TODO: add pagination information)
## Common response codes
Each route shows for each method which data they expect and which they will respond when the call succeeds.
The table below shows most common response codes you can receive from our endpoints.
code | condition
--- | ---
[\`200\`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200) | The [\`GET\`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET) request was handled successfully. The response provides the requested data.
[\`201\`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/201) | The [\`POST\`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST) request was handled successfully. The response provides the created data.
[\`204\`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/204) | The [\`PATCH\`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH) or [\`DELETE\`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/DELETE) request was handled successfully. The response provides no data, generally.
[\`400\`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/400) | The server will not process the request due to something that is perceived to be a client error. Check the provided error for mote information.
[\`401\`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/401) | The request requires user authentication. Check the provided error for more information.
[\`403\`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/403) | The request was valid, but the server is refusing user access. Check the provided error for more information.
[\`404\`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/404) | The requested resource could not be found. Check the provided error for more information.
[\`429\`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429) | The current API Key made too many requests in the last hour. Check [Rate limiting](#ratelimiting) for more information.
## Additional links`;
app.useLogger(app.get(Logger));
app.flushLogs();
app.enableCors();
app.enableVersioning({
type: VersioningType.URI,
defaultVersion: String(major("1.0.0", { loose: false })),
});
const options = (new DocumentBuilder);
if (configService.get("api.development")) {
options.addServer(`http://localhost:${String(configService.get("api.port"))}`, "Development");
}
options
.addServer(`https://${apiDomain}`, "Production")
.addServer(`https://beta.${apiDomain}`, "Beta")
// .setTitle(name)
.setDescription(markdownDescription)
// .setVersion(version)
.setContact("Open Sauced", "https://opensauced.pizza", "[email protected]")
.setTermsOfService("https://github.com/open-sauced/code-of-conduct")
// .setLicense(`The ${license} License`, `https://opensource.org/licenses/${license}`)
.addBearerAuth();
const document = SwaggerModule.createDocument(app, options.build(), {
operationIdFactory: (
controllerKey: string,
methodKey: string,
) => methodKey,
});
const customOptions: SwaggerCustomOptions = { swaggerOptions: { persistAuthorization: true } };
const outputPath = path.resolve(process.cwd(), "dist/swagger.json");
try {
await writeFile(outputPath, JSON.stringify(document, null, 2), { encoding: "utf8" });
} catch (e) {
console.log(e);
}
SwaggerModule.setup("/", app, document, customOptions);
await app.register(fastifyHelmet, { contentSecurityPolicy: false });
await app.register(fastifyRateLimit, {
global: true,
max: 5000,
timeWindow: "1 hour",
enableDraftSpec: false,
addHeadersOnExceeding: {
"x-ratelimit-limit": true,
"x-ratelimit-remaining": true,
"x-ratelimit-reset": true,
},
addHeaders: {
"x-ratelimit-limit": true,
"x-ratelimit-remaining": true,
"x-ratelimit-reset": true,
"retry-after": true,
},
});
app.useGlobalPipes(new ValidationPipe({
transform: true,
forbidUnknownValues: true,
}));
await app.listen(configService.get("api.port")!, configService.get("api.host"));
}
void bootstrap();