Skip to content

Commit 18e39b2

Browse files
authored
Merge pull request #28 from jaredwray/feat-adding-in-the-start-of-mockhttp-class
feat: adding in the start of mockhttp class
2 parents ffffc5d + d389087 commit 18e39b2

File tree

5 files changed

+356
-109
lines changed

5 files changed

+356
-109
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
"@fastify/swagger-ui": "^5.2.1",
5454
"@scalar/api-reference": "^1.25.108",
5555
"fastify": "^5.2.1",
56+
"hookified": "^1.7.0",
5657
"html-escaper": "^3.0.3",
5758
"pino": "^9.6.0",
5859
"pino-pretty": "^13.0.0"

src/index.ts

Lines changed: 13 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,23 @@
11
import process from 'node:process';
2-
import path from 'node:path';
3-
import Fastify from 'fastify';
4-
import fastifyStatic from '@fastify/static';
5-
import {fastifySwagger} from '@fastify/swagger';
6-
import fastifyHelmet from '@fastify/helmet';
7-
import {indexRoute} from './routes/index.js';
8-
import {sitemapRoute} from './routes/sitemap.js';
9-
import {fastifyConfig} from './fastify-config.js';
10-
import {fastifySwaggerConfig, registerSwaggerUi} from './swagger.js';
11-
import {ipRoute, headersRoute, userAgentRoute} from './routes/request-inspection/index.js';
12-
import {
13-
getRoute, postRoute, deleteRoute, putRoute, patchRoute,
14-
} from './routes/http-methods/index.js';
15-
import {statusCodeRoute} from './routes/status-codes/index.js';
16-
import {cacheRoutes, etagRoutes, responseHeadersRoutes} from './routes/response-inspection/index.js';
17-
import {absoluteRedirectRoute, relativeRedirectRoute, redirectToRoute} from './routes/redirects/index.js';
18-
19-
// eslint-disable-next-line new-cap
20-
const fastify = Fastify(fastifyConfig);
21-
22-
// Register Scalar API client
23-
await fastify.register(fastifyStatic, {
24-
root: path.resolve('./node_modules/@scalar/api-reference/dist'),
25-
prefix: '/scalar',
26-
});
27-
28-
// Register the Public for favicon
29-
await fastify.register(fastifyStatic, {
30-
root: path.resolve('./public'),
31-
decorateReply: false,
32-
});
33-
34-
// Register the Helmet plugin for security headers
35-
await fastify.register(fastifyHelmet);
36-
37-
// Set up Swagger for API documentation
38-
await fastify.register(fastifySwagger, fastifySwaggerConfig);
39-
40-
// Register Swagger UI
41-
await registerSwaggerUi(fastify);
42-
43-
// Register the index / home page route
44-
await fastify.register(indexRoute);
45-
// Register the sitemap route
46-
await fastify.register(sitemapRoute);
47-
// Register the HTTP method routes
48-
await fastify.register(getRoute);
49-
await fastify.register(postRoute);
50-
await fastify.register(deleteRoute);
51-
await fastify.register(putRoute);
52-
await fastify.register(patchRoute);
53-
// Register the status code routes
54-
await fastify.register(statusCodeRoute);
55-
// Register the request inspection routes
56-
await fastify.register(ipRoute);
57-
await fastify.register(headersRoute);
58-
await fastify.register(userAgentRoute);
59-
// Register the response inspection routes
60-
await fastify.register(cacheRoutes);
61-
await fastify.register(etagRoutes);
62-
await fastify.register(responseHeadersRoutes);
63-
// Register the absolute redirect route
64-
await fastify.register(absoluteRedirectRoute);
65-
await fastify.register(relativeRedirectRoute);
66-
await fastify.register(redirectToRoute);
2+
import {MockHttp} from './mock-http.js';
673

684
// Start the Fastify server
695
export const start = async () => {
70-
try {
71-
let port = 3000;
72-
if (process.env.PORT) {
73-
port = Number.parseInt(process.env.PORT, 10);
74-
}
6+
const mockHttp = new MockHttp();
757

76-
let host = '0.0.0.0';
77-
if (process.env.HOST) {
78-
host = process.env.HOST;
79-
}
8+
if (process.env.PORT) {
9+
mockHttp.port = Number.parseInt(process.env.PORT, 10);
10+
}
8011

81-
await fastify.listen({port, host});
82-
} catch (error) {
83-
/* c8 ignore next 4 */
84-
fastify.log.error(error);
85-
// eslint-disable-next-line unicorn/no-process-exit
86-
process.exit(1);
12+
if (process.env.HOST) {
13+
mockHttp.host = process.env.HOST;
8714
}
15+
16+
await mockHttp.start();
17+
18+
return mockHttp;
8819
};
8920

9021
await start();
22+
23+
export {MockHttp as default, MockHttp as mockhttp} from './mock-http.js';

src/mock-http.ts

Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
import path from 'node:path';
2+
import fastifyStatic from '@fastify/static';
3+
import fastifyHelmet from '@fastify/helmet';
4+
import {fastifySwagger} from '@fastify/swagger';
5+
import {Hookified, type HookifiedOptions} from 'hookified';
6+
import Fastify, {type FastifyInstance} from 'fastify';
7+
import {fastifySwaggerConfig, registerSwaggerUi} from './swagger.js';
8+
import {fastifyConfig} from './fastify-config.js';
9+
import {indexRoute} from './routes/index.js';
10+
import {sitemapRoute} from './routes/sitemap.js';
11+
import {
12+
getRoute, postRoute, deleteRoute, putRoute, patchRoute,
13+
} from './routes/http-methods/index.js';
14+
import {statusCodeRoute} from './routes/status-codes/index.js';
15+
import {ipRoute, headersRoute, userAgentRoute} from './routes/request-inspection/index.js';
16+
import {cacheRoutes, etagRoutes, responseHeadersRoutes} from './routes/response-inspection/index.js';
17+
import {absoluteRedirectRoute, relativeRedirectRoute, redirectToRoute} from './routes/redirects/index.js';
18+
19+
// eslint-disable-next-line unicorn/prevent-abbreviations
20+
export type HttpBinOptions = {
21+
httpMethods?: boolean;
22+
redirects?: boolean;
23+
requestInspection?: boolean;
24+
responseInspection?: boolean;
25+
statusCodes?: boolean;
26+
};
27+
28+
export type MockHttpOptions = {
29+
/**
30+
* The port to listen on. If not provided, defaults to 3000 and falls back to 3001 if the PORT is in use.
31+
*/
32+
port?: number;
33+
/**
34+
* The host to listen on. If not provided, defaults to '0.0.0.0'.
35+
*/
36+
host?: string;
37+
/**
38+
* Whether to use Helmet for security headers. Defaults to true.
39+
*/
40+
helmet?: boolean;
41+
/**
42+
* Whether to use Swagger for API documentation. Defaults to true.
43+
*/
44+
apiDocs?: boolean;
45+
/**
46+
* Whether to use Swagger UI. Defaults to true.
47+
*/
48+
httpBin?: HttpBinOptions;
49+
/**
50+
* Hookified options.
51+
*/
52+
hookOptions?: HookifiedOptions;
53+
};
54+
55+
export class MockHttp extends Hookified {
56+
private _port = 3000;
57+
private _host = '0.0.0.0';
58+
private _helmet = true;
59+
private _apiDocs = true;
60+
private _httpBin: HttpBinOptions = {
61+
httpMethods: true,
62+
redirects: true,
63+
requestInspection: true,
64+
responseInspection: true,
65+
statusCodes: true,
66+
};
67+
68+
// eslint-disable-next-line new-cap
69+
private _server: FastifyInstance = Fastify();
70+
71+
constructor(options?: MockHttpOptions) {
72+
super(options?.hookOptions);
73+
74+
if (options?.port) {
75+
this._port = options.port;
76+
}
77+
78+
if (options?.host) {
79+
this._host = options.host;
80+
}
81+
82+
if (options?.helmet !== undefined) {
83+
this._helmet = options.helmet;
84+
}
85+
86+
if (options?.apiDocs !== undefined) {
87+
this._apiDocs = options.apiDocs;
88+
}
89+
90+
if (options?.httpBin !== undefined) {
91+
this._httpBin = options.httpBin;
92+
}
93+
}
94+
95+
public get port(): number {
96+
return this._port;
97+
}
98+
99+
public set port(port: number) {
100+
this._port = port;
101+
}
102+
103+
public get host(): string {
104+
return this._host;
105+
}
106+
107+
public set host(host: string) {
108+
this._host = host;
109+
}
110+
111+
public get helmet(): boolean {
112+
return this._helmet;
113+
}
114+
115+
public set helmet(helmet: boolean) {
116+
this._helmet = helmet;
117+
}
118+
119+
public get apiDocs(): boolean {
120+
return this._apiDocs;
121+
}
122+
123+
// eslint-disable-next-line unicorn/prevent-abbreviations
124+
public set apiDocs(apiDocs: boolean) {
125+
this._apiDocs = apiDocs;
126+
}
127+
128+
public get httpBin(): HttpBinOptions {
129+
return this._httpBin;
130+
}
131+
132+
public set httpBin(httpBinary: HttpBinOptions) {
133+
this._httpBin = httpBinary;
134+
}
135+
136+
public get server(): FastifyInstance {
137+
return this._server;
138+
}
139+
140+
public set server(server: FastifyInstance) {
141+
this._server = server;
142+
}
143+
144+
public async start(): Promise<void> {
145+
try {
146+
const {port, host} = this;
147+
148+
if (this._server) {
149+
await this._server.close();
150+
}
151+
152+
// eslint-disable-next-line new-cap
153+
this._server = Fastify(fastifyConfig);
154+
155+
// Register Scalar API client
156+
await this._server.register(fastifyStatic, {
157+
root: path.resolve('./node_modules/@scalar/api-reference/dist'),
158+
prefix: '/scalar',
159+
});
160+
161+
// Register the Public for favicon
162+
await this.server.register(fastifyStatic, {
163+
root: path.resolve('./public'),
164+
decorateReply: false,
165+
});
166+
167+
// Register the site map route
168+
await this._server.register(sitemapRoute);
169+
170+
// Register the Helmet plugin for security headers
171+
if (this._helmet) {
172+
await this._server.register(fastifyHelmet);
173+
}
174+
175+
if (this._apiDocs) {
176+
await this.registerApiDocs();
177+
}
178+
179+
const {httpMethods, redirects, requestInspection, responseInspection, statusCodes} = this._httpBin;
180+
181+
if (httpMethods) {
182+
await this.registerHttpMethods();
183+
}
184+
185+
if (statusCodes) {
186+
await this.registerStatusCodeRoutes();
187+
}
188+
189+
if (requestInspection) {
190+
await this.registerRequestInspectionRoutes();
191+
}
192+
193+
if (responseInspection) {
194+
await this.registerResponseInspectionRoutes();
195+
}
196+
197+
if (redirects) {
198+
await this.registerRedirectRoutes();
199+
}
200+
201+
await this._server.listen({port, host});
202+
} catch (error) {
203+
/* c8 ignore next 2 */
204+
this._server.log.error(error);
205+
}
206+
}
207+
208+
public async close(): Promise<void> {
209+
await this._server.close();
210+
}
211+
212+
public async registerApiDocs(fastifyInstance?: FastifyInstance): Promise<void> {
213+
const fastify = fastifyInstance ?? this._server;
214+
215+
// Set up Swagger for API documentation
216+
await fastify.register(fastifySwagger, fastifySwaggerConfig);
217+
218+
// Register Swagger UI
219+
await registerSwaggerUi(fastify);
220+
221+
// Register the index / home page route
222+
await fastify.register(indexRoute);
223+
}
224+
225+
public async registerHttpMethods(fastifyInstance?: FastifyInstance): Promise<void> {
226+
const fastify = fastifyInstance ?? this._server;
227+
await fastify.register(getRoute);
228+
await fastify.register(postRoute);
229+
await fastify.register(deleteRoute);
230+
await fastify.register(putRoute);
231+
await fastify.register(patchRoute);
232+
}
233+
234+
public async registerStatusCodeRoutes(fastifyInstance?: FastifyInstance): Promise<void> {
235+
const fastify = fastifyInstance ?? this._server;
236+
await fastify.register(statusCodeRoute);
237+
}
238+
239+
public async registerRequestInspectionRoutes(fastifyInstance?: FastifyInstance): Promise<void> {
240+
const fastify = fastifyInstance ?? this._server;
241+
await fastify.register(ipRoute);
242+
await fastify.register(headersRoute);
243+
await fastify.register(userAgentRoute);
244+
}
245+
246+
public async registerResponseInspectionRoutes(fastifyInstance?: FastifyInstance): Promise<void> {
247+
const fastify = fastifyInstance ?? this._server;
248+
await fastify.register(cacheRoutes);
249+
await fastify.register(etagRoutes);
250+
await fastify.register(responseHeadersRoutes);
251+
}
252+
253+
public async registerRedirectRoutes(fastifyInstance?: FastifyInstance): Promise<void> {
254+
const fastify = fastifyInstance ?? this._server;
255+
await fastify.register(absoluteRedirectRoute);
256+
await fastify.register(relativeRedirectRoute);
257+
await fastify.register(redirectToRoute);
258+
}
259+
}
260+
261+
export const mockhttp = MockHttp;

0 commit comments

Comments
 (0)