@rest-vir/run-service 0.6.0 → 0.8.0
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.
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { assertWrap } from '@augment-vir/assert';
|
|
2
2
|
import { ensureErrorAndPrependMessage, extractErrorMessage, HttpStatus, stringify, wrapInTry, } from '@augment-vir/common';
|
|
3
|
-
import { matchUrlToService, restVirServiceNameHeader, } from '@rest-vir/define-service';
|
|
3
|
+
import { isFormDataShape, matchUrlToService, restVirServiceNameHeader, } from '@rest-vir/define-service';
|
|
4
4
|
import { HttpMethod, RestVirHandlerError, } from '@rest-vir/implement-service';
|
|
5
5
|
import { assertValidShape, isValidShape } from 'object-shape-tester';
|
|
6
6
|
import { handleHandlerResult } from './endpoint-handler.js';
|
|
@@ -55,7 +55,7 @@ export async function preHandler(request, response, service, attachId) {
|
|
|
55
55
|
}), response).responseSent) {
|
|
56
56
|
return;
|
|
57
57
|
}
|
|
58
|
-
const requestData = wrapInTry(() => extractRequestData(request.body, route));
|
|
58
|
+
const requestData = wrapInTry(() => extractRequestData(request.body, request.headers, route));
|
|
59
59
|
if (requestData instanceof Error) {
|
|
60
60
|
service.logger.error(new RestVirHandlerError(route, `Rejected request body from '${request.originalUrl}': ${stringify(requestData)}`));
|
|
61
61
|
response.statusCode = HttpStatus.BadRequest;
|
|
@@ -102,7 +102,7 @@ export async function preHandler(request, response, service, attachId) {
|
|
|
102
102
|
throw ensureErrorAndPrependMessage(error, 'Failed to generate request context.');
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
|
-
function extractRequestData(body, route) {
|
|
105
|
+
function extractRequestData(body, headers, route) {
|
|
106
106
|
const dataShape = 'requestDataShape' in route ? route.requestDataShape : undefined;
|
|
107
107
|
if (!dataShape) {
|
|
108
108
|
if (body) {
|
|
@@ -112,7 +112,10 @@ function extractRequestData(body, route) {
|
|
|
112
112
|
return undefined;
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
|
-
if (
|
|
115
|
+
if (isFormDataShape(dataShape.shape) && headers['content-type'] === 'multipart/form-data') {
|
|
116
|
+
return body;
|
|
117
|
+
}
|
|
118
|
+
else if (!isValidShape(body, dataShape, {
|
|
116
119
|
/** Allow extra keys for forwards / backwards compatibility. */
|
|
117
120
|
allowExtraKeys: true,
|
|
118
121
|
})) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type SelectFrom } from '@augment-vir/common';
|
|
2
2
|
import { GenericServiceImplementation } from '@rest-vir/implement-service';
|
|
3
3
|
import { ClusterManager, type WorkerRunner } from 'cluster-vir';
|
|
4
|
-
import { type FastifyInstance } from 'fastify';
|
|
4
|
+
import { type FastifyInstance, type FastifyPluginCallback } from 'fastify';
|
|
5
5
|
import { StartServiceUserOptions } from './start-service-options.js';
|
|
6
6
|
/**
|
|
7
7
|
* Output of {@link startService}.
|
|
@@ -42,6 +42,15 @@ export type StartServiceOutput = {
|
|
|
42
42
|
/** A function that will kill the service even if it's using multiple workers. */
|
|
43
43
|
kill: () => void;
|
|
44
44
|
};
|
|
45
|
+
/**
|
|
46
|
+
* A list of plugins and their options that will be registered on the internal fastify instance
|
|
47
|
+
* created by {@link startService}.
|
|
48
|
+
*
|
|
49
|
+
* @category Internal
|
|
50
|
+
* @category Package : @rest-vir/run-service
|
|
51
|
+
* @package [`@rest-vir/run-service`](https://www.npmjs.com/package/@rest-vir/run-service)
|
|
52
|
+
*/
|
|
53
|
+
export type FastifyPlugins = [plugin: FastifyPluginCallback, options?: any][];
|
|
45
54
|
/**
|
|
46
55
|
* Starts the given {@link ServiceImplementation} inside of a backend [Fastify
|
|
47
56
|
* server](https://www.npmjs.com/package/fastify).
|
|
@@ -60,4 +69,4 @@ export declare function startService(service: Readonly<SelectFrom<GenericService
|
|
|
60
69
|
serviceOrigin: true;
|
|
61
70
|
requiredClientOrigin: true;
|
|
62
71
|
logger: true;
|
|
63
|
-
}>>, userOptions?: Readonly<StartServiceUserOptions>): Promise<StartServiceOutput>;
|
|
72
|
+
}>>, userOptions?: Readonly<StartServiceUserOptions>, fastifyPlugins?: Readonly<FastifyPlugins>): Promise<StartServiceOutput>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { check } from '@augment-vir/assert';
|
|
2
|
+
import { awaitedForEach } from '@augment-vir/common';
|
|
2
3
|
import { ClusterManager, runInCluster } from 'cluster-vir';
|
|
3
4
|
import fastify from 'fastify';
|
|
4
5
|
import { getPortPromise } from 'portfinder';
|
|
@@ -14,7 +15,7 @@ import { finalizeOptions, } from './start-service-options.js';
|
|
|
14
15
|
* @category Package : @rest-vir/run-service
|
|
15
16
|
* @package [`@rest-vir/run-service`](https://www.npmjs.com/package/@rest-vir/run-service)
|
|
16
17
|
*/
|
|
17
|
-
export async function startService(service, userOptions = {}) {
|
|
18
|
+
export async function startService(service, userOptions = {}, fastifyPlugins = []) {
|
|
18
19
|
const options = finalizeOptions(service.serviceOrigin, userOptions);
|
|
19
20
|
const port = options.lockPort || check.isFalse(options.port)
|
|
20
21
|
? options.port
|
|
@@ -24,7 +25,7 @@ export async function startService(service, userOptions = {}) {
|
|
|
24
25
|
options.port = port;
|
|
25
26
|
if (options.workerCount === 1 || !check.isNumber(port)) {
|
|
26
27
|
/** Only run a single server. */
|
|
27
|
-
const result = await startServer(service, options);
|
|
28
|
+
const result = await startServer(service, options, fastifyPlugins);
|
|
28
29
|
if (options.port) {
|
|
29
30
|
service.logger.info(`${service.serviceName} started on http://localhost:${options.port}`);
|
|
30
31
|
}
|
|
@@ -33,7 +34,7 @@ export async function startService(service, userOptions = {}) {
|
|
|
33
34
|
else {
|
|
34
35
|
/** Run in a cluster. */
|
|
35
36
|
const manager = runInCluster(async () => {
|
|
36
|
-
const { kill } = await startServer(service, options);
|
|
37
|
+
const { kill } = await startServer(service, options, fastifyPlugins);
|
|
37
38
|
return () => {
|
|
38
39
|
kill();
|
|
39
40
|
};
|
|
@@ -68,8 +69,11 @@ export async function startService(service, userOptions = {}) {
|
|
|
68
69
|
}
|
|
69
70
|
}
|
|
70
71
|
}
|
|
71
|
-
async function startServer(service, { host, port }) {
|
|
72
|
+
async function startServer(service, { host, port }, fastifyPlugins) {
|
|
72
73
|
const server = fastify();
|
|
74
|
+
await awaitedForEach(fastifyPlugins, async ([plugin, options,]) => {
|
|
75
|
+
await server.register(plugin, options);
|
|
76
|
+
});
|
|
73
77
|
await attachService(server, service, {
|
|
74
78
|
throwErrorsForExternalHandling: false,
|
|
75
79
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rest-vir/run-service",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Run a service defined by @rest-vir/define-service and implemented by @rest-vir/implement-service.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"rest",
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
"@augment-vir/common": "^31.9.4",
|
|
44
44
|
"@augment-vir/node": "^31.9.4",
|
|
45
45
|
"@fastify/websocket": "^11.0.2",
|
|
46
|
-
"@rest-vir/define-service": "^0.
|
|
47
|
-
"@rest-vir/implement-service": "^0.
|
|
46
|
+
"@rest-vir/define-service": "^0.8.0",
|
|
47
|
+
"@rest-vir/implement-service": "^0.8.0",
|
|
48
48
|
"cluster-vir": "^0.1.0",
|
|
49
49
|
"date-vir": "^7.2.1",
|
|
50
50
|
"fastify": "^5.2.1",
|
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@augment-vir/test": "^31.9.4",
|
|
58
|
+
"@fastify/multipart": "^9.0.3",
|
|
58
59
|
"@types/connect": "^3.4.38",
|
|
59
60
|
"@types/node": "^22.13.9",
|
|
60
61
|
"@types/ws": "^8.18.0",
|