@pjts/fastify 0.0.77
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/README.md +3 -0
- package/dist/__test__/demo.d.ts +1 -0
- package/dist/__test__/demo.js +72 -0
- package/dist/__test__/demo.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/dist/router.d.ts +12 -0
- package/dist/router.js +87 -0
- package/dist/router.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.js +55 -0
- package/dist/server.js.map +1 -0
- package/dist/utils/withCatch.d.ts +22 -0
- package/dist/utils/withCatch.js +28 -0
- package/dist/utils/withCatch.js.map +1 -0
- package/dist/utils/withIpAddress.d.ts +3 -0
- package/dist/utils/withIpAddress.js +25 -0
- package/dist/utils/withIpAddress.js.map +1 -0
- package/dist/utils/withLogger.d.ts +2 -0
- package/dist/utils/withLogger.js +24 -0
- package/dist/utils/withLogger.js.map +1 -0
- package/package.json +48 -0
package/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var FileDto_1;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const core_1 = require("@pjts/core");
|
|
6
|
+
const index_1 = require("../index");
|
|
7
|
+
let String255 = class String255 {
|
|
8
|
+
value;
|
|
9
|
+
constructor(value) {
|
|
10
|
+
this.value = value;
|
|
11
|
+
}
|
|
12
|
+
toJSON() {
|
|
13
|
+
return this.value;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
String255 = tslib_1.__decorate([
|
|
17
|
+
core_1.StringDomainPrimitive,
|
|
18
|
+
tslib_1.__metadata("design:paramtypes", [String])
|
|
19
|
+
], String255);
|
|
20
|
+
let FileDto = FileDto_1 = class FileDto {
|
|
21
|
+
static fromUnknown(data) {
|
|
22
|
+
console.log(data);
|
|
23
|
+
return new FileDto_1();
|
|
24
|
+
}
|
|
25
|
+
toJSON() {
|
|
26
|
+
return {};
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
FileDto = FileDto_1 = tslib_1.__decorate([
|
|
30
|
+
core_1.ObjectDomainPrimitive
|
|
31
|
+
], FileDto);
|
|
32
|
+
let TestService = class TestService {
|
|
33
|
+
async upload(file1, other) {
|
|
34
|
+
console.log(file1);
|
|
35
|
+
console.log(other);
|
|
36
|
+
}
|
|
37
|
+
async other(watever) {
|
|
38
|
+
console.log(watever);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
tslib_1.__decorate([
|
|
42
|
+
core_1.Post,
|
|
43
|
+
tslib_1.__param(0, core_1.File),
|
|
44
|
+
tslib_1.__param(1, core_1.Body),
|
|
45
|
+
tslib_1.__metadata("design:type", Function),
|
|
46
|
+
tslib_1.__metadata("design:paramtypes", [FileDto, String255]),
|
|
47
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
48
|
+
], TestService.prototype, "upload", null);
|
|
49
|
+
tslib_1.__decorate([
|
|
50
|
+
core_1.Post,
|
|
51
|
+
tslib_1.__param(0, core_1.Body),
|
|
52
|
+
tslib_1.__metadata("design:type", Function),
|
|
53
|
+
tslib_1.__metadata("design:paramtypes", [String255]),
|
|
54
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
55
|
+
], TestService.prototype, "other", null);
|
|
56
|
+
TestService = tslib_1.__decorate([
|
|
57
|
+
core_1.AppService
|
|
58
|
+
], TestService);
|
|
59
|
+
let TestModule =
|
|
60
|
+
// @ts-ignore
|
|
61
|
+
class TestModule {
|
|
62
|
+
get testService() {
|
|
63
|
+
return new TestService();
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
TestModule = tslib_1.__decorate([
|
|
67
|
+
(0, core_1.HttpModule)('/v1')
|
|
68
|
+
// @ts-ignore
|
|
69
|
+
], TestModule);
|
|
70
|
+
const server = (0, index_1.buildServer)([new TestModule()], 3019);
|
|
71
|
+
server.start('*');
|
|
72
|
+
//# sourceMappingURL=demo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demo.js","sourceRoot":"","sources":["../../src/__test__/demo.ts"],"names":[],"mappings":";;;;AAAA,qCAQmB;AACnB,oCAAuC;AAEvC,IACM,SAAS,GADf,MACM,SAAS;IACe;IAA5B,YAA4B,KAAa;QAAb,UAAK,GAAL,KAAK,CAAQ;IAAI,CAAC;IAEvC,MAAM;QACX,OAAO,IAAI,CAAC,KAAK,CAAA;IACnB,CAAC;CACF,CAAA;AANK,SAAS;IADd,4BAAqB;;GAChB,SAAS,CAMd;AAGD,IAAM,OAAO,eAAb,MAAM,OAAO;IACJ,MAAM,CAAC,WAAW,CAAC,IAAS;QACjC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACjB,OAAO,IAAI,SAAO,EAAE,CAAA;IACtB,CAAC;IAEM,MAAM;QACX,OAAO,EAAE,CAAA;IACX,CAAC;CACF,CAAA;AATK,OAAO;IADZ,4BAAqB;GAChB,OAAO,CASZ;AAGD,IAAM,WAAW,GAAjB,MAAM,WAAW;IAEF,AAAN,KAAK,CAAC,MAAM,CAAO,KAAc,EAAQ,KAAgB;QAC9D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QAClB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;IACpB,CAAC;IAGY,AAAN,KAAK,CAAC,KAAK,CAAO,OAAkB;QACzC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IACtB,CAAC;CACF,CAAA;AATc;IADZ,WAAI;IACgB,mBAAA,WAAI,CAAA;IAAkB,mBAAA,WAAI,CAAA;;6CAAd,OAAO,EAAe,SAAS;;yCAG/D;AAGY;IADZ,WAAI;IACe,mBAAA,WAAI,CAAA;;6CAAU,SAAS;;wCAE1C;AAVG,WAAW;IADhB,iBAAU;GACL,WAAW,CAWhB;AAID,IAAM,UAAU;AADhB,aAAa;AACb,MAAM,UAAU;IACd,IAAW,WAAW;QACpB,OAAO,IAAI,WAAW,EAAE,CAAA;IAC1B,CAAC;CACF,CAAA;AAJK,UAAU;IAFf,IAAA,iBAAU,EAAC,KAAK,CAAC;IAClB,aAAa;GACP,UAAU,CAIf;AAED,MAAM,MAAM,GAAG,IAAA,mBAAW,EAAC,CAAC,IAAI,UAAU,EAAE,CAAC,EAAE,IAAI,CAAC,CAAA;AAEpD,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { AppModule } from '@pjts/core';
|
|
2
|
+
import { ErrorDescriptor } from './router';
|
|
3
|
+
import { OpenAPIObject } from 'openapi3-ts';
|
|
4
|
+
import { Description } from '@pjts/swagger';
|
|
5
|
+
export declare const buildServer: <T extends AppModule<T>>(appModules: T[], port: number, prefix?: string) => {
|
|
6
|
+
start: (allowOrigin: string, logTraffic?: boolean) => Promise<void>;
|
|
7
|
+
stop: () => any;
|
|
8
|
+
getSchema: (description: Description) => OpenAPIObject;
|
|
9
|
+
onError(handler: (error: ErrorDescriptor) => void): void;
|
|
10
|
+
};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildServer = void 0;
|
|
4
|
+
const server_1 = require("./server");
|
|
5
|
+
const router_1 = require("./router");
|
|
6
|
+
const swagger_1 = require("@pjts/swagger");
|
|
7
|
+
const buildServer = (appModules, port, prefix = '/') => {
|
|
8
|
+
let stop;
|
|
9
|
+
const errorHandlers = [];
|
|
10
|
+
return {
|
|
11
|
+
start: async (allowOrigin, logTraffic = false) => {
|
|
12
|
+
stop = await (0, server_1.startServer)(server => {
|
|
13
|
+
appModules.forEach(appModule => {
|
|
14
|
+
(0, router_1.registerRoutes)(server, appModule, prefix, error => {
|
|
15
|
+
errorHandlers.forEach(handler => handler(error));
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
}, port, allowOrigin, prefix, logTraffic);
|
|
19
|
+
},
|
|
20
|
+
stop: () => {
|
|
21
|
+
if (stop) {
|
|
22
|
+
return stop();
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
getSchema: (description) => {
|
|
26
|
+
return (0, swagger_1.buildOpenAPISchema)(appModules, port, description, prefix);
|
|
27
|
+
},
|
|
28
|
+
onError(handler) {
|
|
29
|
+
errorHandlers.push(handler);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
exports.buildServer = buildServer;
|
|
34
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,qCAAsC;AACtC,qCAA0D;AAE1D,2CAA+D;AAExD,MAAM,WAAW,GAAG,CAAyB,UAAe,EAAE,IAAY,EAAE,MAAM,GAAG,GAAG,EAAE,EAAE;IACjG,IAAI,IAAI,CAAA;IACR,MAAM,aAAa,GAA4C,EAAE,CAAA;IACjE,OAAO;QACL,KAAK,EAAE,KAAK,EAAE,WAAmB,EAAE,UAAU,GAAG,KAAK,EAAE,EAAE;YACvD,IAAI,GAAG,MAAM,IAAA,oBAAW,EACtB,MAAM,CAAC,EAAE;gBACP,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE;oBAC7B,IAAA,uBAAc,EAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE;wBAChD,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAA;oBAClD,CAAC,CAAC,CAAA;gBACJ,CAAC,CAAC,CAAA;YACJ,CAAC,EACD,IAAI,EACJ,WAAW,EACX,MAAM,EACN,UAAU,CACX,CAAA;QACH,CAAC;QACD,IAAI,EAAE,GAAG,EAAE;YACT,IAAI,IAAI,EAAE;gBACR,OAAO,IAAI,EAAE,CAAA;aACd;QACH,CAAC;QACD,SAAS,EAAE,CAAC,WAAwB,EAAiB,EAAE;YACrD,OAAO,IAAA,4BAAkB,EAAC,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,CAAC,CAAA;QAClE,CAAC;QACD,OAAO,CAAC,OAAyC;YAC/C,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAC7B,CAAC;KACF,CAAA;AACH,CAAC,CAAA;AA/BY,QAAA,WAAW,eA+BvB"}
|
package/dist/router.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { FastifyInstance } from 'fastify';
|
|
2
|
+
import { AppModule } from '@pjts/core';
|
|
3
|
+
export interface ErrorDescriptor {
|
|
4
|
+
timestamp: string;
|
|
5
|
+
prefix: string;
|
|
6
|
+
url: string;
|
|
7
|
+
service: string;
|
|
8
|
+
method: string;
|
|
9
|
+
httpMethod: string;
|
|
10
|
+
error: any;
|
|
11
|
+
}
|
|
12
|
+
export declare const registerRoutes: (server: FastifyInstance, appModule: AppModule<any>, prefix: string, onError: (errorDescriptor: ErrorDescriptor) => void) => void;
|
package/dist/router.js
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerRoutes = void 0;
|
|
4
|
+
const core_1 = require("@pjts/core");
|
|
5
|
+
const withCatch_1 = require("./utils/withCatch");
|
|
6
|
+
const getMultipartData = async (req, params) => {
|
|
7
|
+
const hasFiles = params.some(p => p.source === 'file');
|
|
8
|
+
try {
|
|
9
|
+
const data = {};
|
|
10
|
+
const files = hasFiles ? req.files() : [];
|
|
11
|
+
for await (const part of files) {
|
|
12
|
+
if (part.type === 'file') {
|
|
13
|
+
data[part.fieldname] = {
|
|
14
|
+
field: part.fieldname,
|
|
15
|
+
fileName: part.filename,
|
|
16
|
+
mimeType: part.mimetype,
|
|
17
|
+
buffer: await part.toBuffer(),
|
|
18
|
+
};
|
|
19
|
+
Object.entries(part.fields).forEach((entry) => {
|
|
20
|
+
if (entry[1].type === 'field') {
|
|
21
|
+
data[entry[0]] = entry[1].value;
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
data[part.fieldname] = part.value;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return data;
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
throw core_1.AppError.badRequest(err.code);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
const registerRoutes = (server, appModule, prefix, onError) => {
|
|
36
|
+
const moduleDescriptor = (0, core_1.getModuleDescriptor)(appModule);
|
|
37
|
+
moduleDescriptor.routes.forEach(route => {
|
|
38
|
+
route.endpoints.forEach(endpoint => {
|
|
39
|
+
const methodName = (0, core_1.getServiceMethodName)(route);
|
|
40
|
+
const url = (0, core_1.buildServerUrl)(moduleDescriptor, route, endpoint, prefix);
|
|
41
|
+
server.route({
|
|
42
|
+
method: endpoint.httpMethod,
|
|
43
|
+
url,
|
|
44
|
+
handler: (0, withCatch_1.withCatch)(async (req, reply) => {
|
|
45
|
+
if (process.env.LOG_FASTIFY_REQUESTS === 'true') {
|
|
46
|
+
console.log(JSON.stringify({
|
|
47
|
+
endpoint,
|
|
48
|
+
method: endpoint.httpMethod,
|
|
49
|
+
url,
|
|
50
|
+
headers: req.headers,
|
|
51
|
+
params: req.params,
|
|
52
|
+
body: req.body,
|
|
53
|
+
}));
|
|
54
|
+
}
|
|
55
|
+
const multipartData = await getMultipartData(req, endpoint.params);
|
|
56
|
+
const args = endpoint.params
|
|
57
|
+
.map(param => param.builder({
|
|
58
|
+
...multipartData,
|
|
59
|
+
...(param.source === 'middleware' ? req : req[param.source]),
|
|
60
|
+
}));
|
|
61
|
+
const response = await appModule[methodName][endpoint.method](...args);
|
|
62
|
+
if (typeof response === 'function') {
|
|
63
|
+
return await response(req, reply);
|
|
64
|
+
}
|
|
65
|
+
reply
|
|
66
|
+
.headers({ 'content-type': 'application/json' })
|
|
67
|
+
.status(endpoint.status)
|
|
68
|
+
.send({
|
|
69
|
+
data: await response,
|
|
70
|
+
});
|
|
71
|
+
}, error => {
|
|
72
|
+
onError({
|
|
73
|
+
timestamp: new Date().toISOString(),
|
|
74
|
+
prefix: moduleDescriptor.prefix,
|
|
75
|
+
service: route.name,
|
|
76
|
+
url,
|
|
77
|
+
httpMethod: endpoint.httpMethod,
|
|
78
|
+
method: endpoint.method,
|
|
79
|
+
error: String(error),
|
|
80
|
+
});
|
|
81
|
+
}),
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
exports.registerRoutes = registerRoutes;
|
|
87
|
+
//# sourceMappingURL=router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { FastifyInstance } from 'fastify';
|
|
2
|
+
export type RouteBuilder = (server: FastifyInstance) => void;
|
|
3
|
+
export declare const startServer: (routeBuilder: RouteBuilder, port: number, allowOrigin: string, prefix: string, logTraffic?: boolean) => Promise<() => Promise<void>>;
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.startServer = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const fastify_1 = tslib_1.__importDefault(require("fastify"));
|
|
6
|
+
const cors_1 = tslib_1.__importDefault(require("@fastify/cors"));
|
|
7
|
+
const withIpAddress_1 = require("./utils/withIpAddress");
|
|
8
|
+
const withLogger_1 = require("./utils/withLogger");
|
|
9
|
+
const core_1 = require("@pjts/core");
|
|
10
|
+
const startServer = async (routeBuilder, port, allowOrigin, prefix, logTraffic = false) => {
|
|
11
|
+
const server = (0, fastify_1.default)({
|
|
12
|
+
bodyLimit: 10 * 1024 * 1000,
|
|
13
|
+
maxParamLength: 255,
|
|
14
|
+
logger: process.env.LOG_FASTIFY_REQUESTS === 'true',
|
|
15
|
+
});
|
|
16
|
+
/* Allow empty body on POST request */
|
|
17
|
+
server.addContentTypeParser('application/json', { parseAs: 'string' }, function (_req, body, done) {
|
|
18
|
+
try {
|
|
19
|
+
const json = JSON.parse(body);
|
|
20
|
+
done(null, json);
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
done(null, {});
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
server.register(cors_1.default, {
|
|
27
|
+
origin: allowOrigin,
|
|
28
|
+
exposedHeaders: ['content-type', 'authorization', 'content-length', 'content-disposition'],
|
|
29
|
+
});
|
|
30
|
+
if (logTraffic) {
|
|
31
|
+
(0, withLogger_1.withLogger)(server);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
(0, withIpAddress_1.withIpAddress)(server);
|
|
35
|
+
}
|
|
36
|
+
server.register(require('@fastify/multipart'), { prefix });
|
|
37
|
+
routeBuilder(server);
|
|
38
|
+
server.setNotFoundHandler((_, reply) => {
|
|
39
|
+
reply.code(404).send({
|
|
40
|
+
statusCode: 404,
|
|
41
|
+
message: 'Endpoint not found',
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
await server.listen({
|
|
45
|
+
port,
|
|
46
|
+
host: '0.0.0.0',
|
|
47
|
+
});
|
|
48
|
+
core_1.Logger.info(`HTTP Server running on port: ${port}, prefix: ${prefix}`);
|
|
49
|
+
return async () => {
|
|
50
|
+
await server.close();
|
|
51
|
+
core_1.Logger.info('Server stopped');
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
exports.startServer = startServer;
|
|
55
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";;;;AAAA,8DAAkD;AAClD,iEAAgC;AAChC,yDAAqD;AACrD,mDAA+C;AAC/C,qCAAmC;AAI5B,MAAM,WAAW,GAAG,KAAK,EAC9B,YAA0B,EAC1B,IAAY,EACZ,WAAmB,EACnB,MAAc,EACd,UAAU,GAAG,KAAK,EACY,EAAE;IAChC,MAAM,MAAM,GAAG,IAAA,iBAAO,EAAC;QACrB,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI;QAC3B,cAAc,EAAE,GAAG;QACnB,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,oBAAoB,KAAK,MAAM;KACpD,CAAC,CAAA;IAEF,sCAAsC;IACtC,MAAM,CAAC,oBAAoB,CAAC,kBAAkB,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,UAAU,IAAI,EAAE,IAAI,EAAE,IAAI;QAC/F,IAAI;YACF,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAc,CAAC,CAAA;YACvC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;SACjB;QAAC,OAAO,GAAG,EAAE;YACZ,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;SACf;IACH,CAAC,CAAC,CAAA;IAEF,MAAM,CAAC,QAAQ,CAAC,cAAI,EAAE;QACpB,MAAM,EAAE,WAAW;QACnB,cAAc,EAAE,CAAC,cAAc,EAAE,eAAe,EAAE,gBAAgB,EAAE,qBAAqB,CAAC;KAC3F,CAAC,CAAA;IAEF,IAAI,UAAU,EAAE;QACd,IAAA,uBAAU,EAAC,MAAM,CAAC,CAAA;KACnB;SAAM;QACL,IAAA,6BAAa,EAAC,MAAM,CAAC,CAAA;KACtB;IAED,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,oBAAoB,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,CAAA;IAE1D,YAAY,CAAC,MAAM,CAAC,CAAA;IAEpB,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE;QACrC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YACnB,UAAU,EAAE,GAAG;YACf,OAAO,EAAE,oBAAoB;SAC9B,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,MAAM,MAAM,CAAC,MAAM,CAAC;QAClB,IAAI;QACJ,IAAI,EAAE,SAAS;KAChB,CAAC,CAAA;IAEF,aAAM,CAAC,IAAI,CAAC,gCAAgC,IAAI,aAAa,MAAM,EAAE,CAAC,CAAA;IAEtE,OAAO,KAAK,IAAI,EAAE;QAChB,MAAM,MAAM,CAAC,KAAK,EAAE,CAAA;QACpB,aAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAA;IAC/B,CAAC,CAAA;AACH,CAAC,CAAA;AAxDY,QAAA,WAAW,eAwDvB"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
type Controller = (request: any, rep: any) => Promise<unknown>;
|
|
3
|
+
interface FileDescriptor {
|
|
4
|
+
type: string;
|
|
5
|
+
value: string;
|
|
6
|
+
filepath: string;
|
|
7
|
+
fieldname: string;
|
|
8
|
+
filename: string;
|
|
9
|
+
encoding: string;
|
|
10
|
+
mimetype: string;
|
|
11
|
+
fields: Record<string, FileDescriptor>;
|
|
12
|
+
toBuffer: () => Promise<Buffer>;
|
|
13
|
+
}
|
|
14
|
+
export interface Request {
|
|
15
|
+
headers: Record<string, string>;
|
|
16
|
+
params: Record<string, string>;
|
|
17
|
+
query: Record<string, string>;
|
|
18
|
+
body: Record<string, any>;
|
|
19
|
+
files: () => FileDescriptor[];
|
|
20
|
+
}
|
|
21
|
+
export declare const withCatch: (controller: Controller, onError: (error: Error) => void) => Controller;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withCatch = void 0;
|
|
4
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
5
|
+
const core_1 = require("@pjts/core");
|
|
6
|
+
const withCatch = (controller, onError) => async (request, reply) => {
|
|
7
|
+
try {
|
|
8
|
+
return await controller(request, reply);
|
|
9
|
+
}
|
|
10
|
+
catch (err) {
|
|
11
|
+
if (err.statusCode === 400 || err.statusCode >= 500) {
|
|
12
|
+
onError(err);
|
|
13
|
+
}
|
|
14
|
+
if (process.env.LOG_FASTIFY_REQUESTS === 'true') {
|
|
15
|
+
console.log(err);
|
|
16
|
+
}
|
|
17
|
+
if (err.statusCode) {
|
|
18
|
+
return reply.code(err.statusCode).send(err.toJSON());
|
|
19
|
+
}
|
|
20
|
+
core_1.Logger.error(err.toString());
|
|
21
|
+
return reply.code(500).send({
|
|
22
|
+
statusCode: 500,
|
|
23
|
+
message: 'Something went wrong. Please try again later.',
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
exports.withCatch = withCatch;
|
|
28
|
+
//# sourceMappingURL=withCatch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"withCatch.js","sourceRoot":"","sources":["../../src/utils/withCatch.ts"],"names":[],"mappings":";;;AAAA,uDAAuD;AACvD,qCAAmC;AAwB5B,MAAM,SAAS,GACpB,CAAC,UAAsB,EAAE,OAA+B,EAAc,EAAE,CACtE,KAAK,EAAE,OAAgB,EAAE,KAAU,EAAoB,EAAE;IACvD,IAAI;QACF,OAAO,MAAM,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;KACxC;IAAC,OAAO,GAAQ,EAAE;QACjB,IAAI,GAAG,CAAC,UAAU,KAAK,GAAG,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,EAAE;YACnD,OAAO,CAAC,GAAY,CAAC,CAAA;SACtB;QACD,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAoB,KAAK,MAAM,EAAE;YAC/C,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;SACjB;QACD,IAAI,GAAG,CAAC,UAAU,EAAE;YAClB,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAA;SACrD;QACD,aAAM,CAAC,KAAK,CAAE,GAAa,CAAC,QAAQ,EAAE,CAAC,CAAA;QACvC,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YAC1B,UAAU,EAAE,GAAG;YACf,OAAO,EAAE,+CAA+C;SACzD,CAAC,CAAA;KACH;AACH,CAAC,CAAA;AArBQ,QAAA,SAAS,aAqBjB"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withIpAddress = exports.getIpAddress = void 0;
|
|
4
|
+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
5
|
+
const getIpAddress = (req) => {
|
|
6
|
+
const ip = req.headers['x-forwarded-for'] || req.socket.remoteAddress || '';
|
|
7
|
+
if (ip === '::1') {
|
|
8
|
+
return '127.0.0.1';
|
|
9
|
+
}
|
|
10
|
+
else if (ip.slice(0, 7) == '::ffff:') {
|
|
11
|
+
return ip.slice(7);
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
return ip;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
exports.getIpAddress = getIpAddress;
|
|
18
|
+
const withIpAddress = (server) => {
|
|
19
|
+
server.addHook('onRequest', (req, _res, done) => {
|
|
20
|
+
req.ipAddress = (0, exports.getIpAddress)(req);
|
|
21
|
+
done();
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
exports.withIpAddress = withIpAddress;
|
|
25
|
+
//# sourceMappingURL=withIpAddress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"withIpAddress.js","sourceRoot":"","sources":["../../src/utils/withIpAddress.ts"],"names":[],"mappings":";;;AAGA,6EAA6E;AACtE,MAAM,YAAY,GAAG,CAAC,GAAQ,EAAiB,EAAE;IACtD,MAAM,EAAE,GAAW,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,aAAa,IAAI,EAAE,CAAA;IACnF,IAAI,EAAE,KAAK,KAAK,EAAE;QAChB,OAAO,WAAW,CAAA;KACnB;SAAM,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,SAAS,EAAE;QACtC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;KACnB;SAAM;QACL,OAAO,EAAE,CAAA;KACV;AACH,CAAC,CAAA;AATY,QAAA,YAAY,gBASxB;AAEM,MAAM,aAAa,GAAG,CAAC,MAAuB,EAAQ,EAAE;IAC7D,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,GAAQ,EAAE,IAAS,EAAE,IAAS,EAAE,EAAE;QAC7D,GAAG,CAAC,SAAS,GAAG,IAAA,oBAAY,EAAC,GAAG,CAAC,CAAA;QACjC,IAAI,EAAE,CAAA;IACR,CAAC,CAAC,CAAA;AACJ,CAAC,CAAA;AALY,QAAA,aAAa,iBAKzB"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withLogger = void 0;
|
|
4
|
+
const withIpAddress_1 = require("./withIpAddress");
|
|
5
|
+
const withLogger = (server) => {
|
|
6
|
+
server.addHook('onRequest', (req, _res, done) => {
|
|
7
|
+
req.receivedAt = Date.now();
|
|
8
|
+
req.ipAddress = (0, withIpAddress_1.getIpAddress)(req);
|
|
9
|
+
done();
|
|
10
|
+
});
|
|
11
|
+
server.addHook('onResponse', (req, res, done) => {
|
|
12
|
+
console.log([
|
|
13
|
+
new Date().toISOString(),
|
|
14
|
+
req.ipAddress,
|
|
15
|
+
req.raw.method,
|
|
16
|
+
req.raw.url,
|
|
17
|
+
res.statusCode,
|
|
18
|
+
`${req.receivedAt ? Date.now() - req.receivedAt : 0}ms`,
|
|
19
|
+
].join(' '));
|
|
20
|
+
done();
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
exports.withLogger = withLogger;
|
|
24
|
+
//# sourceMappingURL=withLogger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"withLogger.js","sourceRoot":"","sources":["../../src/utils/withLogger.ts"],"names":[],"mappings":";;;AAEA,mDAA4C;AAErC,MAAM,UAAU,GAAG,CAAC,MAAuB,EAAQ,EAAE;IAC1D,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,GAAQ,EAAE,IAAS,EAAE,IAAS,EAAE,EAAE;QAC7D,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAC3B,GAAG,CAAC,SAAS,GAAG,IAAA,4BAAY,EAAC,GAAG,CAAC,CAAA;QACjC,IAAI,EAAE,CAAA;IACR,CAAC,CAAC,CAAA;IACF,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,GAAQ,EAAE,GAAQ,EAAE,IAAS,EAAE,EAAE;QAC7D,OAAO,CAAC,GAAG,CACT;YACE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACxB,GAAG,CAAC,SAAS;YACb,GAAG,CAAC,GAAG,CAAC,MAAM;YACd,GAAG,CAAC,GAAG,CAAC,GAAG;YACX,GAAG,CAAC,UAAU;YACd,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI;SACxD,CAAC,IAAI,CAAC,GAAG,CAAC,CACZ,CAAA;QACD,IAAI,EAAE,CAAA;IACR,CAAC,CAAC,CAAA;AACJ,CAAC,CAAA;AAnBY,QAAA,UAAU,cAmBtB"}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pjts/fastify",
|
|
3
|
+
"version": "0.0.77",
|
|
4
|
+
"description": "Piotr Józefów DDD utility package",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"packageManager": "yarn@3.4.1",
|
|
8
|
+
"author": "Piotr Józefów",
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": "^18.14.0"
|
|
12
|
+
},
|
|
13
|
+
"engineStrict": true,
|
|
14
|
+
"scripts": {
|
|
15
|
+
"lint": "eslint src/ --ext .js,.jsx,.ts,.tsx",
|
|
16
|
+
"test": "NODE_ENV=test jest --coverage=false --verbose",
|
|
17
|
+
"test:watch": "NODE_ENV=test jest --coverage=false --watchAll --testNamePattern=",
|
|
18
|
+
"test:coverage": "yarn test --collectCoverage",
|
|
19
|
+
"build": "rm -rf ./dist && tsc",
|
|
20
|
+
"package": "npm run build && npm publish --access=public",
|
|
21
|
+
"prepare": "npm install @pjts/swagger@latest & npm version patch",
|
|
22
|
+
"demo": "ts-node src/__test__/demo.ts"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@types/jest": "^29.4.0",
|
|
26
|
+
"jest": "^29.4.2",
|
|
27
|
+
"prettier": "^2.8.4",
|
|
28
|
+
"ts-jest": "^29.0.5",
|
|
29
|
+
"ts-node": "^10.9.1",
|
|
30
|
+
"typescript": "^4.9.5"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@fastify/cors": "8.2.0",
|
|
34
|
+
"@fastify/multipart": "7.6.0",
|
|
35
|
+
"@fastify/swagger": "8.3.1",
|
|
36
|
+
"@fastify/swagger-ui": "1.3.0",
|
|
37
|
+
"@pjts/swagger": "^0.0.63",
|
|
38
|
+
"@types/express": "4.17.17",
|
|
39
|
+
"@types/node": "18.13.0",
|
|
40
|
+
"express": "4.18.2",
|
|
41
|
+
"fastify": "4.13.0",
|
|
42
|
+
"fastify-multer": "2.0.3",
|
|
43
|
+
"openapi3-ts": "3.1.2"
|
|
44
|
+
},
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"registry": "https://registry.npmjs.org"
|
|
47
|
+
}
|
|
48
|
+
}
|