-
-
Notifications
You must be signed in to change notification settings - Fork 34
/
Copy pathfactories.ts
118 lines (110 loc) · 4.13 KB
/
factories.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
import {
EndpointsFactory,
arrayResultHandler,
ResultHandler,
defaultResultHandler,
ez,
ensureHttpError,
EventStreamFactory,
} from "../src";
import { config } from "./config";
import { authMiddleware } from "./middlewares";
import { createReadStream } from "node:fs";
import { z } from "zod";
/** @desc The factory assures the endpoints tagging constraints from config */
export const taggedEndpointsFactory = new EndpointsFactory({
resultHandler: defaultResultHandler,
config,
});
/** @desc This one extends the previous one by enforcing the authentication using the specified middleware */
export const keyAndTokenAuthenticatedEndpointsFactory =
taggedEndpointsFactory.addMiddleware(authMiddleware);
/** @desc This factory sends the file as string located in the "data" property of the endpoint's output */
export const fileSendingEndpointsFactory = new EndpointsFactory({
config,
resultHandler: new ResultHandler({
positive: { schema: z.string(), mimeType: "image/svg+xml" },
negative: { schema: z.string(), mimeType: "text/plain" },
handler: ({ response, error, output }) => {
if (error) return void response.status(400).send(error.message);
if (output && "data" in output && typeof output.data === "string")
response.type("svg").send(output.data);
else response.status(400).send("Data is missing");
},
}),
});
/** @desc This one streams the file using the "filename" property of the endpoint's output */
export const fileStreamingEndpointsFactory = new EndpointsFactory({
config,
resultHandler: new ResultHandler({
positive: { schema: ez.file("buffer"), mimeType: "image/*" },
negative: { schema: z.string(), mimeType: "text/plain" },
handler: ({ response, error, output }) => {
if (error) return void response.status(400).send(error.message);
if (output && "filename" in output && typeof output.filename === "string")
createReadStream(output.filename).pipe(response.type(output.filename));
else response.status(400).send("Filename is missing");
},
}),
});
/**
* @desc This factory demonstrates the ability to respond with array.
* @deprecated Avoid doing this in new projects. This feature is only for easier migration of legacy APIs.
* @alias arrayEndpointsFactory
*/
export const arrayRespondingFactory = new EndpointsFactory({
config,
resultHandler: arrayResultHandler,
});
/** @desc The factory demonstrates slightly different response schemas depending on the negative status code */
export const statusDependingFactory = new EndpointsFactory({
config,
resultHandler: new ResultHandler({
positive: (data) => ({
statusCode: [201, 202],
schema: z.object({ status: z.literal("created"), data }),
}),
negative: [
{
statusCode: 409,
schema: z.object({ status: z.literal("exists"), id: z.number().int() }),
},
{
statusCode: [400, 500],
schema: z.object({ status: z.literal("error"), reason: z.string() }),
},
],
handler: ({ error, response, output }) => {
if (error) {
const httpError = ensureHttpError(error);
const doesExist =
httpError.statusCode === 409 &&
"id" in httpError &&
typeof httpError.id === "number";
return void response
.status(httpError.statusCode)
.json(
doesExist
? { status: "exists", id: httpError.id }
: { status: "error", reason: httpError.message },
);
}
response.status(201).json({ status: "created", data: output });
},
}),
});
/** @desc This factory demonstrates response without body, such as 204 No Content */
export const noContentFactory = new EndpointsFactory({
config,
resultHandler: new ResultHandler({
positive: { statusCode: 204, mimeType: null, schema: z.never() },
negative: { statusCode: 404, mimeType: null, schema: z.never() },
handler: ({ error, response }) => {
response.status(error ? ensureHttpError(error).statusCode : 204).end(); // no content
},
}),
});
export const eventsFactory = new EventStreamFactory({
config,
events: { time: z.number().int().positive() },
});