@zenofolio/hyper-decor 0.0.3
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/.mocharc.js +5 -0
- package/LICENSE +21 -0
- package/README.md +191 -0
- package/dist/__internals/constants.d.ts +61 -0
- package/dist/__internals/constants.js +72 -0
- package/dist/__internals/creators/request.creator.d.ts +12 -0
- package/dist/__internals/creators/request.creator.js +53 -0
- package/dist/__internals/creators/routes.creator.d.ts +10 -0
- package/dist/__internals/creators/routes.creator.js +37 -0
- package/dist/__internals/decorator-base.d.ts +30 -0
- package/dist/__internals/decorator-base.js +86 -0
- package/dist/__internals/helpers/merge-metadata.d.ts +14 -0
- package/dist/__internals/helpers/merge-metadata.js +44 -0
- package/dist/__internals/helpers/who.helper.d.ts +9 -0
- package/dist/__internals/helpers/who.helper.js +19 -0
- package/dist/__internals/store.d.ts +10 -0
- package/dist/__internals/store.js +17 -0
- package/dist/__internals/stores/index.d.ts +15 -0
- package/dist/__internals/stores/index.js +37 -0
- package/dist/__internals/stores/middleware.store.d.ts +7 -0
- package/dist/__internals/stores/middleware.store.js +19 -0
- package/dist/__internals/stores/params.store.d.ts +21 -0
- package/dist/__internals/stores/params.store.js +65 -0
- package/dist/__internals/stores/routes.store.d.ts +17 -0
- package/dist/__internals/stores/routes.store.js +43 -0
- package/dist/__internals/stores/store.interface.d.ts +8 -0
- package/dist/__internals/stores/store.interface.js +2 -0
- package/dist/__internals/transform/method.transform.d.ts +2 -0
- package/dist/__internals/transform/method.transform.js +20 -0
- package/dist/__internals/transform/pass.transfrom.d.ts +1 -0
- package/dist/__internals/transform/pass.transfrom.js +2 -0
- package/dist/__internals/transform/role.transform.d.ts +7 -0
- package/dist/__internals/transform/role.transform.js +86 -0
- package/dist/__internals/transform/scope.transfrom.d.ts +7 -0
- package/dist/__internals/transform/scope.transfrom.js +72 -0
- package/dist/__internals/types.d.ts +8 -0
- package/dist/__internals/types.js +2 -0
- package/dist/__internals/utils/function.util.d.ts +4 -0
- package/dist/__internals/utils/function.util.js +20 -0
- package/dist/__internals/utils/mixin.utils.d.ts +11 -0
- package/dist/__internals/utils/mixin.utils.js +34 -0
- package/dist/__internals/utils/object.util.d.ts +27 -0
- package/dist/__internals/utils/object.util.js +72 -0
- package/dist/__internals/utils/path.util.d.ts +4 -0
- package/dist/__internals/utils/path.util.js +8 -0
- package/dist/__internals/utils/router.d.ts +1 -0
- package/dist/__internals/utils/router.js +2 -0
- package/dist/common/bootstrap.d.ts +3 -0
- package/dist/common/bootstrap.js +25 -0
- package/dist/common/helpers/index.d.ts +2 -0
- package/dist/common/helpers/index.js +18 -0
- package/dist/common/helpers/role.d.ts +22 -0
- package/dist/common/helpers/role.js +43 -0
- package/dist/common/helpers/scopes.d.ts +23 -0
- package/dist/common/helpers/scopes.js +47 -0
- package/dist/common/openapi/collect-class-data.d.ts +21 -0
- package/dist/common/openapi/collect-class-data.js +45 -0
- package/dist/common/openapi/collect-function-data.d.ts +32 -0
- package/dist/common/openapi/collect-function-data.js +70 -0
- package/dist/common/openapi/index.d.ts +2 -0
- package/dist/common/openapi/index.js +18 -0
- package/dist/constants.d.ts +3 -0
- package/dist/constants.js +6 -0
- package/dist/decorators/File.d.ts +65 -0
- package/dist/decorators/File.js +180 -0
- package/dist/decorators/Http.d.ts +55 -0
- package/dist/decorators/Http.js +93 -0
- package/dist/decorators/HyperApp.d.ts +7 -0
- package/dist/decorators/HyperApp.js +262 -0
- package/dist/decorators/HyperController.d.ts +2 -0
- package/dist/decorators/HyperController.js +19 -0
- package/dist/decorators/HyperModule.d.ts +5 -0
- package/dist/decorators/HyperModule.js +14 -0
- package/dist/decorators/Middleware.d.ts +24 -0
- package/dist/decorators/Middleware.js +51 -0
- package/dist/decorators/Pass.d.ts +12 -0
- package/dist/decorators/Pass.js +29 -0
- package/dist/decorators/Role.d.ts +6 -0
- package/dist/decorators/Role.js +34 -0
- package/dist/decorators/Routes.d.ts +14 -0
- package/dist/decorators/Routes.js +21 -0
- package/dist/decorators/Scope.d.ts +6 -0
- package/dist/decorators/Scope.js +25 -0
- package/dist/decorators/index.d.ts +11 -0
- package/dist/decorators/index.js +27 -0
- package/dist/decorators/types.d.ts +89 -0
- package/dist/decorators/types.js +2 -0
- package/dist/exeptions/DuplicateControllerPathException.d.ts +14 -0
- package/dist/exeptions/DuplicateControllerPathException.js +12 -0
- package/dist/exeptions/DuplicatedException.d.ts +8 -0
- package/dist/exeptions/DuplicatedException.js +12 -0
- package/dist/exeptions/DuplicatedHandlerException.d.ts +4 -0
- package/dist/exeptions/DuplicatedHandlerException.js +12 -0
- package/dist/exeptions/HyperException.d.ts +7 -0
- package/dist/exeptions/HyperException.js +13 -0
- package/dist/exeptions/HyperFileException.d.ts +4 -0
- package/dist/exeptions/HyperFileException.js +12 -0
- package/dist/exeptions/MethodNotFountException.d.ts +4 -0
- package/dist/exeptions/MethodNotFountException.js +12 -0
- package/dist/exeptions/NotPropertyException.d.ts +6 -0
- package/dist/exeptions/NotPropertyException.js +16 -0
- package/dist/exeptions/NotRoleException.d.ts +6 -0
- package/dist/exeptions/NotRoleException.js +17 -0
- package/dist/exeptions/NotScopeException.d.ts +7 -0
- package/dist/exeptions/NotScopeException.js +18 -0
- package/dist/exeptions/WrongPlaceException.d.ts +8 -0
- package/dist/exeptions/WrongPlaceException.js +21 -0
- package/dist/exeptions/index.d.ts +8 -0
- package/dist/exeptions/index.js +18 -0
- package/dist/exeptions/types.d.ts +1 -0
- package/dist/exeptions/types.js +2 -0
- package/dist/extension.d.ts +1 -0
- package/dist/extension.js +41 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +25 -0
- package/dist/type.d.ts +10 -0
- package/dist/type.js +2 -0
- package/hyper-express-decorators.d.ts +16 -0
- package/package.json +61 -0
- package/tsconfig.json +17 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.File = void 0;
|
|
16
|
+
const Http_1 = require("./Http");
|
|
17
|
+
const consumers_1 = require("stream/consumers");
|
|
18
|
+
const HyperFileException_1 = __importDefault(require("../exeptions/HyperFileException"));
|
|
19
|
+
/**
|
|
20
|
+
* Decorator to extract file from the request
|
|
21
|
+
*
|
|
22
|
+
* @param param0
|
|
23
|
+
*/
|
|
24
|
+
const File = (options) => {
|
|
25
|
+
const _options = typeof options === "string" ? { fieldName: options } : options;
|
|
26
|
+
return (0, Http_1.createCustomRequestDecorator)("File", (request) => __awaiter(void 0, void 0, void 0, function* () {
|
|
27
|
+
var _a, _b;
|
|
28
|
+
const { allowedMimeTypes, maxFileSize } = yield resolveRestrictions(request, _options.restrictions);
|
|
29
|
+
const passTypes = allowedMimeTypes.includes("*") || allowedMimeTypes.length === 0;
|
|
30
|
+
const passSize = maxFileSize === Infinity;
|
|
31
|
+
const contentType = (_a = request.headers) === null || _a === void 0 ? void 0 : _a["content-type"];
|
|
32
|
+
const fileSize = Number((_b = request.headers) === null || _b === void 0 ? void 0 : _b["content-length"]);
|
|
33
|
+
const isMultipart = contentType === null || contentType === void 0 ? void 0 : contentType.includes("multipart/form-data");
|
|
34
|
+
if (!isMultipart) {
|
|
35
|
+
throw new HyperFileException_1.default("Invalid request, expected multipart form data", {
|
|
36
|
+
fieldName: _options.fieldName,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
if (isNaN(fileSize) || fileSize <= 0) {
|
|
40
|
+
throw new HyperFileException_1.default(`File ${_options.fieldName} is missing or empty`, {
|
|
41
|
+
fieldName: _options.fieldName,
|
|
42
|
+
fileSize,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
if (!passSize && fileSize > maxFileSize) {
|
|
46
|
+
throw new HyperFileException_1.default(`File ${_options.fieldName} is too large. Max size is ${maxFileSize} bytes`, {
|
|
47
|
+
fieldName: _options.fieldName,
|
|
48
|
+
maxFileSize,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
const files = yield extractFiles(request, {
|
|
52
|
+
maxSize: passSize ? undefined : maxFileSize,
|
|
53
|
+
mimeTypes: passTypes ? undefined : allowedMimeTypes,
|
|
54
|
+
requires: _options.required
|
|
55
|
+
? Array.isArray(_options.fieldName)
|
|
56
|
+
? _options.fieldName
|
|
57
|
+
: [_options.fieldName]
|
|
58
|
+
: undefined,
|
|
59
|
+
requireName: true,
|
|
60
|
+
});
|
|
61
|
+
return Array.isArray(_options.fieldName)
|
|
62
|
+
? files
|
|
63
|
+
: files[_options.fieldName];
|
|
64
|
+
}));
|
|
65
|
+
};
|
|
66
|
+
exports.File = File;
|
|
67
|
+
/**
|
|
68
|
+
*
|
|
69
|
+
* Helper function to create a file decorator with options
|
|
70
|
+
*
|
|
71
|
+
* @param options
|
|
72
|
+
* @returns
|
|
73
|
+
*/
|
|
74
|
+
exports.File.options = (options, required = false) => {
|
|
75
|
+
return (fieldName) => {
|
|
76
|
+
return (0, exports.File)(Object.assign(Object.assign({}, options), { required, fieldName }));
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Helper function to create a file decorator with restrictions
|
|
81
|
+
*
|
|
82
|
+
* @param restrictions
|
|
83
|
+
* @returns
|
|
84
|
+
*/
|
|
85
|
+
exports.File.restrictions = (restrictions) => {
|
|
86
|
+
return (fieldName, required = false) => {
|
|
87
|
+
return (0, exports.File)({ fieldName, restrictions, required });
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
/////////////////////////////
|
|
91
|
+
// Types
|
|
92
|
+
/////////////////////////////
|
|
93
|
+
/////////////////////////////
|
|
94
|
+
/// Utility
|
|
95
|
+
/////////////////////////////
|
|
96
|
+
const resolveRestrictions = (request, restrictions) => __awaiter(void 0, void 0, void 0, function* () {
|
|
97
|
+
if (typeof restrictions === "function") {
|
|
98
|
+
return yield restrictions(request);
|
|
99
|
+
}
|
|
100
|
+
return (restrictions !== null && restrictions !== void 0 ? restrictions : {
|
|
101
|
+
allowedMimeTypes: ["*"],
|
|
102
|
+
maxFileSize: Infinity,
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
/**
|
|
106
|
+
* Extract files from a request with validation, transformation, and required files check.
|
|
107
|
+
*
|
|
108
|
+
* @param request
|
|
109
|
+
* @param options Validation and transformation options
|
|
110
|
+
* @returns Transformed or raw file details
|
|
111
|
+
*/
|
|
112
|
+
const extractFiles = (request, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
113
|
+
var _a;
|
|
114
|
+
const contentType = (_a = request.headers) === null || _a === void 0 ? void 0 : _a["content-type"];
|
|
115
|
+
if (!(contentType === null || contentType === void 0 ? void 0 : contentType.includes("multipart/form-data"))) {
|
|
116
|
+
throw new Error("Invalid request, expected multipart form data");
|
|
117
|
+
}
|
|
118
|
+
const filesMap = {};
|
|
119
|
+
yield request.multipart((field) => __awaiter(void 0, void 0, void 0, function* () {
|
|
120
|
+
var _a, _b, _c, _d;
|
|
121
|
+
if (field.file && field.file.stream) {
|
|
122
|
+
const bufferFile = yield (0, consumers_1.buffer)(field.file.stream);
|
|
123
|
+
const type = yield (yield import("file-type")).fileTypeFromBuffer(bufferFile);
|
|
124
|
+
if (!type) {
|
|
125
|
+
throw new HyperFileException_1.default(`Invalid file type`, {
|
|
126
|
+
field: field.name,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
const mimeType = type.mime;
|
|
130
|
+
const extention = type.ext;
|
|
131
|
+
// Validate MIME type early
|
|
132
|
+
if ((options === null || options === void 0 ? void 0 : options.mimeTypes) && !options.mimeTypes.includes(mimeType)) {
|
|
133
|
+
throw new HyperFileException_1.default(`Invalid file type, only ${options.mimeTypes.join(", ")} is allowed`, {
|
|
134
|
+
field: field.name,
|
|
135
|
+
allowedMimeTypes: options.mimeTypes,
|
|
136
|
+
mimeType,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
if (!type) {
|
|
140
|
+
throw new HyperFileException_1.default(`Invalid file type`, {
|
|
141
|
+
field: field.name,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
if ((options === null || options === void 0 ? void 0 : options.maxSize) && bufferFile.byteLength > options.maxSize) {
|
|
145
|
+
throw new HyperFileException_1.default(`File '${field.name}' size exceeds the maximum limit of ${options.maxSize} bytes`, {
|
|
146
|
+
field: field.name,
|
|
147
|
+
maxSize: options.maxSize,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
if ((options === null || options === void 0 ? void 0 : options.requireName) && !((_a = field.file) === null || _a === void 0 ? void 0 : _a.name)) {
|
|
151
|
+
throw new HyperFileException_1.default(`File name is required`, {
|
|
152
|
+
field: field.name,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
// Derive file details
|
|
156
|
+
const name = (_d = (_c = (_b = field.file) === null || _b === void 0 ? void 0 : _b.name) === null || _c === void 0 ? void 0 : _c.split(".").shift()) !== null && _d !== void 0 ? _d : field.name;
|
|
157
|
+
const filename = `${name === null || name === void 0 ? void 0 : name.replace(extention, "")}.${extention}`;
|
|
158
|
+
filesMap[field.name] = {
|
|
159
|
+
field: field.name,
|
|
160
|
+
name: name,
|
|
161
|
+
filename: filename,
|
|
162
|
+
ext: extention,
|
|
163
|
+
size: bufferFile.byteLength,
|
|
164
|
+
mimeType: mimeType,
|
|
165
|
+
buffer: bufferFile,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
}));
|
|
169
|
+
// Check for required files
|
|
170
|
+
if (options === null || options === void 0 ? void 0 : options.requires) {
|
|
171
|
+
for (const required of options.requires) {
|
|
172
|
+
if (!filesMap[required]) {
|
|
173
|
+
throw new HyperFileException_1.default(`File "${required}" is required`, {
|
|
174
|
+
required,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return filesMap;
|
|
180
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { ParameterResolver } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Get the value of a key from the request object
|
|
4
|
+
*
|
|
5
|
+
* @param key
|
|
6
|
+
* @returns
|
|
7
|
+
*/
|
|
8
|
+
export declare const Query: (key?: string, transfrom?: (data: any) => any) => ParameterDecorator;
|
|
9
|
+
/**
|
|
10
|
+
* Get the body of the request
|
|
11
|
+
*
|
|
12
|
+
* @param resolver
|
|
13
|
+
* @returns
|
|
14
|
+
*/
|
|
15
|
+
export declare const Body: <T, R>(resolver?: (data: T) => R) => ParameterDecorator;
|
|
16
|
+
/**
|
|
17
|
+
* Get the params from the request
|
|
18
|
+
*
|
|
19
|
+
* @param k
|
|
20
|
+
* @returns
|
|
21
|
+
*/
|
|
22
|
+
export declare const Param: (k?: string, validator?: (data: any) => any) => ParameterDecorator;
|
|
23
|
+
/**
|
|
24
|
+
* get the headers from the request
|
|
25
|
+
*
|
|
26
|
+
* @param key
|
|
27
|
+
* @returns
|
|
28
|
+
*/
|
|
29
|
+
export declare const Headers: <T extends string>(key?: T) => ParameterDecorator;
|
|
30
|
+
export declare const Req: () => ParameterDecorator;
|
|
31
|
+
export declare const Res: () => ParameterDecorator;
|
|
32
|
+
/**
|
|
33
|
+
* Create a custom request decorator
|
|
34
|
+
* that can be used to extract data from the request object
|
|
35
|
+
*
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
*
|
|
40
|
+
* interface LoginData {
|
|
41
|
+
* username: string;
|
|
42
|
+
* password: string;
|
|
43
|
+
* }
|
|
44
|
+
*
|
|
45
|
+
* const LoginData = createCustomRequestDecorator<LoginData>({
|
|
46
|
+
* resolver: async (request) => {
|
|
47
|
+
* const data = await request.json();
|
|
48
|
+
* return [data];
|
|
49
|
+
* }
|
|
50
|
+
* }
|
|
51
|
+
*
|
|
52
|
+
*
|
|
53
|
+
*
|
|
54
|
+
*/
|
|
55
|
+
export declare const createCustomRequestDecorator: (decoratorName: string, resolver: ParameterResolver) => ParameterDecorator;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.createCustomRequestDecorator = exports.Res = exports.Req = exports.Headers = exports.Param = exports.Body = exports.Query = void 0;
|
|
16
|
+
const request_creator_1 = __importDefault(require("../__internals/creators/request.creator"));
|
|
17
|
+
const object_util_1 = require("../__internals/utils/object.util");
|
|
18
|
+
/**
|
|
19
|
+
* Get the value of a key from the request object
|
|
20
|
+
*
|
|
21
|
+
* @param key
|
|
22
|
+
* @returns
|
|
23
|
+
*/
|
|
24
|
+
const Query = (key, transfrom) => (0, request_creator_1.default)("query", "Query", (request) => {
|
|
25
|
+
const value = (0, object_util_1.$get)(request.query, key, request.query);
|
|
26
|
+
if (!transfrom)
|
|
27
|
+
return value;
|
|
28
|
+
return value;
|
|
29
|
+
});
|
|
30
|
+
exports.Query = Query;
|
|
31
|
+
/**
|
|
32
|
+
* Get the body of the request
|
|
33
|
+
*
|
|
34
|
+
* @param resolver
|
|
35
|
+
* @returns
|
|
36
|
+
*/
|
|
37
|
+
const Body = (resolver) => (0, request_creator_1.default)("req", "BODY", (request) => __awaiter(void 0, void 0, void 0, function* () {
|
|
38
|
+
const value = yield request.json();
|
|
39
|
+
return resolver ? resolver(value) : value;
|
|
40
|
+
}));
|
|
41
|
+
exports.Body = Body;
|
|
42
|
+
/**
|
|
43
|
+
* Get the params from the request
|
|
44
|
+
*
|
|
45
|
+
* @param k
|
|
46
|
+
* @returns
|
|
47
|
+
*/
|
|
48
|
+
const Param = (k, validator) => (0, request_creator_1.default)("params", "Param", (req) => {
|
|
49
|
+
const value = (0, object_util_1.$get)(req.params, k, req.params);
|
|
50
|
+
if (typeof validator === "function")
|
|
51
|
+
return validator(value);
|
|
52
|
+
return value;
|
|
53
|
+
});
|
|
54
|
+
exports.Param = Param;
|
|
55
|
+
/**
|
|
56
|
+
* get the headers from the request
|
|
57
|
+
*
|
|
58
|
+
* @param key
|
|
59
|
+
* @returns
|
|
60
|
+
*/
|
|
61
|
+
const Headers = (key) => (0, request_creator_1.default)("headers", "Headers", (req) => (0, object_util_1.$get)(req.headers, key, req.headers));
|
|
62
|
+
exports.Headers = Headers;
|
|
63
|
+
const Req = () => (0, request_creator_1.default)("req", "Req", (req) => req);
|
|
64
|
+
exports.Req = Req;
|
|
65
|
+
const Res = () => (0, request_creator_1.default)("res", "Res", (req, res) => res);
|
|
66
|
+
exports.Res = Res;
|
|
67
|
+
/**
|
|
68
|
+
* Create a custom request decorator
|
|
69
|
+
* that can be used to extract data from the request object
|
|
70
|
+
*
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```typescript
|
|
74
|
+
*
|
|
75
|
+
* interface LoginData {
|
|
76
|
+
* username: string;
|
|
77
|
+
* password: string;
|
|
78
|
+
* }
|
|
79
|
+
*
|
|
80
|
+
* const LoginData = createCustomRequestDecorator<LoginData>({
|
|
81
|
+
* resolver: async (request) => {
|
|
82
|
+
* const data = await request.json();
|
|
83
|
+
* return [data];
|
|
84
|
+
* }
|
|
85
|
+
* }
|
|
86
|
+
*
|
|
87
|
+
*
|
|
88
|
+
*
|
|
89
|
+
*/
|
|
90
|
+
const createCustomRequestDecorator = (decoratorName, resolver) => {
|
|
91
|
+
return (0, request_creator_1.default)("req", decoratorName, resolver);
|
|
92
|
+
};
|
|
93
|
+
exports.createCustomRequestDecorator = createCustomRequestDecorator;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import "reflect-metadata";
|
|
2
|
+
import { HyperAppDecorator } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* Decorator to define the main application class with assigned modules.
|
|
5
|
+
* @param modules - List of modules to be used in the application.
|
|
6
|
+
*/
|
|
7
|
+
export declare const HyperApp: HyperAppDecorator;
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.HyperApp = void 0;
|
|
16
|
+
require("reflect-metadata");
|
|
17
|
+
const constants_1 = require("../__internals/constants");
|
|
18
|
+
const hyper_express_1 = require("hyper-express");
|
|
19
|
+
const decorator_base_1 = require("../__internals/decorator-base");
|
|
20
|
+
const path_util_1 = require("../__internals/utils/path.util");
|
|
21
|
+
const scope_transfrom_1 = __importDefault(require("../__internals/transform/scope.transfrom"));
|
|
22
|
+
const role_transform_1 = __importDefault(require("../__internals/transform/role.transform"));
|
|
23
|
+
const object_util_1 = require("../__internals/utils/object.util");
|
|
24
|
+
const merge_metadata_1 = require("../__internals/helpers/merge-metadata");
|
|
25
|
+
const tsyringe_1 = require("tsyringe");
|
|
26
|
+
/**
|
|
27
|
+
* Decorator to define the main application class with assigned modules.
|
|
28
|
+
* @param modules - List of modules to be used in the application.
|
|
29
|
+
*/
|
|
30
|
+
const HyperApp = (options) => (0, decorator_base_1.DecoratorHelper)({
|
|
31
|
+
type: constants_1.KEY_TYPE_APP,
|
|
32
|
+
key: constants_1.KEY_PARAMS_APP,
|
|
33
|
+
options: options !== null && options !== void 0 ? options : { modules: [] },
|
|
34
|
+
}, (options, Target) => {
|
|
35
|
+
return class extends hyper_express_1.Server {
|
|
36
|
+
constructor(...args) {
|
|
37
|
+
super(options.options);
|
|
38
|
+
this.listArguments = [];
|
|
39
|
+
this.storeLogs = {};
|
|
40
|
+
this.listArguments = args;
|
|
41
|
+
}
|
|
42
|
+
prepare() {
|
|
43
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
44
|
+
this.mergeMetadata(Target);
|
|
45
|
+
yield this.applyOptions(Target);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
/** Fusiona los metadatos relevantes al Target */
|
|
49
|
+
mergeMetadata(targetPrototype) {
|
|
50
|
+
(0, merge_metadata_1.mergeMetadata)(targetPrototype, this.constructor, [
|
|
51
|
+
constants_1.KEY_PARAMS_MIDDLEWARES,
|
|
52
|
+
constants_1.KEY_PARAMS_SCOPE,
|
|
53
|
+
constants_1.KEY_PARAMS_ROLE,
|
|
54
|
+
constants_1.KEY_PARAMS_PASS,
|
|
55
|
+
]);
|
|
56
|
+
}
|
|
57
|
+
/** Aplica las opciones y prepara la instancia del Target */
|
|
58
|
+
applyOptions(Target) {
|
|
59
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
60
|
+
var _a;
|
|
61
|
+
yield applyAppOptions(options, Target, this, this.log.bind(this));
|
|
62
|
+
const target = Reflect.construct(Target, this.listArguments);
|
|
63
|
+
(_a = target === null || target === void 0 ? void 0 : target.onPrepare) === null || _a === void 0 ? void 0 : _a.call(target);
|
|
64
|
+
this.showLogs();
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
/** Maneja los logs respetando las opciones configuradas */
|
|
68
|
+
log(space, message) {
|
|
69
|
+
var _a;
|
|
70
|
+
var _b;
|
|
71
|
+
if (((_a = options.logs) === null || _a === void 0 ? void 0 : _a[space]) === false)
|
|
72
|
+
return;
|
|
73
|
+
((_b = this.storeLogs)[space] || (_b[space] = [])).push(`- ${message}`);
|
|
74
|
+
}
|
|
75
|
+
showLogs() {
|
|
76
|
+
var _a, _b, _c;
|
|
77
|
+
const content = ["\n\n"];
|
|
78
|
+
content.push("/////////////////////////////");
|
|
79
|
+
content.push(`- HyperExpress Application`);
|
|
80
|
+
content.push(`- ${(_a = options.name) !== null && _a !== void 0 ? _a : "Hyper App"} - ${(_b = options.version) !== null && _b !== void 0 ? _b : "1.0.0"}`);
|
|
81
|
+
content.push("/////////////////////////////\n");
|
|
82
|
+
content.push("\nLogs:");
|
|
83
|
+
Object.entries(this.storeLogs).forEach(([space, logs]) => {
|
|
84
|
+
if (!logs.length)
|
|
85
|
+
return;
|
|
86
|
+
content.push(`- [${space.toUpperCase()}]`);
|
|
87
|
+
logs.forEach((log) => content.push(` ${log}`));
|
|
88
|
+
content.push("");
|
|
89
|
+
});
|
|
90
|
+
(_c = options.logger) === null || _c === void 0 ? void 0 : _c.call(this, content.join("\n"));
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
});
|
|
94
|
+
exports.HyperApp = HyperApp;
|
|
95
|
+
//////////////////////////////////
|
|
96
|
+
/// Private methods
|
|
97
|
+
//////////////////////////////////
|
|
98
|
+
const if_router = (current) => {
|
|
99
|
+
if (!current || !((current === null || current === void 0 ? void 0 : current.prototype) instanceof hyper_express_1.Router))
|
|
100
|
+
return new hyper_express_1.Router();
|
|
101
|
+
return new current();
|
|
102
|
+
};
|
|
103
|
+
function getData(target) {
|
|
104
|
+
var _a, _b, _c, _d, _e;
|
|
105
|
+
const app = (0, decorator_base_1.getDecorData)(constants_1.KEY_PARAMS_APP, target);
|
|
106
|
+
const module = (0, decorator_base_1.getDecorData)(constants_1.KEY_PARAMS_MODULE, target);
|
|
107
|
+
const controller = (0, decorator_base_1.getDecorData)(constants_1.KEY_TYPE_CONTROLLER, target);
|
|
108
|
+
const middlewares = (_a = (0, decorator_base_1.getDecorData)(constants_1.KEY_PARAMS_MIDDLEWARES, target)) !== null && _a !== void 0 ? _a : [];
|
|
109
|
+
const scopes = (_b = (0, decorator_base_1.getDecorData)(constants_1.KEY_PARAMS_SCOPE, target)) !== null && _b !== void 0 ? _b : [];
|
|
110
|
+
const roles = (_c = (0, decorator_base_1.getDecorData)(constants_1.KEY_PARAMS_ROLE, target)) !== null && _c !== void 0 ? _c : [];
|
|
111
|
+
const routes = (_d = (0, decorator_base_1.getDecorData)(constants_1.KEY_PARAMS_ROUTE, target)) !== null && _d !== void 0 ? _d : {
|
|
112
|
+
routes: [],
|
|
113
|
+
};
|
|
114
|
+
const params = (_e = (0, decorator_base_1.getDecorData)(constants_1.KEY_PARAMS_PARAM, target)) !== null && _e !== void 0 ? _e : {};
|
|
115
|
+
const pass = (0, decorator_base_1.getDecorData)(constants_1.KEY_PARAMS_PASS, target);
|
|
116
|
+
return {
|
|
117
|
+
app,
|
|
118
|
+
module,
|
|
119
|
+
controller,
|
|
120
|
+
middlewares,
|
|
121
|
+
scopes,
|
|
122
|
+
roles,
|
|
123
|
+
routes,
|
|
124
|
+
params,
|
|
125
|
+
pass,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
function applyAppOptions(options, Target, app, log) {
|
|
129
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
130
|
+
var _a, _b;
|
|
131
|
+
const data = getData(Target);
|
|
132
|
+
const prefix = (_a = options.prefix) !== null && _a !== void 0 ? _a : "/";
|
|
133
|
+
const services = (_b = options.imports) !== null && _b !== void 0 ? _b : [];
|
|
134
|
+
if (data.middlewares.length) {
|
|
135
|
+
app.use(...data.middlewares);
|
|
136
|
+
log("middleware", `${Target.name} with middlewares: ${data.middlewares.map((e) => e.name).join(", ")}`);
|
|
137
|
+
}
|
|
138
|
+
(0, scope_transfrom_1.default)(data.scopes, (middleware) => {
|
|
139
|
+
app.use(middleware);
|
|
140
|
+
log("middleware", `${Target.name} with scopes: ${data.scopes.join(", ")}`);
|
|
141
|
+
});
|
|
142
|
+
(0, role_transform_1.default)(data.roles, (middleware) => {
|
|
143
|
+
app.use(middleware);
|
|
144
|
+
log("middleware", `${Target.name} with roles: ${data.roles.join(", ")}`);
|
|
145
|
+
});
|
|
146
|
+
const routers = yield Promise.all(options.modules.map((module) => __awaiter(this, void 0, void 0, function* () {
|
|
147
|
+
var _a, _b;
|
|
148
|
+
const path = (_b = (_a = getData(module).module) === null || _a === void 0 ? void 0 : _a.path) !== null && _b !== void 0 ? _b : "/";
|
|
149
|
+
return prepareTarget({
|
|
150
|
+
target: module,
|
|
151
|
+
router: if_router(module),
|
|
152
|
+
namespace: `${Target.name}/${module.name}`,
|
|
153
|
+
instance: app,
|
|
154
|
+
prefix: path,
|
|
155
|
+
log,
|
|
156
|
+
});
|
|
157
|
+
})));
|
|
158
|
+
routers.forEach(({ router, path }) => {
|
|
159
|
+
app.use((0, path_util_1.join)(prefix, path), router);
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
function prepareTarget(_a) {
|
|
164
|
+
return __awaiter(this, arguments, void 0, function* ({ target, router, prefix = "/", namespace = "", instance, log, }) {
|
|
165
|
+
var _b, _c, _d, _e, _f, _g, _h, _j;
|
|
166
|
+
const _router = router !== null && router !== void 0 ? router : if_router(target);
|
|
167
|
+
const data = getData(target);
|
|
168
|
+
const modules = (_c = (_b = data.module) === null || _b === void 0 ? void 0 : _b.modules) !== null && _c !== void 0 ? _c : [];
|
|
169
|
+
const controllers = (_e = (_d = data.module) === null || _d === void 0 ? void 0 : _d.controllers) !== null && _e !== void 0 ? _e : [];
|
|
170
|
+
const routes = (_f = data.routes) !== null && _f !== void 0 ? _f : [];
|
|
171
|
+
const middlewares = (_g = data.middlewares) !== null && _g !== void 0 ? _g : [];
|
|
172
|
+
const scopes = (_h = data.scopes) !== null && _h !== void 0 ? _h : [];
|
|
173
|
+
const roles = (_j = data.roles) !== null && _j !== void 0 ? _j : [];
|
|
174
|
+
////////////////////////////////
|
|
175
|
+
/// Attach Middlewares
|
|
176
|
+
////////////////////////////////
|
|
177
|
+
_router.use(...middlewares);
|
|
178
|
+
(0, scope_transfrom_1.default)(scopes, (middleware) => _router.use(middleware));
|
|
179
|
+
(0, role_transform_1.default)(roles, (middleware) => _router.use(middleware));
|
|
180
|
+
////////////////////////////////
|
|
181
|
+
/// Prepare Modules
|
|
182
|
+
////////////////////////////////
|
|
183
|
+
yield (0, object_util_1.$each)(modules, (module) => __awaiter(this, void 0, void 0, function* () {
|
|
184
|
+
const moduleData = getData(module);
|
|
185
|
+
if (!moduleData.module)
|
|
186
|
+
return;
|
|
187
|
+
const router = yield prepareTarget({
|
|
188
|
+
target: module,
|
|
189
|
+
namespace: `${namespace}/${module.name}`,
|
|
190
|
+
prefix: moduleData.module.path,
|
|
191
|
+
instance: tsyringe_1.container.resolve(module),
|
|
192
|
+
log,
|
|
193
|
+
});
|
|
194
|
+
_router.use(router.path, router.router);
|
|
195
|
+
}));
|
|
196
|
+
// ////////////////////////////////
|
|
197
|
+
// /// Prepare Controllers
|
|
198
|
+
// ////////////////////////////////
|
|
199
|
+
yield (0, object_util_1.$each)(controllers, (controller) => __awaiter(this, void 0, void 0, function* () {
|
|
200
|
+
const data = getData(controller);
|
|
201
|
+
const controllerData = data.controller;
|
|
202
|
+
if (!controllerData)
|
|
203
|
+
return;
|
|
204
|
+
const router = yield prepareTarget({
|
|
205
|
+
target: controller,
|
|
206
|
+
namespace: `${namespace}/${controller.name}`,
|
|
207
|
+
prefix: controllerData.path,
|
|
208
|
+
instance: tsyringe_1.container.resolve(controller),
|
|
209
|
+
log,
|
|
210
|
+
});
|
|
211
|
+
_router.use(router.path, router.router);
|
|
212
|
+
}));
|
|
213
|
+
////////////////////////////////
|
|
214
|
+
/// Prepare Routes
|
|
215
|
+
////////////////////////////////
|
|
216
|
+
yield (0, object_util_1.$each)(Array.from(routes.routes), (route) => __awaiter(this, void 0, void 0, function* () {
|
|
217
|
+
if (typeof route !== "object")
|
|
218
|
+
return;
|
|
219
|
+
yield prepareRoutes({
|
|
220
|
+
target: target,
|
|
221
|
+
router: _router,
|
|
222
|
+
route,
|
|
223
|
+
namespace,
|
|
224
|
+
instance,
|
|
225
|
+
prefix,
|
|
226
|
+
log,
|
|
227
|
+
});
|
|
228
|
+
}));
|
|
229
|
+
return {
|
|
230
|
+
router: _router,
|
|
231
|
+
path: prefix,
|
|
232
|
+
};
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
function prepareRoutes(_a) {
|
|
236
|
+
return __awaiter(this, arguments, void 0, function* ({ target, router, route, instance, namespace, prefix, scopes = [], roles = [], log, }) {
|
|
237
|
+
var _b, _c, _d;
|
|
238
|
+
const { method, path, handler, propertyKey } = route;
|
|
239
|
+
const metadata = getData(handler);
|
|
240
|
+
const params = (_d = (_c = (_b = metadata.params) === null || _b === void 0 ? void 0 : _b.params) === null || _c === void 0 ? void 0 : _c[propertyKey]) !== null && _d !== void 0 ? _d : [];
|
|
241
|
+
const $fn = Reflect.get(router, method);
|
|
242
|
+
const hasParams = params.length > 0;
|
|
243
|
+
if (!$fn)
|
|
244
|
+
return;
|
|
245
|
+
const middlewares = [...metadata.middlewares];
|
|
246
|
+
(0, role_transform_1.default)(metadata.roles, (middleware) => middlewares.push(middleware));
|
|
247
|
+
(0, scope_transfrom_1.default)(metadata.scopes, (middleware) => middlewares.push(middleware));
|
|
248
|
+
log("routes", `${namespace}/${propertyKey} ${method.toUpperCase()} { ${path} }`);
|
|
249
|
+
if (!hasParams) {
|
|
250
|
+
$fn.call(router, path, ...middlewares, handler.bind(instance));
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
$fn.call(router, path, ...middlewares, (req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
254
|
+
const args = yield Promise.all(params.map((param) => __awaiter(this, void 0, void 0, function* () {
|
|
255
|
+
const { resolver, key } = param;
|
|
256
|
+
return yield resolver(req, res);
|
|
257
|
+
})));
|
|
258
|
+
return handler.bind(instance)(...args, req, res);
|
|
259
|
+
}));
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HyperController = void 0;
|
|
4
|
+
const decorator_base_1 = require("../__internals/decorator-base");
|
|
5
|
+
const constants_1 = require("../__internals/constants");
|
|
6
|
+
const HyperController = (options) => {
|
|
7
|
+
var _a, _b, _c;
|
|
8
|
+
const isString = typeof options === "string";
|
|
9
|
+
return (0, decorator_base_1.DecoratorHelper)({
|
|
10
|
+
type: constants_1.KEY_TYPE_CONTROLLER,
|
|
11
|
+
key: constants_1.KEY_PARAMS_CONTROLLER,
|
|
12
|
+
options: {
|
|
13
|
+
path: isString ? options : (_a = options === null || options === void 0 ? void 0 : options.path) !== null && _a !== void 0 ? _a : "/",
|
|
14
|
+
roles: isString ? [] : (_b = options === null || options === void 0 ? void 0 : options.roles) !== null && _b !== void 0 ? _b : [],
|
|
15
|
+
scopes: isString ? [] : (_c = options === null || options === void 0 ? void 0 : options.scopes) !== null && _c !== void 0 ? _c : [],
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
exports.HyperController = HyperController;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HyperModule = void 0;
|
|
4
|
+
const constants_1 = require("../__internals/constants");
|
|
5
|
+
const decorator_base_1 = require("../__internals/decorator-base");
|
|
6
|
+
/**
|
|
7
|
+
* Decorator to define a module with controllers and services.
|
|
8
|
+
*/
|
|
9
|
+
const HyperModule = (options) => (0, decorator_base_1.DecoratorHelper)({
|
|
10
|
+
type: constants_1.KEY_PARAMS_MODULE,
|
|
11
|
+
key: constants_1.KEY_PARAMS_MODULE,
|
|
12
|
+
options,
|
|
13
|
+
});
|
|
14
|
+
exports.HyperModule = HyperModule;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import "reflect-metadata";
|
|
2
|
+
import { MiddlewareHandler } from "hyper-express";
|
|
3
|
+
/**
|
|
4
|
+
* Middleware decorator to attach middleware to controllers, modules, and routes.
|
|
5
|
+
*/
|
|
6
|
+
export declare const Middleware: {
|
|
7
|
+
(...middleware: MiddlewareHandler[]): ClassDecorator & MethodDecorator;
|
|
8
|
+
/**
|
|
9
|
+
* Exclude middleware from matching paths.
|
|
10
|
+
*
|
|
11
|
+
* @param expresiosn
|
|
12
|
+
* @param middleware
|
|
13
|
+
* @returns
|
|
14
|
+
*/
|
|
15
|
+
exclude(expresiosn: RegExp | RegExp[], middleware: MiddlewareHandler): ClassDecorator & MethodDecorator;
|
|
16
|
+
/**
|
|
17
|
+
* Only run middleware on matching paths.
|
|
18
|
+
*
|
|
19
|
+
* @param expresiosn
|
|
20
|
+
* @param middleware
|
|
21
|
+
* @returns
|
|
22
|
+
*/
|
|
23
|
+
only(expresiosn: RegExp | RegExp[], middleware: MiddlewareHandler): ClassDecorator & MethodDecorator;
|
|
24
|
+
};
|