@twin.org/api-server-fastify 0.0.2-next.8 → 0.0.3-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/es/fastifySocketIo.js +18 -0
- package/dist/es/fastifySocketIo.js.map +1 -0
- package/dist/{esm/index.mjs → es/fastifyWebServer.js} +111 -88
- package/dist/es/fastifyWebServer.js.map +1 -0
- package/dist/es/index.js +6 -0
- package/dist/es/index.js.map +1 -0
- package/dist/es/models/IFastifyWebServerConfig.js +2 -0
- package/dist/es/models/IFastifyWebServerConfig.js.map +1 -0
- package/dist/es/models/IFastifyWebServerConstructorOptions.js +2 -0
- package/dist/es/models/IFastifyWebServerConstructorOptions.js.map +1 -0
- package/dist/types/fastifyWebServer.d.ts +2 -2
- package/dist/types/index.d.ts +3 -3
- package/dist/types/models/IFastifyWebServerConstructorOptions.d.ts +1 -1
- package/docs/changelog.md +114 -0
- package/docs/reference/classes/FastifyWebServer.md +1 -1
- package/locales/.validate-ignore +2 -0
- package/locales/en.json +18 -12
- package/package.json +24 -13
- package/dist/cjs/index.cjs +0 -562
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import fp from "fastify-plugin";
|
|
2
|
+
import { Server } from "socket.io";
|
|
3
|
+
// This is a clone of fastify-socket.io which runs with recent fastify versions.
|
|
4
|
+
const fastifySocketIO = fp(async (fastify, opts) => {
|
|
5
|
+
const ioServer = new Server(fastify.server, opts);
|
|
6
|
+
fastify.decorate("io", ioServer);
|
|
7
|
+
fastify.addHook("preClose", done => {
|
|
8
|
+
ioServer.disconnectSockets();
|
|
9
|
+
ioServer
|
|
10
|
+
.close()
|
|
11
|
+
// eslint-disable-next-line promise/prefer-await-to-then, promise/no-callback-in-promise
|
|
12
|
+
.then(() => done())
|
|
13
|
+
// eslint-disable-next-line promise/prefer-await-to-then, promise/no-callback-in-promise
|
|
14
|
+
.catch(() => done());
|
|
15
|
+
});
|
|
16
|
+
}, { fastify: ">=5.x.x", name: "socket.io" });
|
|
17
|
+
export default fastifySocketIO;
|
|
18
|
+
//# sourceMappingURL=fastifySocketIo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fastifySocketIo.js","sourceRoot":"","sources":["../../src/fastifySocketIo.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAChC,OAAO,EAAE,MAAM,EAAsB,MAAM,WAAW,CAAC;AAEvD,gFAAgF;AAChF,MAAM,eAAe,GAA+C,EAAE,CACrE,KAAK,EAAE,OAAwB,EAAE,IAA4B,EAAE,EAAE;IAChE,MAAM,QAAQ,GAAG,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAElD,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACjC,OAAO,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE;QAClC,QAAQ,CAAC,iBAAiB,EAAE,CAAC;QAC7B,QAAQ;aACN,KAAK,EAAE;YACR,wFAAwF;aACvF,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC;YACnB,wFAAwF;aACvF,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;AACJ,CAAC,EACD,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,CACzC,CAAC;AAEF,eAAe,eAAe,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { FastifyInstance, FastifyPluginAsync } from \"fastify\";\nimport fp from \"fastify-plugin\";\nimport { Server, type ServerOptions } from \"socket.io\";\n\n// This is a clone of fastify-socket.io which runs with recent fastify versions.\nconst fastifySocketIO: FastifyPluginAsync<Partial<ServerOptions>> = fp(\n\tasync (fastify: FastifyInstance, opts: Partial<ServerOptions>) => {\n\t\tconst ioServer = new Server(fastify.server, opts);\n\n\t\tfastify.decorate(\"io\", ioServer);\n\t\tfastify.addHook(\"preClose\", done => {\n\t\t\tioServer.disconnectSockets();\n\t\t\tioServer\n\t\t\t\t.close()\n\t\t\t\t// eslint-disable-next-line promise/prefer-await-to-then, promise/no-callback-in-promise\n\t\t\t\t.then(() => done())\n\t\t\t\t// eslint-disable-next-line promise/prefer-await-to-then, promise/no-callback-in-promise\n\t\t\t\t.catch(() => done());\n\t\t});\n\t},\n\t{ fastify: \">=5.x.x\", name: \"socket.io\" }\n);\n\nexport default fastifySocketIO;\n"]}
|
|
@@ -1,35 +1,22 @@
|
|
|
1
|
-
import FastifyCompress from '@fastify/compress';
|
|
2
|
-
import FastifyCors from '@fastify/cors';
|
|
3
|
-
import { HttpErrorHelper } from '@twin.org/api-models';
|
|
4
|
-
import { JsonLdMimeTypeProcessor } from '@twin.org/api-processors';
|
|
5
|
-
import { StringHelper, ComponentFactory, Is, GeneralError, BaseError } from '@twin.org/core';
|
|
6
|
-
import { HttpStatusCode, HttpMethod, HeaderTypes } from '@twin.org/web';
|
|
7
|
-
import Fastify from 'fastify';
|
|
8
|
-
import fp from 'fastify-plugin';
|
|
9
|
-
import { Server } from 'socket.io';
|
|
10
|
-
|
|
11
|
-
// This is a clone of fastify-socket.io which runs with recent fastify versions.
|
|
12
|
-
const fastifySocketIO = fp(async (fastify, opts) => {
|
|
13
|
-
const ioServer = new Server(fastify.server, opts);
|
|
14
|
-
fastify.decorate("io", ioServer);
|
|
15
|
-
fastify.addHook("preClose", done => {
|
|
16
|
-
ioServer.disconnectSockets();
|
|
17
|
-
ioServer.close();
|
|
18
|
-
done();
|
|
19
|
-
});
|
|
20
|
-
}, { fastify: ">=5.x.x", name: "socket.io" });
|
|
21
|
-
|
|
22
1
|
// Copyright 2024 IOTA Stiftung.
|
|
23
2
|
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
import FastifyCompress from "@fastify/compress";
|
|
4
|
+
import FastifyCors from "@fastify/cors";
|
|
5
|
+
import { HttpErrorHelper } from "@twin.org/api-models";
|
|
6
|
+
import { JsonLdMimeTypeProcessor } from "@twin.org/api-processors";
|
|
7
|
+
import { ContextIdStore } from "@twin.org/context";
|
|
8
|
+
import { BaseError, ComponentFactory, GeneralError, Is, StringHelper } from "@twin.org/core";
|
|
9
|
+
import { HeaderTypes, HttpMethod, HttpStatusCode } from "@twin.org/web";
|
|
10
|
+
import Fastify from "fastify";
|
|
11
|
+
import FastifySocketIO from "./fastifySocketIo.js";
|
|
24
12
|
/**
|
|
25
13
|
* Implementation of the web server using Fastify.
|
|
26
14
|
*/
|
|
27
|
-
class FastifyWebServer {
|
|
15
|
+
export class FastifyWebServer {
|
|
28
16
|
/**
|
|
29
|
-
* Runtime name for the class
|
|
30
|
-
* @internal
|
|
17
|
+
* Runtime name for the class.
|
|
31
18
|
*/
|
|
32
|
-
static
|
|
19
|
+
static CLASS_NAME = "FastifyWebServer";
|
|
33
20
|
/**
|
|
34
21
|
* Default port for running the server.
|
|
35
22
|
* @internal
|
|
@@ -40,10 +27,6 @@ class FastifyWebServer {
|
|
|
40
27
|
* @internal
|
|
41
28
|
*/
|
|
42
29
|
static _DEFAULT_HOST = "localhost";
|
|
43
|
-
/**
|
|
44
|
-
* Runtime name for the class.
|
|
45
|
-
*/
|
|
46
|
-
CLASS_NAME = "FastifyWebServer";
|
|
47
30
|
/**
|
|
48
31
|
* The logging component type.
|
|
49
32
|
* @internal
|
|
@@ -105,7 +88,7 @@ class FastifyWebServer {
|
|
|
105
88
|
};
|
|
106
89
|
this._started = false;
|
|
107
90
|
this._mimeTypeProcessors = options?.mimeTypeProcessors ?? [];
|
|
108
|
-
const hasJsonLd = this._mimeTypeProcessors.find(processor => processor.
|
|
91
|
+
const hasJsonLd = this._mimeTypeProcessors.find(processor => processor.className() === "json-ld");
|
|
109
92
|
if (!hasJsonLd) {
|
|
110
93
|
this._mimeTypeProcessors.push(new JsonLdMimeTypeProcessor());
|
|
111
94
|
}
|
|
@@ -129,21 +112,21 @@ class FastifyWebServer {
|
|
|
129
112
|
*/
|
|
130
113
|
async build(restRouteProcessors, restRoutes, socketRouteProcessors, socketRoutes, options) {
|
|
131
114
|
if (Is.arrayValue(restRoutes) && !Is.arrayValue(restRouteProcessors)) {
|
|
132
|
-
throw new GeneralError(
|
|
115
|
+
throw new GeneralError(FastifyWebServer.CLASS_NAME, "noRestProcessors");
|
|
133
116
|
}
|
|
134
117
|
if (Is.arrayValue(socketRoutes) && !Is.arrayValue(socketRouteProcessors)) {
|
|
135
|
-
throw new GeneralError(
|
|
118
|
+
throw new GeneralError(FastifyWebServer.CLASS_NAME, "noSocketProcessors");
|
|
136
119
|
}
|
|
137
120
|
await this._logging?.log({
|
|
138
121
|
level: "info",
|
|
139
122
|
ts: Date.now(),
|
|
140
|
-
source:
|
|
141
|
-
message:
|
|
123
|
+
source: FastifyWebServer.CLASS_NAME,
|
|
124
|
+
message: "building"
|
|
142
125
|
});
|
|
143
126
|
this._options = options;
|
|
144
127
|
await this._fastify.register(FastifyCompress);
|
|
145
128
|
if (Is.arrayValue(socketRoutes)) {
|
|
146
|
-
await this._fastify.register(
|
|
129
|
+
await this._fastify.register(FastifySocketIO, this._socketConfig);
|
|
147
130
|
}
|
|
148
131
|
if (Is.arrayValue(this._mimeTypeProcessors)) {
|
|
149
132
|
for (const contentTypeHandler of this._mimeTypeProcessors) {
|
|
@@ -166,9 +149,9 @@ class FastifyWebServer {
|
|
|
166
149
|
// otherwise it's from our framework
|
|
167
150
|
let httpStatusCode;
|
|
168
151
|
let err;
|
|
169
|
-
if (Is.number(error.code)) {
|
|
152
|
+
if (Is.number(error.code) || Is.string(error.code)) {
|
|
170
153
|
err = {
|
|
171
|
-
source:
|
|
154
|
+
source: FastifyWebServer.CLASS_NAME,
|
|
172
155
|
name: error.name,
|
|
173
156
|
message: `${error.code}: ${error.message}`
|
|
174
157
|
};
|
|
@@ -182,8 +165,8 @@ class FastifyWebServer {
|
|
|
182
165
|
await this._logging?.log({
|
|
183
166
|
level: "error",
|
|
184
167
|
ts: Date.now(),
|
|
185
|
-
source:
|
|
186
|
-
message:
|
|
168
|
+
source: FastifyWebServer.CLASS_NAME,
|
|
169
|
+
message: "badRequest",
|
|
187
170
|
error: err
|
|
188
171
|
});
|
|
189
172
|
return reply.status(httpStatusCode).send({
|
|
@@ -203,8 +186,8 @@ class FastifyWebServer {
|
|
|
203
186
|
await this._logging?.log({
|
|
204
187
|
level: "info",
|
|
205
188
|
ts: Date.now(),
|
|
206
|
-
source:
|
|
207
|
-
message:
|
|
189
|
+
source: FastifyWebServer.CLASS_NAME,
|
|
190
|
+
message: "starting",
|
|
208
191
|
data: {
|
|
209
192
|
host,
|
|
210
193
|
port
|
|
@@ -218,8 +201,8 @@ class FastifyWebServer {
|
|
|
218
201
|
await this._logging?.log({
|
|
219
202
|
level: "info",
|
|
220
203
|
ts: Date.now(),
|
|
221
|
-
source:
|
|
222
|
-
message:
|
|
204
|
+
source: FastifyWebServer.CLASS_NAME,
|
|
205
|
+
message: "started",
|
|
223
206
|
data: {
|
|
224
207
|
addresses: addresses
|
|
225
208
|
.map(a => `${protocol}${a.family === "IPv6" ? "[" : ""}${a.address}${a.family === "IPv6" ? "]" : ""}:${a.port}`)
|
|
@@ -232,8 +215,8 @@ class FastifyWebServer {
|
|
|
232
215
|
await this._logging?.log({
|
|
233
216
|
level: "error",
|
|
234
217
|
ts: Date.now(),
|
|
235
|
-
source:
|
|
236
|
-
message:
|
|
218
|
+
source: FastifyWebServer.CLASS_NAME,
|
|
219
|
+
message: "startFailed",
|
|
237
220
|
error: BaseError.fromError(err)
|
|
238
221
|
});
|
|
239
222
|
}
|
|
@@ -250,8 +233,8 @@ class FastifyWebServer {
|
|
|
250
233
|
await this._logging?.log({
|
|
251
234
|
level: "info",
|
|
252
235
|
ts: Date.now(),
|
|
253
|
-
source:
|
|
254
|
-
message:
|
|
236
|
+
source: FastifyWebServer.CLASS_NAME,
|
|
237
|
+
message: "stopped"
|
|
255
238
|
});
|
|
256
239
|
}
|
|
257
240
|
}
|
|
@@ -271,8 +254,8 @@ class FastifyWebServer {
|
|
|
271
254
|
await this._logging?.log({
|
|
272
255
|
level: "info",
|
|
273
256
|
ts: Date.now(),
|
|
274
|
-
source:
|
|
275
|
-
message:
|
|
257
|
+
source: FastifyWebServer.CLASS_NAME,
|
|
258
|
+
message: "restRouteAdded",
|
|
276
259
|
data: { route: path, method: restRoute.method }
|
|
277
260
|
});
|
|
278
261
|
const method = restRoute.method.toLowerCase();
|
|
@@ -298,8 +281,8 @@ class FastifyWebServer {
|
|
|
298
281
|
await this._logging?.log({
|
|
299
282
|
level: "info",
|
|
300
283
|
ts: Date.now(),
|
|
301
|
-
source:
|
|
302
|
-
message:
|
|
284
|
+
source: FastifyWebServer.CLASS_NAME,
|
|
285
|
+
message: "socketRouteAdded",
|
|
303
286
|
data: {
|
|
304
287
|
handshakePath: this._socketConfig.path,
|
|
305
288
|
namespace,
|
|
@@ -368,9 +351,9 @@ class FastifyWebServer {
|
|
|
368
351
|
headers: request.headers
|
|
369
352
|
};
|
|
370
353
|
const httpResponse = {};
|
|
371
|
-
const
|
|
372
|
-
const processorState = {};
|
|
373
|
-
await this.runProcessorsRest(restRouteProcessors, restRoute, httpServerRequest, httpResponse,
|
|
354
|
+
const contextIds = {};
|
|
355
|
+
const processorState = restRoute?.processorData ?? {};
|
|
356
|
+
await this.runProcessorsRest(restRouteProcessors, restRoute, httpServerRequest, httpResponse, contextIds, processorState);
|
|
374
357
|
if (!Is.empty(httpResponse.headers)) {
|
|
375
358
|
for (const header of Object.keys(httpResponse.headers)) {
|
|
376
359
|
reply.header(header, httpResponse.headers[header]);
|
|
@@ -386,24 +369,32 @@ class FastifyWebServer {
|
|
|
386
369
|
* @param restRoute The route to process.
|
|
387
370
|
* @param httpServerRequest The incoming request.
|
|
388
371
|
* @param httpResponse The outgoing response.
|
|
389
|
-
* @param
|
|
372
|
+
* @param contextIds The context IDs of the request.
|
|
390
373
|
* @internal
|
|
391
374
|
*/
|
|
392
|
-
async runProcessorsRest(restRouteProcessors, restRoute, httpServerRequest, httpResponse,
|
|
375
|
+
async runProcessorsRest(restRouteProcessors, restRoute, httpServerRequest, httpResponse, contextIds, processorState) {
|
|
393
376
|
try {
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
377
|
+
const filteredProcessors = this.filterRouteProcessors(restRoute, restRouteProcessors);
|
|
378
|
+
for (const routeProcessor of filteredProcessors) {
|
|
379
|
+
const pre = routeProcessor.pre?.bind(routeProcessor);
|
|
380
|
+
if (Is.function(pre)) {
|
|
381
|
+
await pre(httpServerRequest, httpResponse, restRoute, contextIds, processorState, this._loggingComponentType);
|
|
397
382
|
}
|
|
398
383
|
}
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
384
|
+
// Run the processors within an async context
|
|
385
|
+
// so that any services can access the context ids
|
|
386
|
+
await ContextIdStore.run(contextIds, async () => {
|
|
387
|
+
for (const routeProcessor of filteredProcessors) {
|
|
388
|
+
const process = routeProcessor.process?.bind(routeProcessor);
|
|
389
|
+
if (Is.function(process)) {
|
|
390
|
+
await process(httpServerRequest, httpResponse, restRoute, processorState, this._loggingComponentType);
|
|
391
|
+
}
|
|
402
392
|
}
|
|
403
|
-
}
|
|
404
|
-
for (const routeProcessor of
|
|
405
|
-
|
|
406
|
-
|
|
393
|
+
});
|
|
394
|
+
for (const routeProcessor of filteredProcessors) {
|
|
395
|
+
const post = routeProcessor.post?.bind(routeProcessor);
|
|
396
|
+
if (Is.function(post)) {
|
|
397
|
+
await post(httpServerRequest, httpResponse, restRoute, contextIds, processorState, this._loggingComponentType);
|
|
407
398
|
}
|
|
408
399
|
}
|
|
409
400
|
}
|
|
@@ -412,6 +403,33 @@ class FastifyWebServer {
|
|
|
412
403
|
HttpErrorHelper.buildResponse(httpResponse, error, httpStatusCode);
|
|
413
404
|
}
|
|
414
405
|
}
|
|
406
|
+
/**
|
|
407
|
+
* Filter the route processors based on the requested features.
|
|
408
|
+
* @param route The route to process.
|
|
409
|
+
* @param routeProcessors The processors to filter.
|
|
410
|
+
* @returns The filtered list of route processor.
|
|
411
|
+
* @internal
|
|
412
|
+
*/
|
|
413
|
+
filterRouteProcessors(route, routeProcessors) {
|
|
414
|
+
const requestedFeatures = route?.processorFeatures ?? [];
|
|
415
|
+
if (!Is.arrayValue(requestedFeatures)) {
|
|
416
|
+
// If there are no requested features, we just return all the processors
|
|
417
|
+
return routeProcessors;
|
|
418
|
+
}
|
|
419
|
+
// Reduce the list of route processors to just those in the requested features list
|
|
420
|
+
const reducedProcessors = routeProcessors.filter(routeProcessor => {
|
|
421
|
+
// Processors that do not define any features always get run
|
|
422
|
+
// If the route processor has features defined, then we only run it
|
|
423
|
+
// if the route has at least one of those features required
|
|
424
|
+
let runRouteProcessor = true;
|
|
425
|
+
if (routeProcessor.features) {
|
|
426
|
+
const routeProcessorFeatures = routeProcessor.features();
|
|
427
|
+
runRouteProcessor = routeProcessorFeatures.some(feature => requestedFeatures.includes(feature));
|
|
428
|
+
}
|
|
429
|
+
return runRouteProcessor;
|
|
430
|
+
});
|
|
431
|
+
return reducedProcessors;
|
|
432
|
+
}
|
|
415
433
|
/**
|
|
416
434
|
* Handle the incoming socket request.
|
|
417
435
|
* @param socketRouteProcessors The hooks to process the incoming requests.
|
|
@@ -432,12 +450,12 @@ class FastifyWebServer {
|
|
|
432
450
|
socketId: socket.id
|
|
433
451
|
};
|
|
434
452
|
const httpResponse = {};
|
|
435
|
-
const
|
|
453
|
+
const contextIds = {};
|
|
436
454
|
const processorState = {};
|
|
437
455
|
delete socketServerRequest.query?.EIO;
|
|
438
456
|
delete socketServerRequest.query?.transport;
|
|
439
|
-
await this.runProcessorsSocket(socketRouteProcessors, socketRoute, socketServerRequest, httpResponse,
|
|
440
|
-
|
|
457
|
+
await this.runProcessorsSocket(socketRouteProcessors, socketRoute, socketServerRequest, httpResponse, contextIds, processorState, emitTopic, async (topic, response) => {
|
|
458
|
+
socket.emit(topic, response);
|
|
441
459
|
});
|
|
442
460
|
}
|
|
443
461
|
/**
|
|
@@ -447,29 +465,31 @@ class FastifyWebServer {
|
|
|
447
465
|
* @param socketRoute The route to process.
|
|
448
466
|
* @param socketServerRequest The incoming request.
|
|
449
467
|
* @param httpResponse The outgoing response.
|
|
450
|
-
* @param
|
|
468
|
+
* @param contextIds The context IDs of the request.
|
|
451
469
|
* @param processorState The state handed through the processors.
|
|
452
470
|
* @param requestTopic The topic of the request.
|
|
453
471
|
* @internal
|
|
454
472
|
*/
|
|
455
|
-
async runProcessorsSocket(socketRouteProcessors, socketRoute, socketServerRequest, httpResponse,
|
|
473
|
+
async runProcessorsSocket(socketRouteProcessors, socketRoute, socketServerRequest, httpResponse, contextIds, processorState, requestTopic, responseEmitter) {
|
|
474
|
+
const filteredProcessors = this.filterRouteProcessors(socketRoute, socketRouteProcessors);
|
|
456
475
|
// Custom emit method which will also call the post processors
|
|
457
476
|
const postProcessEmit = async (topic, response, responseProcessorState) => {
|
|
458
477
|
await responseEmitter(topic, response);
|
|
459
478
|
try {
|
|
460
479
|
// The post processors are called after the response has been emitted
|
|
461
|
-
for (const postSocketRouteProcessor of
|
|
462
|
-
|
|
463
|
-
|
|
480
|
+
for (const postSocketRouteProcessor of filteredProcessors) {
|
|
481
|
+
const post = postSocketRouteProcessor.post?.bind(postSocketRouteProcessor);
|
|
482
|
+
if (Is.function(post)) {
|
|
483
|
+
await post(socketServerRequest, response, socketRoute, contextIds, responseProcessorState, this._loggingComponentType);
|
|
464
484
|
}
|
|
465
485
|
}
|
|
466
486
|
}
|
|
467
487
|
catch (err) {
|
|
468
|
-
this._logging?.log({
|
|
488
|
+
await this._logging?.log({
|
|
469
489
|
level: "error",
|
|
470
490
|
ts: Date.now(),
|
|
471
|
-
source:
|
|
472
|
-
message:
|
|
491
|
+
source: FastifyWebServer.CLASS_NAME,
|
|
492
|
+
message: "postProcessorError",
|
|
473
493
|
error: BaseError.fromError(err),
|
|
474
494
|
data: {
|
|
475
495
|
route: socketRoute.path
|
|
@@ -478,9 +498,10 @@ class FastifyWebServer {
|
|
|
478
498
|
}
|
|
479
499
|
};
|
|
480
500
|
try {
|
|
481
|
-
for (const socketRouteProcessor of
|
|
482
|
-
|
|
483
|
-
|
|
501
|
+
for (const socketRouteProcessor of filteredProcessors) {
|
|
502
|
+
const pre = socketRouteProcessor.pre?.bind(socketRouteProcessor);
|
|
503
|
+
if (Is.function(pre)) {
|
|
504
|
+
await pre(socketServerRequest, httpResponse, socketRoute, contextIds, processorState, this._loggingComponentType);
|
|
484
505
|
}
|
|
485
506
|
}
|
|
486
507
|
// We always call all the processors regardless of any response set by a previous processor.
|
|
@@ -489,13 +510,16 @@ class FastifyWebServer {
|
|
|
489
510
|
if (!Is.empty(httpResponse.statusCode)) {
|
|
490
511
|
await postProcessEmit(requestTopic, httpResponse, processorState);
|
|
491
512
|
}
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
513
|
+
await ContextIdStore.run(contextIds, async () => {
|
|
514
|
+
for (const socketRouteProcessor of filteredProcessors) {
|
|
515
|
+
const process = socketRouteProcessor.process?.bind(socketRouteProcessor);
|
|
516
|
+
if (Is.function(process)) {
|
|
517
|
+
await process(socketServerRequest, httpResponse, socketRoute, processorState, async (topic, processResponse) => {
|
|
518
|
+
await postProcessEmit(topic, processResponse, processorState);
|
|
519
|
+
}, this._loggingComponentType);
|
|
520
|
+
}
|
|
497
521
|
}
|
|
498
|
-
}
|
|
522
|
+
});
|
|
499
523
|
// If the processors set the status to any kind of error then we should emit this manually
|
|
500
524
|
if (Is.integer(httpResponse.statusCode) &&
|
|
501
525
|
httpResponse.statusCode >= HttpStatusCode.badRequest) {
|
|
@@ -556,5 +580,4 @@ class FastifyWebServer {
|
|
|
556
580
|
});
|
|
557
581
|
}
|
|
558
582
|
}
|
|
559
|
-
|
|
560
|
-
export { FastifyWebServer };
|
|
583
|
+
//# sourceMappingURL=fastifyWebServer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fastifyWebServer.js","sourceRoot":"","sources":["../../src/fastifyWebServer.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport FastifyCompress from \"@fastify/compress\";\nimport FastifyCors from \"@fastify/cors\";\nimport {\n\tHttpErrorHelper,\n\ttype IBaseRoute,\n\ttype IBaseRouteProcessor,\n\ttype IHttpRequest,\n\ttype IHttpRequestPathParams,\n\ttype IHttpRequestQuery,\n\ttype IHttpResponse,\n\ttype IHttpServerRequest,\n\ttype IMimeTypeProcessor,\n\ttype IRestRoute,\n\ttype IRestRouteProcessor,\n\ttype ISocketRoute,\n\ttype ISocketRouteProcessor,\n\ttype ISocketServerRequest,\n\ttype IWebServer,\n\ttype IWebServerOptions\n} from \"@twin.org/api-models\";\nimport { JsonLdMimeTypeProcessor } from \"@twin.org/api-processors\";\nimport { ContextIdStore, type IContextIds } from \"@twin.org/context\";\nimport {\n\tBaseError,\n\tComponentFactory,\n\tGeneralError,\n\ttype IError,\n\tIs,\n\tStringHelper\n} from \"@twin.org/core\";\nimport type { ILoggingComponent } from \"@twin.org/logging-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport { HeaderTypes, HttpMethod, HttpStatusCode, type IHttpHeaders } from \"@twin.org/web\";\nimport Fastify, {\n\ttype FastifyInstance,\n\ttype FastifyReply,\n\ttype FastifyRequest,\n\ttype FastifyServerOptions\n} from \"fastify\";\nimport type { Server, ServerOptions, Socket } from \"socket.io\";\nimport FastifySocketIO from \"./fastifySocketIo.js\";\nimport type { IFastifyWebServerConstructorOptions } from \"./models/IFastifyWebServerConstructorOptions.js\";\n\n/**\n * Implementation of the web server using Fastify.\n */\nexport class FastifyWebServer implements IWebServer<FastifyInstance> {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<FastifyWebServer>();\n\n\t/**\n\t * Default port for running the server.\n\t * @internal\n\t */\n\tprivate static readonly _DEFAULT_PORT: number = 3000;\n\n\t/**\n\t * Default host for running the server.\n\t * @internal\n\t */\n\tprivate static readonly _DEFAULT_HOST: string = \"localhost\";\n\n\t/**\n\t * The logging component type.\n\t * @internal\n\t */\n\tprivate readonly _loggingComponentType?: string;\n\n\t/**\n\t * The logging component.\n\t * @internal\n\t */\n\tprivate readonly _logging?: ILoggingComponent;\n\n\t/**\n\t * The options for the server.\n\t * @internal\n\t */\n\tprivate _options?: IWebServerOptions;\n\n\t/**\n\t * The Fastify instance.\n\t * @internal\n\t */\n\tprivate readonly _fastify: FastifyInstance;\n\n\t/**\n\t * The options for the socket server.\n\t * @internal\n\t */\n\tprivate readonly _socketConfig: Partial<ServerOptions>;\n\n\t/**\n\t * Whether the server has been started.\n\t * @internal\n\t */\n\tprivate _started: boolean;\n\n\t/**\n\t * The mime type processors.\n\t * @internal\n\t */\n\tprivate readonly _mimeTypeProcessors: IMimeTypeProcessor[];\n\n\t/**\n\t * Include the stack with errors.\n\t * @internal\n\t */\n\tprivate readonly _includeErrorStack: boolean;\n\n\t/**\n\t * Create a new instance of FastifyWebServer.\n\t * @param options The options for the server.\n\t */\n\tconstructor(options?: IFastifyWebServerConstructorOptions) {\n\t\tthis._loggingComponentType = options?.loggingComponentType;\n\t\tthis._logging = ComponentFactory.getIfExists(options?.loggingComponentType ?? \"logging\");\n\t\tthis._fastify = Fastify({\n\t\t\trouterOptions: {\n\t\t\t\tmaxParamLength: 2000\n\t\t\t},\n\t\t\t...options?.config?.web\n\t\t\t// Need this cast for now as maxParamLength has moved in to routerOptions\n\t\t\t// but the TS defs has not been updated yet\n\t\t} as unknown as FastifyServerOptions);\n\t\tthis._socketConfig = {\n\t\t\tpath: \"/socket\",\n\t\t\t...options?.config?.socket\n\t\t};\n\t\tthis._started = false;\n\n\t\tthis._mimeTypeProcessors = options?.mimeTypeProcessors ?? [];\n\n\t\tconst hasJsonLd = this._mimeTypeProcessors.find(\n\t\t\tprocessor => processor.className() === \"json-ld\"\n\t\t);\n\t\tif (!hasJsonLd) {\n\t\t\tthis._mimeTypeProcessors.push(new JsonLdMimeTypeProcessor());\n\t\t}\n\n\t\tthis._includeErrorStack = options?.config?.includeErrorStack ?? false;\n\t}\n\n\t/**\n\t * Get the web server instance.\n\t * @returns The web server instance.\n\t */\n\tpublic getInstance(): FastifyInstance {\n\t\treturn this._fastify;\n\t}\n\n\t/**\n\t * Build the server.\n\t * @param restRouteProcessors The processors for incoming requests over REST.\n\t * @param restRoutes The REST routes.\n\t * @param socketRouteProcessors The processors for incoming requests over Sockets.\n\t * @param socketRoutes The socket routes.\n\t * @param options Options for building the server.\n\t * @returns Nothing.\n\t */\n\tpublic async build(\n\t\trestRouteProcessors?: IRestRouteProcessor[],\n\t\trestRoutes?: IRestRoute[],\n\t\tsocketRouteProcessors?: ISocketRouteProcessor[],\n\t\tsocketRoutes?: ISocketRoute[],\n\t\toptions?: IWebServerOptions\n\t): Promise<void> {\n\t\tif (Is.arrayValue(restRoutes) && !Is.arrayValue(restRouteProcessors)) {\n\t\t\tthrow new GeneralError(FastifyWebServer.CLASS_NAME, \"noRestProcessors\");\n\t\t}\n\t\tif (Is.arrayValue(socketRoutes) && !Is.arrayValue(socketRouteProcessors)) {\n\t\t\tthrow new GeneralError(FastifyWebServer.CLASS_NAME, \"noSocketProcessors\");\n\t\t}\n\t\tawait this._logging?.log({\n\t\t\tlevel: \"info\",\n\t\t\tts: Date.now(),\n\t\t\tsource: FastifyWebServer.CLASS_NAME,\n\t\t\tmessage: \"building\"\n\t\t});\n\n\t\tthis._options = options;\n\n\t\tawait this._fastify.register(FastifyCompress);\n\n\t\tif (Is.arrayValue(socketRoutes)) {\n\t\t\tawait this._fastify.register(FastifySocketIO, this._socketConfig);\n\t\t}\n\n\t\tif (Is.arrayValue(this._mimeTypeProcessors)) {\n\t\t\tfor (const contentTypeHandler of this._mimeTypeProcessors) {\n\t\t\t\tthis._fastify.addContentTypeParser(\n\t\t\t\t\tcontentTypeHandler.getTypes(),\n\t\t\t\t\t{ parseAs: \"buffer\" },\n\t\t\t\t\t(request, body, done) => {\n\t\t\t\t\t\t// Fastify does not handle this method correctly if it is async\n\t\t\t\t\t\t// so we have to use the callback method\n\t\t\t\t\t\tcontentTypeHandler\n\t\t\t\t\t\t\t.handle(body as Buffer)\n\t\t\t\t\t\t\t// eslint-disable-next-line promise/prefer-await-to-then, promise/no-callback-in-promise\n\t\t\t\t\t\t\t.then(processed => done(null, processed))\n\t\t\t\t\t\t\t// eslint-disable-next-line promise/prefer-await-to-then, promise/no-callback-in-promise\n\t\t\t\t\t\t\t.catch(err => done(BaseError.fromError(err)));\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tawait this.initCors(options);\n\n\t\tthis._fastify.setNotFoundHandler({}, async (request, reply) =>\n\t\t\tthis.handleRequestRest(restRouteProcessors ?? [], request, reply)\n\t\t);\n\n\t\tthis._fastify.setErrorHandler(\n\t\t\tasync (\n\t\t\t\terror: Error & {\n\t\t\t\t\tcode?: number | string;\n\t\t\t\t\tstatusCode?: number | string;\n\t\t\t\t},\n\t\t\t\trequest,\n\t\t\t\treply\n\t\t\t) => {\n\t\t\t\t// If code property is set this is a fastify error\n\t\t\t\t// otherwise it's from our framework\n\t\t\t\tlet httpStatusCode: HttpStatusCode;\n\t\t\t\tlet err: IError;\n\t\t\t\tif (Is.number(error.code) || Is.string(error.code)) {\n\t\t\t\t\terr = {\n\t\t\t\t\t\tsource: FastifyWebServer.CLASS_NAME,\n\t\t\t\t\t\tname: error.name,\n\t\t\t\t\t\tmessage: `${error.code}: ${error.message}`\n\t\t\t\t\t};\n\t\t\t\t\thttpStatusCode = (error.statusCode as HttpStatusCode) ?? HttpStatusCode.badRequest;\n\t\t\t\t} else {\n\t\t\t\t\tconst errorAndCode = HttpErrorHelper.processError(error);\n\t\t\t\t\terr = errorAndCode.error;\n\t\t\t\t\thttpStatusCode = errorAndCode.httpStatusCode;\n\t\t\t\t}\n\n\t\t\t\tawait this._logging?.log({\n\t\t\t\t\tlevel: \"error\",\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tsource: FastifyWebServer.CLASS_NAME,\n\t\t\t\t\tmessage: \"badRequest\",\n\t\t\t\t\terror: err\n\t\t\t\t});\n\n\t\t\t\treturn reply.status(httpStatusCode).send({\n\t\t\t\t\terror: err\n\t\t\t\t});\n\t\t\t}\n\t\t);\n\n\t\tawait this.addRoutesRest(restRouteProcessors, restRoutes);\n\t\tawait this.addRoutesSocket(socketRouteProcessors, socketRoutes);\n\t}\n\n\t/**\n\t * Start the server.\n\t * @returns Nothing.\n\t */\n\tpublic async start(): Promise<void> {\n\t\tconst host = this._options?.host ?? FastifyWebServer._DEFAULT_HOST;\n\t\tconst port = this._options?.port ?? FastifyWebServer._DEFAULT_PORT;\n\n\t\tawait this._logging?.log({\n\t\t\tlevel: \"info\",\n\t\t\tts: Date.now(),\n\t\t\tsource: FastifyWebServer.CLASS_NAME,\n\t\t\tmessage: \"starting\",\n\t\t\tdata: {\n\t\t\t\thost,\n\t\t\t\tport\n\t\t\t}\n\t\t});\n\n\t\tif (!this._started) {\n\t\t\ttry {\n\t\t\t\tawait this._fastify.listen({ port, host });\n\t\t\t\tconst addresses = this._fastify.addresses();\n\n\t\t\t\tconst protocol = Is.object(this._fastify.initialConfig.https) ? \"https://\" : \"http://\";\n\t\t\t\tawait this._logging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tsource: FastifyWebServer.CLASS_NAME,\n\t\t\t\t\tmessage: \"started\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\taddresses: addresses\n\t\t\t\t\t\t\t.map(\n\t\t\t\t\t\t\t\ta =>\n\t\t\t\t\t\t\t\t\t`${protocol}${a.family === \"IPv6\" ? \"[\" : \"\"}${a.address}${a.family === \"IPv6\" ? \"]\" : \"\"}:${a.port}`\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.join(\", \")\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tthis._started = true;\n\t\t\t} catch (err) {\n\t\t\t\tawait this._logging?.log({\n\t\t\t\t\tlevel: \"error\",\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tsource: FastifyWebServer.CLASS_NAME,\n\t\t\t\t\tmessage: \"startFailed\",\n\t\t\t\t\terror: BaseError.fromError(err)\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Stop the server.\n\t * @returns Nothing.\n\t */\n\tpublic async stop(): Promise<void> {\n\t\tif (this._started) {\n\t\t\tthis._started = false;\n\n\t\t\tawait this._fastify.close();\n\n\t\t\tawait this._logging?.log({\n\t\t\t\tlevel: \"info\",\n\t\t\t\tts: Date.now(),\n\t\t\t\tsource: FastifyWebServer.CLASS_NAME,\n\t\t\t\tmessage: \"stopped\"\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Add the REST routes to the server.\n\t * @param restRouteProcessors The processors for the incoming requests.\n\t * @param restRoutes The REST routes to add.\n\t * @internal\n\t */\n\tprivate async addRoutesRest(\n\t\trestRouteProcessors?: IRestRouteProcessor[],\n\t\trestRoutes?: IRestRoute[]\n\t): Promise<void> {\n\t\tif (Is.arrayValue(restRouteProcessors) && Is.arrayValue(restRoutes)) {\n\t\t\tfor (const restRoute of restRoutes) {\n\t\t\t\tlet path = StringHelper.trimTrailingSlashes(restRoute.path);\n\t\t\t\tif (!path.startsWith(\"/\")) {\n\t\t\t\t\tpath = `/${path}`;\n\t\t\t\t}\n\t\t\t\tawait this._logging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tsource: FastifyWebServer.CLASS_NAME,\n\t\t\t\t\tmessage: \"restRouteAdded\",\n\t\t\t\t\tdata: { route: path, method: restRoute.method }\n\t\t\t\t});\n\t\t\t\tconst method = restRoute.method.toLowerCase() as\n\t\t\t\t\t| \"get\"\n\t\t\t\t\t| \"post\"\n\t\t\t\t\t| \"put\"\n\t\t\t\t\t| \"patch\"\n\t\t\t\t\t| \"delete\"\n\t\t\t\t\t| \"options\"\n\t\t\t\t\t| \"head\";\n\n\t\t\t\tthis._fastify[method](path, async (request, reply) =>\n\t\t\t\t\tthis.handleRequestRest(restRouteProcessors, request, reply, restRoute)\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Add the socket routes to the server.\n\t * @param socketRouteProcessors The processors for the incoming requests.\n\t * @param socketRoutes The socket routes to add.\n\t * @internal\n\t */\n\tprivate async addRoutesSocket(\n\t\tsocketRouteProcessors?: ISocketRouteProcessor[],\n\t\tsocketRoutes?: ISocketRoute[]\n\t): Promise<void> {\n\t\tif (Is.arrayValue(socketRouteProcessors) && Is.arrayValue(socketRoutes)) {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\tconst io: Server = (this._fastify as any).io;\n\n\t\t\tfor (const socketRoute of socketRoutes) {\n\t\t\t\tconst path = StringHelper.trimLeadingSlashes(\n\t\t\t\t\tStringHelper.trimTrailingSlashes(socketRoute.path)\n\t\t\t\t);\n\t\t\t\tconst pathParts = path.split(\"/\");\n\n\t\t\t\tconst namespace = `/${pathParts[0]}`;\n\t\t\t\tconst topic = pathParts.slice(1).join(\"/\");\n\n\t\t\t\tawait this._logging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tsource: FastifyWebServer.CLASS_NAME,\n\t\t\t\t\tmessage: \"socketRouteAdded\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\thandshakePath: this._socketConfig.path,\n\t\t\t\t\t\tnamespace,\n\t\t\t\t\t\teventName: topic\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tconst socketNamespace = io.of(namespace);\n\n\t\t\t\tsocketNamespace.on(\"connection\", async socket => {\n\t\t\t\t\tconst socketServerRequest: ISocketServerRequest = {\n\t\t\t\t\t\tmethod: HttpMethod.GET,\n\t\t\t\t\t\turl: socket.handshake.url,\n\t\t\t\t\t\tquery: socket.handshake.query as IHttpRequestQuery,\n\t\t\t\t\t\theaders: socket.handshake.headers as IHttpHeaders,\n\t\t\t\t\t\tsocketId: socket.id\n\t\t\t\t\t};\n\n\t\t\t\t\t// Pass the connected information on to any processors\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor (const socketRouteProcessor of socketRouteProcessors) {\n\t\t\t\t\t\t\tif (socketRouteProcessor.connected) {\n\t\t\t\t\t\t\t\tawait socketRouteProcessor.connected(\n\t\t\t\t\t\t\t\t\tsocketServerRequest,\n\t\t\t\t\t\t\t\t\tsocketRoute,\n\t\t\t\t\t\t\t\t\tthis._loggingComponentType\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tconst { error, httpStatusCode } = HttpErrorHelper.processError(\n\t\t\t\t\t\t\terr,\n\t\t\t\t\t\t\tthis._includeErrorStack\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst response: IHttpResponse = {};\n\t\t\t\t\t\tHttpErrorHelper.buildResponse(response, error, httpStatusCode);\n\t\t\t\t\t\tsocket.emit(topic, response);\n\t\t\t\t\t}\n\n\t\t\t\t\tsocket.on(\"disconnect\", async () => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// The socket disconnected so notify any processors\n\t\t\t\t\t\t\tfor (const socketRouteProcessor of socketRouteProcessors) {\n\t\t\t\t\t\t\t\tif (socketRouteProcessor.disconnected) {\n\t\t\t\t\t\t\t\t\tawait socketRouteProcessor.disconnected(\n\t\t\t\t\t\t\t\t\t\tsocketServerRequest,\n\t\t\t\t\t\t\t\t\t\tsocketRoute,\n\t\t\t\t\t\t\t\t\t\tthis._loggingComponentType\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// If something fails on a disconnect there is not much we can do with it\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\t// Handle any incoming messages\n\t\t\t\t\tsocket.on(topic, async data => {\n\t\t\t\t\t\tawait this.handleRequestSocket(\n\t\t\t\t\t\t\tsocketRouteProcessors,\n\t\t\t\t\t\t\tsocketRoute,\n\t\t\t\t\t\t\tsocket,\n\t\t\t\t\t\t\t`/${pathParts.join(\"/\")}`,\n\t\t\t\t\t\t\ttopic,\n\t\t\t\t\t\t\tdata\n\t\t\t\t\t\t);\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Handle the incoming REST request.\n\t * @param restRouteProcessors The hooks to process the incoming requests.\n\t * @param request The incoming request.\n\t * @param reply The outgoing response.\n\t * @param restRoute The REST route to handle.\n\t * @internal\n\t */\n\tprivate async handleRequestRest(\n\t\trestRouteProcessors: IRestRouteProcessor[],\n\t\trequest: FastifyRequest,\n\t\treply: FastifyReply,\n\t\trestRoute?: IRestRoute\n\t): Promise<FastifyReply> {\n\t\tconst httpServerRequest: IHttpServerRequest = {\n\t\t\tmethod: request.method.toUpperCase() as HttpMethod,\n\t\t\turl: `${request.protocol}://${request.hostname}${request.url}`,\n\t\t\tbody: request.body,\n\t\t\tquery: request.query as IHttpRequestQuery,\n\t\t\tpathParams: request.params as IHttpRequestPathParams,\n\t\t\theaders: request.headers as IHttpHeaders\n\t\t};\n\t\tconst httpResponse: IHttpResponse = {};\n\t\tconst contextIds: IContextIds = {};\n\t\tconst processorState = restRoute?.processorData ?? {};\n\n\t\tawait this.runProcessorsRest(\n\t\t\trestRouteProcessors,\n\t\t\trestRoute,\n\t\t\thttpServerRequest,\n\t\t\thttpResponse,\n\t\t\tcontextIds,\n\t\t\tprocessorState\n\t\t);\n\n\t\tif (!Is.empty(httpResponse.headers)) {\n\t\t\tfor (const header of Object.keys(httpResponse.headers)) {\n\t\t\t\treply.header(header, httpResponse.headers[header]);\n\t\t\t}\n\t\t}\n\t\treturn reply\n\t\t\t.status((httpResponse.statusCode ?? HttpStatusCode.ok) as number)\n\t\t\t.send(httpResponse.body);\n\t}\n\n\t/**\n\t * Run the REST processors for the route.\n\t * @param restRouteProcessors The processors to run.\n\t * @param restRoute The route to process.\n\t * @param httpServerRequest The incoming request.\n\t * @param httpResponse The outgoing response.\n\t * @param contextIds The context IDs of the request.\n\t * @internal\n\t */\n\tprivate async runProcessorsRest(\n\t\trestRouteProcessors: IRestRouteProcessor[],\n\t\trestRoute: IRestRoute | undefined,\n\t\thttpServerRequest: IHttpServerRequest,\n\t\thttpResponse: IHttpResponse,\n\t\tcontextIds: IContextIds,\n\t\tprocessorState: {\n\t\t\t[id: string]: unknown;\n\t\t}\n\t): Promise<void> {\n\t\ttry {\n\t\t\tconst filteredProcessors = this.filterRouteProcessors(restRoute, restRouteProcessors);\n\n\t\t\tfor (const routeProcessor of filteredProcessors) {\n\t\t\t\tconst pre = routeProcessor.pre?.bind(routeProcessor);\n\t\t\t\tif (Is.function(pre)) {\n\t\t\t\t\tawait pre(\n\t\t\t\t\t\thttpServerRequest,\n\t\t\t\t\t\thttpResponse,\n\t\t\t\t\t\trestRoute,\n\t\t\t\t\t\tcontextIds,\n\t\t\t\t\t\tprocessorState,\n\t\t\t\t\t\tthis._loggingComponentType\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Run the processors within an async context\n\t\t\t// so that any services can access the context ids\n\t\t\tawait ContextIdStore.run(contextIds, async () => {\n\t\t\t\tfor (const routeProcessor of filteredProcessors) {\n\t\t\t\t\tconst process = routeProcessor.process?.bind(routeProcessor);\n\t\t\t\t\tif (Is.function(process)) {\n\t\t\t\t\t\tawait process(\n\t\t\t\t\t\t\thttpServerRequest,\n\t\t\t\t\t\t\thttpResponse,\n\t\t\t\t\t\t\trestRoute,\n\t\t\t\t\t\t\tprocessorState,\n\t\t\t\t\t\t\tthis._loggingComponentType\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tfor (const routeProcessor of filteredProcessors) {\n\t\t\t\tconst post = routeProcessor.post?.bind(routeProcessor);\n\t\t\t\tif (Is.function(post)) {\n\t\t\t\t\tawait post(\n\t\t\t\t\t\thttpServerRequest,\n\t\t\t\t\t\thttpResponse,\n\t\t\t\t\t\trestRoute,\n\t\t\t\t\t\tcontextIds,\n\t\t\t\t\t\tprocessorState,\n\t\t\t\t\t\tthis._loggingComponentType\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tconst { error, httpStatusCode } = HttpErrorHelper.processError(err, this._includeErrorStack);\n\t\t\tHttpErrorHelper.buildResponse(httpResponse, error, httpStatusCode);\n\t\t}\n\t}\n\n\t/**\n\t * Filter the route processors based on the requested features.\n\t * @param route The route to process.\n\t * @param routeProcessors The processors to filter.\n\t * @returns The filtered list of route processor.\n\t * @internal\n\t */\n\tprivate filterRouteProcessors<T extends IBaseRouteProcessor>(\n\t\troute: IBaseRoute | undefined,\n\t\trouteProcessors: T[]\n\t): T[] {\n\t\tconst requestedFeatures = route?.processorFeatures ?? [];\n\n\t\tif (!Is.arrayValue(requestedFeatures)) {\n\t\t\t// If there are no requested features, we just return all the processors\n\t\t\treturn routeProcessors;\n\t\t}\n\n\t\t// Reduce the list of route processors to just those in the requested features list\n\t\tconst reducedProcessors = routeProcessors.filter(routeProcessor => {\n\t\t\t// Processors that do not define any features always get run\n\t\t\t// If the route processor has features defined, then we only run it\n\t\t\t// if the route has at least one of those features required\n\t\t\tlet runRouteProcessor = true;\n\t\t\tif (routeProcessor.features) {\n\t\t\t\tconst routeProcessorFeatures = routeProcessor.features();\n\t\t\t\trunRouteProcessor = routeProcessorFeatures.some(feature =>\n\t\t\t\t\trequestedFeatures.includes(feature)\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn runRouteProcessor;\n\t\t});\n\n\t\treturn reducedProcessors;\n\t}\n\n\t/**\n\t * Handle the incoming socket request.\n\t * @param socketRouteProcessors The hooks to process the incoming requests.\n\t * @param socketRoute The socket route to handle.\n\t * @param socket The socket to handle.\n\t * @param fullPath The full path of the socket route.\n\t * @param emitTopic The topic to emit the response on.\n\t * @param data The incoming data.\n\t * @internal\n\t */\n\tprivate async handleRequestSocket(\n\t\tsocketRouteProcessors: ISocketRouteProcessor[],\n\t\tsocketRoute: ISocketRoute,\n\t\tsocket: Socket,\n\t\tfullPath: string,\n\t\temitTopic: string,\n\t\trequest: IHttpRequest\n\t): Promise<void> {\n\t\tconst socketServerRequest: ISocketServerRequest = {\n\t\t\tmethod: HttpMethod.GET,\n\t\t\turl: fullPath,\n\t\t\tquery: socket.handshake.query as IHttpRequestQuery,\n\t\t\theaders: socket.handshake.headers as IHttpHeaders,\n\t\t\tbody: request.body,\n\t\t\tsocketId: socket.id\n\t\t};\n\t\tconst httpResponse: IHttpResponse = {};\n\t\tconst contextIds: IContextIds = {};\n\t\tconst processorState = {};\n\n\t\tdelete socketServerRequest.query?.EIO;\n\t\tdelete socketServerRequest.query?.transport;\n\n\t\tawait this.runProcessorsSocket(\n\t\t\tsocketRouteProcessors,\n\t\t\tsocketRoute,\n\t\t\tsocketServerRequest,\n\t\t\thttpResponse,\n\t\t\tcontextIds,\n\t\t\tprocessorState,\n\t\t\temitTopic,\n\t\t\tasync (topic, response) => {\n\t\t\t\tsocket.emit(topic, response);\n\t\t\t}\n\t\t);\n\t}\n\n\t/**\n\t * Run the socket processors for the route.\n\t * @param socketId The id of the socket.\n\t * @param socketRouteProcessors The processors to run.\n\t * @param socketRoute The route to process.\n\t * @param socketServerRequest The incoming request.\n\t * @param httpResponse The outgoing response.\n\t * @param contextIds The context IDs of the request.\n\t * @param processorState The state handed through the processors.\n\t * @param requestTopic The topic of the request.\n\t * @internal\n\t */\n\tprivate async runProcessorsSocket(\n\t\tsocketRouteProcessors: ISocketRouteProcessor[],\n\t\tsocketRoute: ISocketRoute,\n\t\tsocketServerRequest: ISocketServerRequest,\n\t\thttpResponse: IHttpResponse,\n\t\tcontextIds: IContextIds,\n\t\tprocessorState: {\n\t\t\t[id: string]: unknown;\n\t\t},\n\t\trequestTopic: string,\n\t\tresponseEmitter: (topic: string, response: IHttpResponse) => Promise<void>\n\t): Promise<void> {\n\t\tconst filteredProcessors = this.filterRouteProcessors(socketRoute, socketRouteProcessors);\n\n\t\t// Custom emit method which will also call the post processors\n\t\tconst postProcessEmit = async (\n\t\t\ttopic: string,\n\t\t\tresponse: IHttpResponse,\n\t\t\tresponseProcessorState: {\n\t\t\t\t[id: string]: unknown;\n\t\t\t}\n\t\t): Promise<void> => {\n\t\t\tawait responseEmitter(topic, response);\n\n\t\t\ttry {\n\t\t\t\t// The post processors are called after the response has been emitted\n\t\t\t\tfor (const postSocketRouteProcessor of filteredProcessors) {\n\t\t\t\t\tconst post = postSocketRouteProcessor.post?.bind(postSocketRouteProcessor);\n\t\t\t\t\tif (Is.function(post)) {\n\t\t\t\t\t\tawait post(\n\t\t\t\t\t\t\tsocketServerRequest,\n\t\t\t\t\t\t\tresponse,\n\t\t\t\t\t\t\tsocketRoute,\n\t\t\t\t\t\t\tcontextIds,\n\t\t\t\t\t\t\tresponseProcessorState,\n\t\t\t\t\t\t\tthis._loggingComponentType\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tawait this._logging?.log({\n\t\t\t\t\tlevel: \"error\",\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tsource: FastifyWebServer.CLASS_NAME,\n\t\t\t\t\tmessage: \"postProcessorError\",\n\t\t\t\t\terror: BaseError.fromError(err),\n\t\t\t\t\tdata: {\n\t\t\t\t\t\troute: socketRoute.path\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\n\t\ttry {\n\t\t\tfor (const socketRouteProcessor of filteredProcessors) {\n\t\t\t\tconst pre = socketRouteProcessor.pre?.bind(socketRouteProcessor);\n\t\t\t\tif (Is.function(pre)) {\n\t\t\t\t\tawait pre(\n\t\t\t\t\t\tsocketServerRequest,\n\t\t\t\t\t\thttpResponse,\n\t\t\t\t\t\tsocketRoute,\n\t\t\t\t\t\tcontextIds,\n\t\t\t\t\t\tprocessorState,\n\t\t\t\t\t\tthis._loggingComponentType\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// We always call all the processors regardless of any response set by a previous processor.\n\t\t\t// But if a pre processor sets a status code, we will emit the response manually, as the pre\n\t\t\t// and post processors do not receive the emit method, they just populate the response object.\n\t\t\tif (!Is.empty(httpResponse.statusCode)) {\n\t\t\t\tawait postProcessEmit(requestTopic, httpResponse, processorState);\n\t\t\t}\n\n\t\t\tawait ContextIdStore.run(contextIds, async () => {\n\t\t\t\tfor (const socketRouteProcessor of filteredProcessors) {\n\t\t\t\t\tconst process = socketRouteProcessor.process?.bind(socketRouteProcessor);\n\t\t\t\t\tif (Is.function(process)) {\n\t\t\t\t\t\tawait process(\n\t\t\t\t\t\t\tsocketServerRequest,\n\t\t\t\t\t\t\thttpResponse,\n\t\t\t\t\t\t\tsocketRoute,\n\t\t\t\t\t\t\tprocessorState,\n\t\t\t\t\t\t\tasync (topic: string, processResponse: IHttpResponse) => {\n\t\t\t\t\t\t\t\tawait postProcessEmit(topic, processResponse, processorState);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tthis._loggingComponentType\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// If the processors set the status to any kind of error then we should emit this manually\n\t\t\tif (\n\t\t\t\tIs.integer(httpResponse.statusCode) &&\n\t\t\t\thttpResponse.statusCode >= HttpStatusCode.badRequest\n\t\t\t) {\n\t\t\t\tawait postProcessEmit(requestTopic, httpResponse, processorState);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\t// Emit any unhandled errors manually\n\t\t\tconst { error, httpStatusCode } = HttpErrorHelper.processError(err, this._includeErrorStack);\n\t\t\tHttpErrorHelper.buildResponse(httpResponse, error, httpStatusCode);\n\t\t\tawait postProcessEmit(requestTopic, httpResponse, processorState);\n\t\t}\n\t}\n\n\t/**\n\t * Initialize the cors options.\n\t * @param options The web server options.\n\t * @internal\n\t */\n\tprivate async initCors(options?: IWebServerOptions): Promise<void> {\n\t\tlet origins: string[] = [\"*\"];\n\n\t\tif (Is.arrayValue(options?.corsOrigins)) {\n\t\t\torigins = options?.corsOrigins;\n\t\t} else if (Is.stringValue(options?.corsOrigins)) {\n\t\t\torigins = [options?.corsOrigins];\n\t\t}\n\n\t\tconst hasWildcardOrigin = origins.includes(\"*\");\n\n\t\tconst methods = options?.methods ?? [\n\t\t\tHttpMethod.GET,\n\t\t\tHttpMethod.PUT,\n\t\t\tHttpMethod.POST,\n\t\t\tHttpMethod.DELETE,\n\t\t\tHttpMethod.OPTIONS\n\t\t];\n\t\tconst allowedHeaders = [\n\t\t\t\"Access-Control-Allow-Origin\",\n\t\t\t\"Content-Encoding\",\n\t\t\t\"Accept-Encoding\",\n\t\t\tHeaderTypes.ContentType,\n\t\t\tHeaderTypes.Authorization,\n\t\t\tHeaderTypes.Accept\n\t\t];\n\t\tconst exposedHeaders: string[] = [HeaderTypes.ContentDisposition, HeaderTypes.Location];\n\n\t\tif (Is.arrayValue(options?.allowedHeaders)) {\n\t\t\tallowedHeaders.push(...options.allowedHeaders);\n\t\t}\n\t\tif (Is.arrayValue(options?.exposedHeaders)) {\n\t\t\texposedHeaders.push(...options.exposedHeaders);\n\t\t}\n\n\t\tawait this._fastify.register(FastifyCors, {\n\t\t\torigin: (origin, callback) => {\n\t\t\t\tcallback(null, hasWildcardOrigin ? true : origins.includes(origin as string));\n\t\t\t},\n\t\t\tmethods,\n\t\t\tallowedHeaders,\n\t\t\texposedHeaders,\n\t\t\tcredentials: true\n\t\t});\n\t}\n}\n"]}
|
package/dist/es/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Copyright 2024 IOTA Stiftung.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
export * from "./fastifyWebServer.js";
|
|
4
|
+
export * from "./models/IFastifyWebServerConfig.js";
|
|
5
|
+
export * from "./models/IFastifyWebServerConstructorOptions.js";
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qCAAqC,CAAC;AACpD,cAAc,iDAAiD,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nexport * from \"./fastifyWebServer.js\";\nexport * from \"./models/IFastifyWebServerConfig.js\";\nexport * from \"./models/IFastifyWebServerConstructorOptions.js\";\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IFastifyWebServerConfig.js","sourceRoot":"","sources":["../../../src/models/IFastifyWebServerConfig.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { FastifyServerOptions } from \"fastify\";\nimport type { ServerOptions } from \"socket.io\";\n\n/**\n * The configuration for the Fastify web server.\n */\nexport interface IFastifyWebServerConfig {\n\t/**\n\t * The web server options.\n\t */\n\tweb?: Partial<FastifyServerOptions>;\n\n\t/**\n\t * The socket server options.\n\t */\n\tsocket?: Partial<ServerOptions>;\n\n\t/**\n\t * Include the stack with errors.\n\t */\n\tincludeErrorStack?: boolean;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IFastifyWebServerConstructorOptions.js","sourceRoot":"","sources":["../../../src/models/IFastifyWebServerConstructorOptions.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IMimeTypeProcessor } from \"@twin.org/api-models\";\nimport type { IFastifyWebServerConfig } from \"./IFastifyWebServerConfig.js\";\n\n/**\n * The options for the Fastify web server constructor.\n */\nexport interface IFastifyWebServerConstructorOptions {\n\t/**\n\t * The type of the logging component to use, if undefined, no logging will happen.\n\t */\n\tloggingComponentType?: string;\n\n\t/**\n\t * Additional configuration for the server.\n\t */\n\tconfig?: IFastifyWebServerConfig;\n\n\t/**\n\t * Additional MIME type processors.\n\t */\n\tmimeTypeProcessors?: IMimeTypeProcessor[];\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type IRestRoute, type IRestRouteProcessor, type ISocketRoute, type ISocketRouteProcessor, type IWebServer, type IWebServerOptions } from "@twin.org/api-models";
|
|
2
2
|
import { type FastifyInstance } from "fastify";
|
|
3
|
-
import type { IFastifyWebServerConstructorOptions } from "./models/IFastifyWebServerConstructorOptions";
|
|
3
|
+
import type { IFastifyWebServerConstructorOptions } from "./models/IFastifyWebServerConstructorOptions.js";
|
|
4
4
|
/**
|
|
5
5
|
* Implementation of the web server using Fastify.
|
|
6
6
|
*/
|
|
@@ -8,7 +8,7 @@ export declare class FastifyWebServer implements IWebServer<FastifyInstance> {
|
|
|
8
8
|
/**
|
|
9
9
|
* Runtime name for the class.
|
|
10
10
|
*/
|
|
11
|
-
readonly CLASS_NAME: string;
|
|
11
|
+
static readonly CLASS_NAME: string;
|
|
12
12
|
/**
|
|
13
13
|
* Create a new instance of FastifyWebServer.
|
|
14
14
|
* @param options The options for the server.
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export * from "./fastifyWebServer";
|
|
2
|
-
export * from "./models/IFastifyWebServerConfig";
|
|
3
|
-
export * from "./models/IFastifyWebServerConstructorOptions";
|
|
1
|
+
export * from "./fastifyWebServer.js";
|
|
2
|
+
export * from "./models/IFastifyWebServerConfig.js";
|
|
3
|
+
export * from "./models/IFastifyWebServerConstructorOptions.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { IMimeTypeProcessor } from "@twin.org/api-models";
|
|
2
|
-
import type { IFastifyWebServerConfig } from "./IFastifyWebServerConfig";
|
|
2
|
+
import type { IFastifyWebServerConfig } from "./IFastifyWebServerConfig.js";
|
|
3
3
|
/**
|
|
4
4
|
* The options for the Fastify web server constructor.
|
|
5
5
|
*/
|