@shadow-library/fastify 0.0.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/LICENSE +21 -0
- package/README.md +24 -0
- package/cjs/classes/default-error-handler.d.ts +12 -0
- package/cjs/classes/default-error-handler.js +40 -0
- package/cjs/classes/index.d.ts +1 -0
- package/cjs/classes/index.js +17 -0
- package/cjs/constants.d.ts +5 -0
- package/cjs/constants.js +8 -0
- package/cjs/decorators/http-controller.decorator.d.ts +1 -0
- package/cjs/decorators/http-controller.decorator.js +8 -0
- package/cjs/decorators/http-input.decorator.d.ts +17 -0
- package/cjs/decorators/http-input.decorator.js +46 -0
- package/cjs/decorators/http-output.decorator.d.ts +11 -0
- package/cjs/decorators/http-output.decorator.js +20 -0
- package/cjs/decorators/http-route.decorator.d.ts +23 -0
- package/cjs/decorators/http-route.decorator.js +35 -0
- package/cjs/decorators/index.d.ts +5 -0
- package/cjs/decorators/index.js +21 -0
- package/cjs/decorators/middleware.decorator.d.ts +11 -0
- package/cjs/decorators/middleware.decorator.js +21 -0
- package/cjs/index.d.ts +7 -0
- package/cjs/index.js +23 -0
- package/cjs/interfaces/error-handler.interface.d.ts +4 -0
- package/cjs/interfaces/error-handler.interface.js +2 -0
- package/cjs/interfaces/index.d.ts +4 -0
- package/cjs/interfaces/index.js +20 -0
- package/cjs/interfaces/middleware.interface.d.ts +9 -0
- package/cjs/interfaces/middleware.interface.js +2 -0
- package/cjs/interfaces/route-handler.interface.d.ts +4 -0
- package/cjs/interfaces/route-handler.interface.js +2 -0
- package/cjs/interfaces/server-metadata.interface.d.ts +24 -0
- package/cjs/interfaces/server-metadata.interface.js +2 -0
- package/cjs/module/error-response.dto.d.ts +10 -0
- package/cjs/module/error-response.dto.js +55 -0
- package/cjs/module/fastify-module.interface.d.ts +19 -0
- package/cjs/module/fastify-module.interface.js +2 -0
- package/cjs/module/fastify-router.d.ts +36 -0
- package/cjs/module/fastify-router.js +182 -0
- package/cjs/module/fastify.module.d.ts +7 -0
- package/cjs/module/fastify.module.js +41 -0
- package/cjs/module/fastify.utils.d.ts +7 -0
- package/cjs/module/fastify.utils.js +33 -0
- package/cjs/module/index.d.ts +3 -0
- package/cjs/module/index.js +19 -0
- package/cjs/package.json +1 -0
- package/cjs/server.error.d.ts +16 -0
- package/cjs/server.error.js +38 -0
- package/cjs/services/context.service.d.ts +13 -0
- package/cjs/services/context.service.js +57 -0
- package/cjs/services/index.d.ts +1 -0
- package/cjs/services/index.js +17 -0
- package/esm/classes/default-error-handler.d.ts +12 -0
- package/esm/classes/default-error-handler.js +36 -0
- package/esm/classes/index.d.ts +1 -0
- package/esm/classes/index.js +1 -0
- package/esm/constants.d.ts +5 -0
- package/esm/constants.js +5 -0
- package/esm/decorators/http-controller.decorator.d.ts +1 -0
- package/esm/decorators/http-controller.decorator.js +5 -0
- package/esm/decorators/http-input.decorator.d.ts +17 -0
- package/esm/decorators/http-input.decorator.js +34 -0
- package/esm/decorators/http-output.decorator.d.ts +11 -0
- package/esm/decorators/http-output.decorator.js +12 -0
- package/esm/decorators/http-route.decorator.d.ts +23 -0
- package/esm/decorators/http-route.decorator.js +23 -0
- package/esm/decorators/index.d.ts +5 -0
- package/esm/decorators/index.js +5 -0
- package/esm/decorators/middleware.decorator.d.ts +11 -0
- package/esm/decorators/middleware.decorator.js +15 -0
- package/esm/index.d.ts +7 -0
- package/esm/index.js +7 -0
- package/esm/interfaces/error-handler.interface.d.ts +4 -0
- package/esm/interfaces/error-handler.interface.js +1 -0
- package/esm/interfaces/index.d.ts +4 -0
- package/esm/interfaces/index.js +4 -0
- package/esm/interfaces/middleware.interface.d.ts +9 -0
- package/esm/interfaces/middleware.interface.js +1 -0
- package/esm/interfaces/route-handler.interface.d.ts +4 -0
- package/esm/interfaces/route-handler.interface.js +1 -0
- package/esm/interfaces/server-metadata.interface.d.ts +24 -0
- package/esm/interfaces/server-metadata.interface.js +1 -0
- package/esm/module/error-response.dto.d.ts +10 -0
- package/esm/module/error-response.dto.js +52 -0
- package/esm/module/fastify-module.interface.d.ts +19 -0
- package/esm/module/fastify-module.interface.js +1 -0
- package/esm/module/fastify-router.d.ts +36 -0
- package/esm/module/fastify-router.js +176 -0
- package/esm/module/fastify.module.d.ts +7 -0
- package/esm/module/fastify.module.js +37 -0
- package/esm/module/fastify.utils.d.ts +7 -0
- package/esm/module/fastify.utils.js +27 -0
- package/esm/module/index.d.ts +3 -0
- package/esm/module/index.js +3 -0
- package/esm/server.error.d.ts +16 -0
- package/esm/server.error.js +33 -0
- package/esm/services/context.service.d.ts +13 -0
- package/esm/services/context.service.js +54 -0
- package/esm/services/index.d.ts +1 -0
- package/esm/services/index.js +1 -0
- package/package.json +44 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 shadow-library
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Shadow Fastify Server
|
|
2
|
+
|
|
3
|
+
This TypeScript package is a powerful Node.js server implementation built as a wrapper around the Fastify package. It offers features such as body, query,
|
|
4
|
+
and URL parameter validation using AJV for speed, response formatting with fast-json-stringify, and a unified approach to authentication and authorization.
|
|
5
|
+
The package uses decorators to define controller classes and HTTP methods, and includes a render decorator for templating engine support.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
**Fastify Wrapper:** Built on top of the high-performance Fastify framework.
|
|
10
|
+
**Validation:** Fast validation for body, query, and URL parameters using AJV.
|
|
11
|
+
**Response Serialization:** Consistent serialization of response types with fast-json-stringify to ensure only expected fields are returned.
|
|
12
|
+
**Decorator-Based:** Use decorators to define controllers and HTTP methods.
|
|
13
|
+
**Authentication and Authorization:** Unified methods to implement authentication and authorization.
|
|
14
|
+
**Templating Support:** Render decorator for integrating templating engines.
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
import {} from '@shadow-library/server';
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## License
|
|
23
|
+
|
|
24
|
+
This package is licensed under the MIT License. See the `LICENSE` file for more information.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { AppErrorObject } from '@shadow-library/common';
|
|
2
|
+
import { FastifyError } from 'fastify';
|
|
3
|
+
import { ErrorHandler, HttpRequest, HttpResponse } from '../interfaces/index.js';
|
|
4
|
+
export interface ParsedFastifyError {
|
|
5
|
+
statusCode: number;
|
|
6
|
+
error: AppErrorObject;
|
|
7
|
+
}
|
|
8
|
+
export declare class DefaultErrorHandler implements ErrorHandler {
|
|
9
|
+
private readonly logger;
|
|
10
|
+
protected parseFastifyError(err: FastifyError): ParsedFastifyError;
|
|
11
|
+
handle(err: Error, _req: HttpRequest, res: HttpResponse): HttpResponse;
|
|
12
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DefaultErrorHandler = void 0;
|
|
4
|
+
const common_1 = require("@shadow-library/common");
|
|
5
|
+
const server_error_1 = require("../server.error.js");
|
|
6
|
+
const unexpectedError = new server_error_1.ServerError(server_error_1.ServerErrorCode.S001);
|
|
7
|
+
const validationError = new server_error_1.ServerError(server_error_1.ServerErrorCode.S003);
|
|
8
|
+
class DefaultErrorHandler {
|
|
9
|
+
logger = common_1.Logger.getLogger(DefaultErrorHandler.name);
|
|
10
|
+
parseFastifyError(err) {
|
|
11
|
+
if (err.statusCode === 500)
|
|
12
|
+
return { statusCode: 500, error: unexpectedError.toObject() };
|
|
13
|
+
return {
|
|
14
|
+
statusCode: err.statusCode,
|
|
15
|
+
error: {
|
|
16
|
+
code: err.code,
|
|
17
|
+
type: common_1.ErrorType.CLIENT_ERROR,
|
|
18
|
+
message: err.message,
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
handle(err, _req, res) {
|
|
23
|
+
this.logger.warn('Handling error', err);
|
|
24
|
+
if (err.cause)
|
|
25
|
+
this.logger.warn('Caused by:', err.cause);
|
|
26
|
+
if (err instanceof server_error_1.ServerError)
|
|
27
|
+
return res.status(err.getStatusCode()).send(err.toObject());
|
|
28
|
+
else if (err instanceof common_1.ValidationError)
|
|
29
|
+
return res.status(400).send({ ...err.toObject(), code: validationError.getCode() });
|
|
30
|
+
else if (err instanceof common_1.AppError)
|
|
31
|
+
return res.status(500).send(err.toObject());
|
|
32
|
+
else if (err.name === 'FastifyError') {
|
|
33
|
+
const { statusCode, error } = this.parseFastifyError(err);
|
|
34
|
+
return res.status(statusCode).send(error);
|
|
35
|
+
}
|
|
36
|
+
this.logger.error('Unhandler error has occurred:', err);
|
|
37
|
+
return res.status(500).send(unexpectedError.toObject());
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.DefaultErrorHandler = DefaultErrorHandler;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './default-error-handler.js';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./default-error-handler.js"), exports);
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const PARAMTYPES_METADATA = "design:paramtypes";
|
|
2
|
+
export declare const FASTIFY_CONFIG: unique symbol;
|
|
3
|
+
export declare const FASTIFY_INSTANCE: unique symbol;
|
|
4
|
+
export declare const HTTP_CONTROLLER_TYPE: unique symbol;
|
|
5
|
+
export declare const HTTP_CONTROLLER_INPUTS: unique symbol;
|
package/cjs/constants.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HTTP_CONTROLLER_INPUTS = exports.HTTP_CONTROLLER_TYPE = exports.FASTIFY_INSTANCE = exports.FASTIFY_CONFIG = exports.PARAMTYPES_METADATA = void 0;
|
|
4
|
+
exports.PARAMTYPES_METADATA = 'design:paramtypes';
|
|
5
|
+
exports.FASTIFY_CONFIG = Symbol('fastify-config');
|
|
6
|
+
exports.FASTIFY_INSTANCE = Symbol('fastify-instance');
|
|
7
|
+
exports.HTTP_CONTROLLER_TYPE = Symbol('http-controller-type');
|
|
8
|
+
exports.HTTP_CONTROLLER_INPUTS = Symbol('http-controller-inputs');
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function HttpController(path?: string): ClassDecorator;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HttpController = HttpController;
|
|
4
|
+
const app_1 = require("@shadow-library/app");
|
|
5
|
+
const constants_1 = require("../constants.js");
|
|
6
|
+
function HttpController(path = '') {
|
|
7
|
+
return target => (0, app_1.Controller)({ [constants_1.HTTP_CONTROLLER_TYPE]: 'router', path })(target);
|
|
8
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { JSONSchema } from '@shadow-library/class-schema';
|
|
2
|
+
export declare enum RouteInputType {
|
|
3
|
+
BODY = "body",
|
|
4
|
+
PARAMS = "params",
|
|
5
|
+
QUERY = "query",
|
|
6
|
+
REQUEST = "request",
|
|
7
|
+
RESPONSE = "response"
|
|
8
|
+
}
|
|
9
|
+
export type RouteInputSchemas = Partial<Record<'body' | 'params' | 'query', JSONSchema>>;
|
|
10
|
+
export declare function HttpInput(type: RouteInputType, schema?: JSONSchema): ParameterDecorator;
|
|
11
|
+
export declare const Body: (schema?: JSONSchema) => ParameterDecorator;
|
|
12
|
+
export declare const Params: (schema?: JSONSchema) => ParameterDecorator;
|
|
13
|
+
export declare const Query: (schema?: JSONSchema) => ParameterDecorator;
|
|
14
|
+
export declare const Request: () => ParameterDecorator;
|
|
15
|
+
export declare const Req: () => ParameterDecorator;
|
|
16
|
+
export declare const Response: () => ParameterDecorator;
|
|
17
|
+
export declare const Res: () => ParameterDecorator;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Res = exports.Response = exports.Req = exports.Request = exports.Query = exports.Params = exports.Body = exports.RouteInputType = void 0;
|
|
7
|
+
exports.HttpInput = HttpInput;
|
|
8
|
+
const assert_1 = __importDefault(require("assert"));
|
|
9
|
+
const app_1 = require("@shadow-library/app");
|
|
10
|
+
const class_schema_1 = require("@shadow-library/class-schema");
|
|
11
|
+
const constants_1 = require("../constants.js");
|
|
12
|
+
var RouteInputType;
|
|
13
|
+
(function (RouteInputType) {
|
|
14
|
+
RouteInputType["BODY"] = "body";
|
|
15
|
+
RouteInputType["PARAMS"] = "params";
|
|
16
|
+
RouteInputType["QUERY"] = "query";
|
|
17
|
+
RouteInputType["REQUEST"] = "request";
|
|
18
|
+
RouteInputType["RESPONSE"] = "response";
|
|
19
|
+
})(RouteInputType || (exports.RouteInputType = RouteInputType = {}));
|
|
20
|
+
function HttpInput(type, schema) {
|
|
21
|
+
return (target, propertyKey, index) => {
|
|
22
|
+
(0, assert_1.default)(propertyKey, 'Cannot apply decorator to a constructor parameter');
|
|
23
|
+
const inputs = Reflect.getMetadata(constants_1.HTTP_CONTROLLER_INPUTS, target, propertyKey) ?? [];
|
|
24
|
+
Reflect.defineMetadata(constants_1.HTTP_CONTROLLER_INPUTS, inputs, target, propertyKey);
|
|
25
|
+
inputs[index] = type;
|
|
26
|
+
if (!schema) {
|
|
27
|
+
const paramTypes = Reflect.getMetadata(constants_1.PARAMTYPES_METADATA, target, propertyKey);
|
|
28
|
+
schema = class_schema_1.ClassSchema.generate(paramTypes[index]);
|
|
29
|
+
}
|
|
30
|
+
const descriptor = Reflect.getOwnPropertyDescriptor(target, propertyKey);
|
|
31
|
+
(0, assert_1.default)(descriptor, 'Cannot apply decorator to a non-method');
|
|
32
|
+
(0, app_1.Route)({ schemas: { [type]: schema } })(target, propertyKey, descriptor);
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
const Body = (schema) => HttpInput(RouteInputType.BODY, schema);
|
|
36
|
+
exports.Body = Body;
|
|
37
|
+
const Params = (schema) => HttpInput(RouteInputType.PARAMS, schema);
|
|
38
|
+
exports.Params = Params;
|
|
39
|
+
const Query = (schema) => HttpInput(RouteInputType.QUERY, schema);
|
|
40
|
+
exports.Query = Query;
|
|
41
|
+
const Request = () => HttpInput(RouteInputType.REQUEST);
|
|
42
|
+
exports.Request = Request;
|
|
43
|
+
exports.Req = exports.Request;
|
|
44
|
+
const Response = () => HttpInput(RouteInputType.RESPONSE);
|
|
45
|
+
exports.Response = Response;
|
|
46
|
+
exports.Res = exports.Response;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { JSONSchema, SchemaClass } from '@shadow-library/class-schema';
|
|
2
|
+
import { JsonObject } from 'type-fest';
|
|
3
|
+
export interface DynamicRender<T extends JsonObject> {
|
|
4
|
+
template: string;
|
|
5
|
+
data: T;
|
|
6
|
+
}
|
|
7
|
+
export declare const HttpStatus: (status: number) => MethodDecorator;
|
|
8
|
+
export declare const Header: (name: string, value: string | (() => string)) => MethodDecorator;
|
|
9
|
+
export declare const Redirect: (redirect: string, status?: number) => MethodDecorator;
|
|
10
|
+
export declare const Render: (render?: string) => MethodDecorator;
|
|
11
|
+
export declare function RespondFor(statusCode: number, schema: SchemaClass | JSONSchema): MethodDecorator;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Render = exports.Redirect = exports.Header = exports.HttpStatus = void 0;
|
|
4
|
+
exports.RespondFor = RespondFor;
|
|
5
|
+
const app_1 = require("@shadow-library/app");
|
|
6
|
+
const class_schema_1 = require("@shadow-library/class-schema");
|
|
7
|
+
const isClass = (schema) => schema.toString().startsWith('class ');
|
|
8
|
+
const HttpStatus = (status) => (0, app_1.Route)({ status });
|
|
9
|
+
exports.HttpStatus = HttpStatus;
|
|
10
|
+
const Header = (name, value) => (0, app_1.Route)({ headers: { [name]: value } });
|
|
11
|
+
exports.Header = Header;
|
|
12
|
+
const Redirect = (redirect, status = 301) => (0, app_1.Route)({ redirect, status });
|
|
13
|
+
exports.Redirect = Redirect;
|
|
14
|
+
const Render = (render) => (0, app_1.Route)({ render: render ?? true });
|
|
15
|
+
exports.Render = Render;
|
|
16
|
+
function RespondFor(statusCode, schema) {
|
|
17
|
+
if (isClass(schema))
|
|
18
|
+
schema = class_schema_1.ClassSchema.generate(schema);
|
|
19
|
+
return (0, app_1.Route)({ schemas: { response: { [statusCode]: schema } } });
|
|
20
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export declare enum HttpMethod {
|
|
2
|
+
GET = "GET",
|
|
3
|
+
POST = "POST",
|
|
4
|
+
PUT = "PUT",
|
|
5
|
+
DELETE = "DELETE",
|
|
6
|
+
PATCH = "PATCH",
|
|
7
|
+
OPTIONS = "OPTIONS",
|
|
8
|
+
HEAD = "HEAD",
|
|
9
|
+
ALL = "ALL"
|
|
10
|
+
}
|
|
11
|
+
export interface RouteOptions {
|
|
12
|
+
method: HttpMethod;
|
|
13
|
+
path?: string;
|
|
14
|
+
}
|
|
15
|
+
export declare function HttpRoute(options: RouteOptions): MethodDecorator;
|
|
16
|
+
export declare const Get: (path?: string) => MethodDecorator;
|
|
17
|
+
export declare const Post: (path?: string) => MethodDecorator;
|
|
18
|
+
export declare const Put: (path?: string) => MethodDecorator;
|
|
19
|
+
export declare const Delete: (path?: string) => MethodDecorator;
|
|
20
|
+
export declare const Patch: (path?: string) => MethodDecorator;
|
|
21
|
+
export declare const Options: (path?: string) => MethodDecorator;
|
|
22
|
+
export declare const Head: (path?: string) => MethodDecorator;
|
|
23
|
+
export declare const All: (path?: string) => MethodDecorator;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.All = exports.Head = exports.Options = exports.Patch = exports.Delete = exports.Put = exports.Post = exports.Get = exports.HttpMethod = void 0;
|
|
4
|
+
exports.HttpRoute = HttpRoute;
|
|
5
|
+
const app_1 = require("@shadow-library/app");
|
|
6
|
+
var HttpMethod;
|
|
7
|
+
(function (HttpMethod) {
|
|
8
|
+
HttpMethod["GET"] = "GET";
|
|
9
|
+
HttpMethod["POST"] = "POST";
|
|
10
|
+
HttpMethod["PUT"] = "PUT";
|
|
11
|
+
HttpMethod["DELETE"] = "DELETE";
|
|
12
|
+
HttpMethod["PATCH"] = "PATCH";
|
|
13
|
+
HttpMethod["OPTIONS"] = "OPTIONS";
|
|
14
|
+
HttpMethod["HEAD"] = "HEAD";
|
|
15
|
+
HttpMethod["ALL"] = "ALL";
|
|
16
|
+
})(HttpMethod || (exports.HttpMethod = HttpMethod = {}));
|
|
17
|
+
function HttpRoute(options) {
|
|
18
|
+
return (0, app_1.Route)(options);
|
|
19
|
+
}
|
|
20
|
+
const Get = (path) => HttpRoute({ method: HttpMethod.GET, path });
|
|
21
|
+
exports.Get = Get;
|
|
22
|
+
const Post = (path) => HttpRoute({ method: HttpMethod.POST, path });
|
|
23
|
+
exports.Post = Post;
|
|
24
|
+
const Put = (path) => HttpRoute({ method: HttpMethod.PUT, path });
|
|
25
|
+
exports.Put = Put;
|
|
26
|
+
const Delete = (path) => HttpRoute({ method: HttpMethod.DELETE, path });
|
|
27
|
+
exports.Delete = Delete;
|
|
28
|
+
const Patch = (path) => HttpRoute({ method: HttpMethod.PATCH, path });
|
|
29
|
+
exports.Patch = Patch;
|
|
30
|
+
const Options = (path) => HttpRoute({ method: HttpMethod.OPTIONS, path });
|
|
31
|
+
exports.Options = Options;
|
|
32
|
+
const Head = (path) => HttpRoute({ method: HttpMethod.HEAD, path });
|
|
33
|
+
exports.Head = Head;
|
|
34
|
+
const All = (path) => HttpRoute({ method: HttpMethod.ALL, path });
|
|
35
|
+
exports.All = All;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./http-controller.decorator.js"), exports);
|
|
18
|
+
__exportStar(require("./http-input.decorator.js"), exports);
|
|
19
|
+
__exportStar(require("./http-output.decorator.js"), exports);
|
|
20
|
+
__exportStar(require("./http-route.decorator.js"), exports);
|
|
21
|
+
__exportStar(require("./middleware.decorator.js"), exports);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { HTTP_CONTROLLER_TYPE } from '../constants.js';
|
|
2
|
+
export type MiddlewareType = 'onRequest' | 'preParsing' | 'preValidation' | 'preHandler' | 'preSerialization' | 'onSend' | 'onResponse' | 'onError';
|
|
3
|
+
export interface MiddlewareOptions {
|
|
4
|
+
type: MiddlewareType;
|
|
5
|
+
weight: number;
|
|
6
|
+
}
|
|
7
|
+
export interface MiddlewareMetadata extends MiddlewareOptions {
|
|
8
|
+
[HTTP_CONTROLLER_TYPE]: 'middleware';
|
|
9
|
+
generates: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare function Middleware(options?: Partial<MiddlewareOptions>): ClassDecorator;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Middleware = Middleware;
|
|
7
|
+
const assert_1 = __importDefault(require("assert"));
|
|
8
|
+
const app_1 = require("@shadow-library/app");
|
|
9
|
+
const constants_1 = require("../constants.js");
|
|
10
|
+
const propertyKeys = ['generate', 'use'];
|
|
11
|
+
function Middleware(options = {}) {
|
|
12
|
+
if (!options.type)
|
|
13
|
+
options.type = 'preHandler';
|
|
14
|
+
if (!options.weight)
|
|
15
|
+
options.weight = 0;
|
|
16
|
+
return target => {
|
|
17
|
+
const key = propertyKeys.find(key => key in target.prototype);
|
|
18
|
+
(0, assert_1.default)(key, `Cannot apply @Middleware to a class without a 'generate()' or 'use()' method`);
|
|
19
|
+
(0, app_1.Controller)({ ...options, [constants_1.HTTP_CONTROLLER_TYPE]: 'middleware', generates: key === 'generate' })(target);
|
|
20
|
+
};
|
|
21
|
+
}
|
package/cjs/index.d.ts
ADDED
package/cjs/index.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
require("reflect-metadata");
|
|
18
|
+
__exportStar(require("./classes/index.js"), exports);
|
|
19
|
+
__exportStar(require("./decorators/index.js"), exports);
|
|
20
|
+
__exportStar(require("./interfaces/index.js"), exports);
|
|
21
|
+
__exportStar(require("./module/index.js"), exports);
|
|
22
|
+
__exportStar(require("./services/index.js"), exports);
|
|
23
|
+
__exportStar(require("./server.error.js"), exports);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./error-handler.interface.js"), exports);
|
|
18
|
+
__exportStar(require("./middleware.interface.js"), exports);
|
|
19
|
+
__exportStar(require("./route-handler.interface.js"), exports);
|
|
20
|
+
__exportStar(require("./server-metadata.interface.js"), exports);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { RouteMetdata } from '@shadow-library/app';
|
|
2
|
+
import { HttpRequest, HttpResponse } from './route-handler.interface.js';
|
|
3
|
+
export type MiddlewareHandler = (request: HttpRequest, response: HttpResponse) => Promise<any>;
|
|
4
|
+
export interface MiddlewareGenerator {
|
|
5
|
+
generate(metadata: RouteMetdata): MiddlewareHandler | undefined | Promise<MiddlewareHandler | undefined>;
|
|
6
|
+
}
|
|
7
|
+
export interface HttpMiddleware {
|
|
8
|
+
use(request: HttpRequest, response: HttpResponse): Promise<any>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { RouteMetdata } from '@shadow-library/app';
|
|
2
|
+
import { JSONSchema } from '@shadow-library/class-schema';
|
|
3
|
+
import { RouteShorthandOptions } from 'fastify';
|
|
4
|
+
import { HTTP_CONTROLLER_TYPE } from '../constants.js';
|
|
5
|
+
import { HttpMethod, RouteInputSchemas } from '../decorators/index.js';
|
|
6
|
+
declare module '@shadow-library/app' {
|
|
7
|
+
interface RouteMetdata extends Omit<RouteShorthandOptions, 'config'> {
|
|
8
|
+
method?: HttpMethod;
|
|
9
|
+
path?: string;
|
|
10
|
+
schemas?: RouteInputSchemas & {
|
|
11
|
+
response?: Record<number | string, JSONSchema>;
|
|
12
|
+
};
|
|
13
|
+
rawBody?: boolean;
|
|
14
|
+
status?: number;
|
|
15
|
+
headers?: Record<string, string | (() => string)>;
|
|
16
|
+
redirect?: string;
|
|
17
|
+
render?: string | true;
|
|
18
|
+
}
|
|
19
|
+
interface ControllerMetdata {
|
|
20
|
+
[HTTP_CONTROLLER_TYPE]?: 'router' | 'middleware';
|
|
21
|
+
path?: string;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export type ServerMetadata = RouteMetdata;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.ErrorResponseDto = exports.ErrorFieldDto = void 0;
|
|
13
|
+
const class_schema_1 = require("@shadow-library/class-schema");
|
|
14
|
+
let ErrorFieldDto = class ErrorFieldDto {
|
|
15
|
+
field;
|
|
16
|
+
msg;
|
|
17
|
+
};
|
|
18
|
+
exports.ErrorFieldDto = ErrorFieldDto;
|
|
19
|
+
__decorate([
|
|
20
|
+
(0, class_schema_1.Field)(),
|
|
21
|
+
__metadata("design:type", String)
|
|
22
|
+
], ErrorFieldDto.prototype, "field", void 0);
|
|
23
|
+
__decorate([
|
|
24
|
+
(0, class_schema_1.Field)(),
|
|
25
|
+
__metadata("design:type", String)
|
|
26
|
+
], ErrorFieldDto.prototype, "msg", void 0);
|
|
27
|
+
exports.ErrorFieldDto = ErrorFieldDto = __decorate([
|
|
28
|
+
(0, class_schema_1.Schema)()
|
|
29
|
+
], ErrorFieldDto);
|
|
30
|
+
let ErrorResponseDto = class ErrorResponseDto {
|
|
31
|
+
code;
|
|
32
|
+
type;
|
|
33
|
+
message;
|
|
34
|
+
fields;
|
|
35
|
+
};
|
|
36
|
+
exports.ErrorResponseDto = ErrorResponseDto;
|
|
37
|
+
__decorate([
|
|
38
|
+
(0, class_schema_1.Field)(),
|
|
39
|
+
__metadata("design:type", String)
|
|
40
|
+
], ErrorResponseDto.prototype, "code", void 0);
|
|
41
|
+
__decorate([
|
|
42
|
+
(0, class_schema_1.Field)(),
|
|
43
|
+
__metadata("design:type", String)
|
|
44
|
+
], ErrorResponseDto.prototype, "type", void 0);
|
|
45
|
+
__decorate([
|
|
46
|
+
(0, class_schema_1.Field)(),
|
|
47
|
+
__metadata("design:type", String)
|
|
48
|
+
], ErrorResponseDto.prototype, "message", void 0);
|
|
49
|
+
__decorate([
|
|
50
|
+
(0, class_schema_1.Field)(() => [ErrorFieldDto], { required: false }),
|
|
51
|
+
__metadata("design:type", Array)
|
|
52
|
+
], ErrorResponseDto.prototype, "fields", void 0);
|
|
53
|
+
exports.ErrorResponseDto = ErrorResponseDto = __decorate([
|
|
54
|
+
(0, class_schema_1.Schema)()
|
|
55
|
+
], ErrorResponseDto);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { FactoryProvider, ModuleMetadata } from '@shadow-library/app';
|
|
2
|
+
import { JSONSchema } from '@shadow-library/class-schema';
|
|
3
|
+
import { FastifyInstance, FastifyServerOptions } from 'fastify';
|
|
4
|
+
import { Promisable } from 'type-fest';
|
|
5
|
+
import { ErrorHandler } from '../interfaces/index.js';
|
|
6
|
+
export interface FastifyConfig extends FastifyServerOptions {
|
|
7
|
+
host: string;
|
|
8
|
+
port: number;
|
|
9
|
+
errorHandler: ErrorHandler;
|
|
10
|
+
responseSchema?: Record<string | number, JSONSchema>;
|
|
11
|
+
}
|
|
12
|
+
export interface FastifyModuleOptions extends Partial<FastifyConfig> {
|
|
13
|
+
imports?: ModuleMetadata['imports'];
|
|
14
|
+
fastifyFactory?: (instance: FastifyInstance) => Promisable<FastifyInstance>;
|
|
15
|
+
}
|
|
16
|
+
export interface FastifyModuleAsyncOptions extends Pick<FastifyModuleOptions, 'imports' | 'fastifyFactory'> {
|
|
17
|
+
useFactory: (...args: any[]) => Promisable<FastifyConfig>;
|
|
18
|
+
inject?: FactoryProvider['inject'];
|
|
19
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ControllerRouteMetadata, Router } from '@shadow-library/app';
|
|
2
|
+
import { type FastifyInstance } from 'fastify';
|
|
3
|
+
import { Chain as MockRequestChain, InjectOptions as MockRequestOptions, Response as MockResponse } from 'light-my-request';
|
|
4
|
+
import { JsonObject } from 'type-fest';
|
|
5
|
+
import { HttpRequest, HttpResponse, ServerMetadata } from '../interfaces/index.js';
|
|
6
|
+
import { type FastifyConfig } from './fastify-module.interface.js';
|
|
7
|
+
declare module 'fastify' {
|
|
8
|
+
interface FastifyRequest {
|
|
9
|
+
rawBody?: Buffer;
|
|
10
|
+
}
|
|
11
|
+
interface FastifyContextConfig {
|
|
12
|
+
metadata: ServerMetadata;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export interface RequestContext {
|
|
16
|
+
request: HttpRequest;
|
|
17
|
+
response: HttpResponse;
|
|
18
|
+
params: Record<string, string>;
|
|
19
|
+
query: Record<string, string>;
|
|
20
|
+
body: JsonObject;
|
|
21
|
+
}
|
|
22
|
+
export declare class FastifyRouter extends Router {
|
|
23
|
+
private readonly config;
|
|
24
|
+
private readonly instance;
|
|
25
|
+
private readonly logger;
|
|
26
|
+
constructor(config: FastifyConfig, instance: FastifyInstance);
|
|
27
|
+
getInstance(): FastifyInstance;
|
|
28
|
+
private registerRawBody;
|
|
29
|
+
private parseControllers;
|
|
30
|
+
private getStatusCode;
|
|
31
|
+
private generateRouteHandler;
|
|
32
|
+
register(controllers: ControllerRouteMetadata[]): Promise<void>;
|
|
33
|
+
start(): Promise<void>;
|
|
34
|
+
stop(): Promise<void>;
|
|
35
|
+
mockRequest(options?: MockRequestOptions): MockRequestChain | Promise<MockResponse>;
|
|
36
|
+
}
|