@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 ADDED
@@ -0,0 +1,3 @@
1
+ # Domain-Driven Design TypeScript Utilities / Fastify
2
+
3
+ Module generating Fastify API based on annotations generated by `@pjts/core`
@@ -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"}
@@ -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"}
@@ -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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"}
@@ -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,3 @@
1
+ import { FastifyInstance } from 'fastify';
2
+ export declare const getIpAddress: (req: any) => string | null;
3
+ export declare const withIpAddress: (server: FastifyInstance) => void;
@@ -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,2 @@
1
+ import { FastifyInstance } from 'fastify';
2
+ export declare const withLogger: (server: FastifyInstance) => void;
@@ -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
+ }