@zenofolio/hyper-decor 1.0.7 → 1.0.8
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/.agent/rules/philosophy.md +103 -0
- package/.agent/rules/writing.md +32 -0
- package/README.md +103 -201
- package/dist/__internals/constants.d.ts +1 -62
- package/dist/__internals/constants.js +3 -69
- package/dist/__internals/helpers/merge-metadata.d.ts +2 -3
- package/dist/__internals/helpers/merge-metadata.js +31 -7
- package/dist/__internals/helpers/prepare.helper.d.ts +4 -10
- package/dist/__internals/helpers/prepare.helper.js +325 -281
- package/dist/__internals/stores/hyper.store.d.ts +5 -0
- package/dist/__internals/stores/hyper.store.js +5 -0
- package/dist/__internals/stores/index.d.ts +4 -0
- package/dist/{lib/openapi/helpers → __internals/stores}/index.js +4 -7
- package/dist/__internals/stores/meta.store.d.ts +34 -0
- package/dist/__internals/stores/meta.store.js +107 -0
- package/dist/{stores → __internals/stores}/scope.store.d.ts +1 -1
- package/dist/__internals/transform/middleware.transform.d.ts +1 -1
- package/dist/__internals/transform/middleware.transform.js +1 -1
- package/dist/__internals/transform/role.transform.d.ts +1 -1
- package/dist/__internals/transform/role.transform.js +4 -4
- package/dist/__internals/transform/scope.transfrom.d.ts +1 -1
- package/dist/__internals/transform/scope.transfrom.js +2 -2
- package/dist/__internals/types.d.ts +53 -4
- package/dist/common/bootstrap.d.ts +6 -2
- package/dist/common/bootstrap.js +49 -10
- package/dist/common/testing.d.ts +56 -0
- package/dist/common/testing.js +193 -0
- package/dist/common/transport.d.ts +1 -0
- package/dist/common/transport.js +27 -14
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +2 -1
- package/dist/decorators.d.ts +1 -0
- package/dist/{stores/index.js → decorators.js} +1 -1
- package/dist/index.d.ts +7 -5
- package/dist/index.js +7 -5
- package/dist/lib/event/meta.store.d.ts +4 -0
- package/dist/lib/event/meta.store.js +5 -0
- package/dist/lib/openapi/collectors/class.collector.d.ts +5 -9
- package/dist/lib/openapi/collectors/class.collector.js +6 -63
- package/dist/lib/openapi/collectors/index.d.ts +3 -4
- package/dist/lib/openapi/collectors/index.js +0 -1
- package/dist/lib/openapi/collectors/method.collector.d.ts +6 -1
- package/dist/lib/openapi/collectors/method.collector.js +92 -59
- package/dist/lib/openapi/collectors/schema.collector.d.ts +3 -8
- package/dist/lib/openapi/collectors/schema.collector.js +17 -25
- package/dist/lib/openapi/constants.d.ts +1 -0
- package/dist/lib/openapi/constants.js +2 -2
- package/dist/lib/openapi/decorators.d.ts +16 -0
- package/dist/lib/openapi/decorators.js +93 -0
- package/dist/lib/openapi/index.d.ts +29 -5
- package/dist/lib/openapi/index.js +119 -5
- package/dist/lib/openapi/metadata.d.ts +7 -0
- package/dist/lib/openapi/metadata.js +8 -0
- package/dist/lib/openapi/metadata.registry.d.ts +1 -1
- package/dist/lib/server/decorators/File.d.ts +37 -0
- package/dist/{decorators → lib/server/decorators}/File.js +62 -75
- package/dist/lib/server/decorators/Http.d.ts +12 -0
- package/dist/lib/server/decorators/Http.js +56 -0
- package/dist/lib/server/decorators/HyperApp.d.ts +7 -0
- package/dist/lib/server/decorators/HyperApp.js +14 -0
- package/dist/lib/server/decorators/HyperController.d.ts +6 -0
- package/dist/lib/server/decorators/HyperController.js +15 -0
- package/dist/lib/server/decorators/HyperModule.d.ts +6 -0
- package/dist/lib/server/decorators/HyperModule.js +13 -0
- package/dist/lib/server/decorators/HyperService.d.ts +12 -0
- package/dist/lib/server/decorators/HyperService.js +30 -0
- package/dist/lib/server/decorators/Messaging.d.ts +8 -0
- package/dist/lib/server/decorators/Messaging.js +19 -0
- package/dist/{decorators → lib/server/decorators}/Middleware.d.ts +5 -12
- package/dist/lib/server/decorators/Middleware.js +52 -0
- package/dist/lib/server/decorators/Output.d.ts +6 -0
- package/dist/lib/server/decorators/Output.js +14 -0
- package/dist/lib/server/decorators/Pass.d.ts +10 -0
- package/dist/lib/server/decorators/Pass.js +13 -0
- package/dist/lib/server/decorators/Role.d.ts +7 -0
- package/dist/lib/server/decorators/Role.js +14 -0
- package/dist/lib/server/decorators/Routes.d.ts +14 -0
- package/dist/lib/server/decorators/Routes.js +39 -0
- package/dist/lib/server/decorators/Scope.d.ts +7 -0
- package/dist/lib/server/decorators/Scope.js +14 -0
- package/dist/{decorators → lib/server/decorators}/index.d.ts +6 -4
- package/dist/{decorators → lib/server/decorators}/index.js +6 -4
- package/dist/lib/server/decorators/metadata.d.ts +1 -0
- package/dist/lib/server/decorators/metadata.js +5 -0
- package/dist/{decorators → lib/server/decorators}/types.d.ts +16 -15
- package/dist/{exeptions → lib/server/exeptions}/HyperException.d.ts +2 -1
- package/dist/{exeptions → lib/server/exeptions}/HyperException.js +2 -1
- package/dist/{exeptions → lib/server/exeptions}/HyperFileException.js +1 -1
- package/dist/{exeptions → lib/server/exeptions}/NotRoleException.js +1 -1
- package/dist/{exeptions → lib/server/exeptions}/NotScopeException.js +1 -1
- package/dist/{__internals/helpers/tree.helper.d.ts → lib/tree/tree.d.ts} +12 -12
- package/dist/lib/tree/tree.js +106 -0
- package/package.json +10 -2
- package/scripts/clean.js +54 -54
- package/scripts/test-server.ts +85 -85
- package/vitest.config.mjs +1 -1
- package/debug.txt +0 -1
- package/dist/__internals/creators/request.creator.d.ts +0 -11
- package/dist/__internals/creators/request.creator.js +0 -55
- package/dist/__internals/creators/routes.creator.d.ts +0 -9
- package/dist/__internals/creators/routes.creator.js +0 -39
- package/dist/__internals/decorator-base.d.ts +0 -30
- package/dist/__internals/decorator-base.js +0 -122
- package/dist/__internals/helpers/imports.helper.d.ts +0 -8
- package/dist/__internals/helpers/imports.helper.js +0 -92
- package/dist/__internals/helpers/tree.helper.js +0 -81
- package/dist/__internals/stores/metadata.store.d.ts +0 -15
- package/dist/__internals/stores/metadata.store.js +0 -37
- package/dist/decorators/File.d.ts +0 -65
- package/dist/decorators/Http.d.ts +0 -62
- package/dist/decorators/Http.js +0 -139
- package/dist/decorators/HyperApp.d.ts +0 -3
- package/dist/decorators/HyperApp.js +0 -96
- package/dist/decorators/HyperController.d.ts +0 -2
- package/dist/decorators/HyperController.js +0 -20
- package/dist/decorators/HyperModule.d.ts +0 -5
- package/dist/decorators/HyperModule.js +0 -14
- package/dist/decorators/HyperService.d.ts +0 -15
- package/dist/decorators/HyperService.js +0 -29
- package/dist/decorators/Messaging.d.ts +0 -10
- package/dist/decorators/Messaging.js +0 -22
- package/dist/decorators/Middleware.js +0 -65
- package/dist/decorators/Output.d.ts +0 -9
- package/dist/decorators/Output.js +0 -18
- package/dist/decorators/Pass.d.ts +0 -15
- package/dist/decorators/Pass.js +0 -32
- package/dist/decorators/Role.d.ts +0 -6
- package/dist/decorators/Role.js +0 -34
- package/dist/decorators/Routes.d.ts +0 -15
- package/dist/decorators/Routes.js +0 -21
- package/dist/decorators/Scope.d.ts +0 -6
- package/dist/decorators/Scope.js +0 -25
- package/dist/decorators/Transform.d.ts +0 -14
- package/dist/decorators/Transform.js +0 -18
- package/dist/lib/openapi/collectors/param.collector.d.ts +0 -2
- package/dist/lib/openapi/collectors/param.collector.js +0 -64
- package/dist/lib/openapi/decorators/api-bearer-auth.decorator.d.ts +0 -2
- package/dist/lib/openapi/decorators/api-bearer-auth.decorator.js +0 -10
- package/dist/lib/openapi/decorators/api-method.decorator.d.ts +0 -3
- package/dist/lib/openapi/decorators/api-method.decorator.js +0 -11
- package/dist/lib/openapi/decorators/api-parameter.decorator.d.ts +0 -3
- package/dist/lib/openapi/decorators/api-parameter.decorator.js +0 -10
- package/dist/lib/openapi/decorators/api-request-body.decorator.d.ts +0 -3
- package/dist/lib/openapi/decorators/api-request-body.decorator.js +0 -10
- package/dist/lib/openapi/decorators/api-response.decorator.d.ts +0 -3
- package/dist/lib/openapi/decorators/api-response.decorator.js +0 -10
- package/dist/lib/openapi/decorators/api-security.decorator.d.ts +0 -3
- package/dist/lib/openapi/decorators/api-security.decorator.js +0 -10
- package/dist/lib/openapi/decorators/api-tag.decorator.d.ts +0 -3
- package/dist/lib/openapi/decorators/api-tag.decorator.js +0 -13
- package/dist/lib/openapi/decorators/index.d.ts +0 -7
- package/dist/lib/openapi/decorators/index.js +0 -23
- package/dist/lib/openapi/helpers/index.d.ts +0 -7
- package/dist/lib/openapi/helpers/method.helper.d.ts +0 -3
- package/dist/lib/openapi/helpers/method.helper.js +0 -20
- package/dist/lib/openapi/helpers/openapi.helper.d.ts +0 -7
- package/dist/lib/openapi/helpers/openapi.helper.js +0 -51
- package/dist/lib/openapi/helpers/parameter.helper.d.ts +0 -3
- package/dist/lib/openapi/helpers/parameter.helper.js +0 -16
- package/dist/lib/openapi/helpers/request-body.helper.d.ts +0 -3
- package/dist/lib/openapi/helpers/request-body.helper.js +0 -9
- package/dist/lib/openapi/helpers/response.helper.d.ts +0 -3
- package/dist/lib/openapi/helpers/response.helper.js +0 -18
- package/dist/lib/openapi/helpers/security.helper.d.ts +0 -3
- package/dist/lib/openapi/helpers/security.helper.js +0 -17
- package/dist/lib/openapi/helpers/tag.helper.d.ts +0 -3
- package/dist/lib/openapi/helpers/tag.helper.js +0 -10
- package/dist/stores/index.d.ts +0 -1
- package/vitest.json +0 -0
- /package/dist/{stores → __internals/stores}/scope.store.js +0 -0
- /package/dist/__internals/stores/{service.store.d.ts → serivces.store.d.ts} +0 -0
- /package/dist/__internals/stores/{service.store.js → serivces.store.js} +0 -0
- /package/dist/{decorators → lib/server/decorators}/types.js +0 -0
- /package/dist/{exeptions → lib/server/exeptions}/DuplicateControllerPathException.d.ts +0 -0
- /package/dist/{exeptions → lib/server/exeptions}/DuplicateControllerPathException.js +0 -0
- /package/dist/{exeptions → lib/server/exeptions}/DuplicatedException.d.ts +0 -0
- /package/dist/{exeptions → lib/server/exeptions}/DuplicatedException.js +0 -0
- /package/dist/{exeptions → lib/server/exeptions}/DuplicatedHandlerException.d.ts +0 -0
- /package/dist/{exeptions → lib/server/exeptions}/DuplicatedHandlerException.js +0 -0
- /package/dist/{exeptions → lib/server/exeptions}/HyperFileException.d.ts +0 -0
- /package/dist/{exeptions → lib/server/exeptions}/MethodNotFountException.d.ts +0 -0
- /package/dist/{exeptions → lib/server/exeptions}/MethodNotFountException.js +0 -0
- /package/dist/{exeptions → lib/server/exeptions}/NotPropertyException.d.ts +0 -0
- /package/dist/{exeptions → lib/server/exeptions}/NotPropertyException.js +0 -0
- /package/dist/{exeptions → lib/server/exeptions}/NotRoleException.d.ts +0 -0
- /package/dist/{exeptions → lib/server/exeptions}/NotScopeException.d.ts +0 -0
- /package/dist/{exeptions → lib/server/exeptions}/WrongPlaceException.d.ts +0 -0
- /package/dist/{exeptions → lib/server/exeptions}/WrongPlaceException.js +0 -0
- /package/dist/{exeptions → lib/server/exeptions}/index.d.ts +0 -0
- /package/dist/{exeptions → lib/server/exeptions}/index.js +0 -0
- /package/dist/{exeptions → lib/server/exeptions}/types.d.ts +0 -0
- /package/dist/{exeptions → lib/server/exeptions}/types.js +0 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ApiSummary = ApiSummary;
|
|
4
|
+
exports.ApiDescription = ApiDescription;
|
|
5
|
+
exports.ApiOperationId = ApiOperationId;
|
|
6
|
+
exports.ApiTag = ApiTag;
|
|
7
|
+
exports.ApiResponse = ApiResponse;
|
|
8
|
+
exports.ApiParameter = ApiParameter;
|
|
9
|
+
exports.ApiRequestBody = ApiRequestBody;
|
|
10
|
+
exports.ApiSecurity = ApiSecurity;
|
|
11
|
+
exports.ApiBearerAuth = ApiBearerAuth;
|
|
12
|
+
exports.ApiMethod = ApiMethod;
|
|
13
|
+
exports.ApiNamespace = ApiNamespace;
|
|
14
|
+
exports.ApiIgnore = ApiIgnore;
|
|
15
|
+
const metadata_1 = require("./metadata");
|
|
16
|
+
/**
|
|
17
|
+
* 📝 OpenAPI Decorators consolidated for better performance and clean imports.
|
|
18
|
+
*/
|
|
19
|
+
function ApiSummary(summary) {
|
|
20
|
+
return (target, propertyKey) => {
|
|
21
|
+
metadata_1.SwaggerMeta.set(target, propertyKey, { summary });
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function ApiDescription(description) {
|
|
25
|
+
return (target, propertyKey) => {
|
|
26
|
+
metadata_1.SwaggerMeta.set(target, propertyKey, { description });
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function ApiOperationId(operationId) {
|
|
30
|
+
return (target, propertyKey) => {
|
|
31
|
+
metadata_1.SwaggerMeta.set(target, propertyKey, { operationId });
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function ApiTag(options) {
|
|
35
|
+
const tag = typeof options === 'string' ? { name: options } : options;
|
|
36
|
+
return (target, propertyKey) => {
|
|
37
|
+
if (propertyKey) {
|
|
38
|
+
const current = metadata_1.SwaggerMeta.get(target, propertyKey);
|
|
39
|
+
const tags = [...(current.tags || []), tag];
|
|
40
|
+
// Use Map to deduplicate by name
|
|
41
|
+
const uniqueTags = Array.from(new Map(tags.map(t => [t.name, t])).values());
|
|
42
|
+
metadata_1.SwaggerMeta.set(target, propertyKey, { tags: uniqueTags });
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
const current = metadata_1.SwaggerMeta.get(target);
|
|
46
|
+
const tags = [...(current.tags || []), tag];
|
|
47
|
+
const uniqueTags = Array.from(new Map(tags.map(t => [t.name, t])).values());
|
|
48
|
+
metadata_1.SwaggerMeta.set(target, undefined, { tags: uniqueTags });
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function ApiResponse(options) {
|
|
53
|
+
return (target, propertyKey) => {
|
|
54
|
+
metadata_1.SwaggerMeta.set(target, propertyKey, { responses: options });
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function ApiParameter(options) {
|
|
58
|
+
return (target, propertyKey) => {
|
|
59
|
+
const current = metadata_1.SwaggerMeta.get(target, propertyKey);
|
|
60
|
+
const parameters = [...(current.parameters || []), options];
|
|
61
|
+
metadata_1.SwaggerMeta.set(target, propertyKey, { parameters });
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function ApiRequestBody(options) {
|
|
65
|
+
return (target, propertyKey) => {
|
|
66
|
+
metadata_1.SwaggerMeta.set(target, propertyKey, { requestBody: options });
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function ApiSecurity(options) {
|
|
70
|
+
return (target, propertyKey) => {
|
|
71
|
+
const current = metadata_1.SwaggerMeta.get(target, propertyKey);
|
|
72
|
+
const security = [...(current.security || []), options];
|
|
73
|
+
metadata_1.SwaggerMeta.set(target, propertyKey, { security });
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function ApiBearerAuth(name = 'bearerAuth') {
|
|
77
|
+
return ApiSecurity({ [name]: [] });
|
|
78
|
+
}
|
|
79
|
+
function ApiMethod(options) {
|
|
80
|
+
return (target, propertyKey) => {
|
|
81
|
+
metadata_1.SwaggerMeta.set(target, propertyKey, options);
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function ApiNamespace(name) {
|
|
85
|
+
return (target, propertyKey) => {
|
|
86
|
+
metadata_1.SwaggerMeta.set(target, propertyKey, { namespace: name });
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function ApiIgnore() {
|
|
90
|
+
return (target, propertyKey) => {
|
|
91
|
+
metadata_1.SwaggerMeta.set(target, propertyKey, { ignore: true });
|
|
92
|
+
};
|
|
93
|
+
}
|
|
@@ -1,6 +1,30 @@
|
|
|
1
|
-
export * from "./metadata.registry";
|
|
2
|
-
export * from "./constants";
|
|
3
|
-
export * from "./collectors";
|
|
4
|
-
export * from "./decorators";
|
|
5
|
-
export * from "./helpers";
|
|
6
1
|
export * from "./types";
|
|
2
|
+
import { ApiBearerAuth, ApiDescription, ApiOperationId, ApiParameter, ApiRequestBody, ApiResponse, ApiSecurity, ApiSummary, ApiTag, ApiMethod, ApiNamespace, ApiIgnore } from "./decorators";
|
|
3
|
+
export declare const OpenApi: {
|
|
4
|
+
Summary: typeof ApiSummary;
|
|
5
|
+
Description: typeof ApiDescription;
|
|
6
|
+
OperationId: typeof ApiOperationId;
|
|
7
|
+
Tag: typeof ApiTag;
|
|
8
|
+
Response: typeof ApiResponse;
|
|
9
|
+
Parameter: typeof ApiParameter;
|
|
10
|
+
RequestBody: typeof ApiRequestBody;
|
|
11
|
+
Security: typeof ApiSecurity;
|
|
12
|
+
BearerAuth: typeof ApiBearerAuth;
|
|
13
|
+
Method: typeof ApiMethod;
|
|
14
|
+
Namespace: typeof ApiNamespace;
|
|
15
|
+
Ignore: typeof ApiIgnore;
|
|
16
|
+
};
|
|
17
|
+
export { ApiBearerAuth, ApiDescription, ApiOperationId, ApiParameter, ApiRequestBody, ApiResponse, ApiSecurity, ApiSummary, ApiTag, ApiMethod, ApiNamespace, ApiIgnore, };
|
|
18
|
+
import { Constructor } from "../server/decorators/types";
|
|
19
|
+
import { OpenAPIDocument } from "./types";
|
|
20
|
+
/**
|
|
21
|
+
* Generates an OpenAPI specification object from a HyperApp class.
|
|
22
|
+
*
|
|
23
|
+
* @param App The Root Application Class
|
|
24
|
+
* @param options Generator options
|
|
25
|
+
* @returns OpenAPI Spec Object
|
|
26
|
+
*/
|
|
27
|
+
export declare function getOpenAPI(App: Constructor, options?: {
|
|
28
|
+
includeNamespaces?: string[];
|
|
29
|
+
excludeNamespaces?: string[];
|
|
30
|
+
}): OpenAPIDocument;
|
|
@@ -14,9 +14,123 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
__exportStar(require("./collectors"), exports);
|
|
20
|
-
__exportStar(require("./decorators"), exports);
|
|
21
|
-
__exportStar(require("./helpers"), exports);
|
|
17
|
+
exports.ApiIgnore = exports.ApiNamespace = exports.ApiMethod = exports.ApiTag = exports.ApiSummary = exports.ApiSecurity = exports.ApiResponse = exports.ApiRequestBody = exports.ApiParameter = exports.ApiOperationId = exports.ApiDescription = exports.ApiBearerAuth = exports.OpenApi = void 0;
|
|
18
|
+
exports.getOpenAPI = getOpenAPI;
|
|
22
19
|
__exportStar(require("./types"), exports);
|
|
20
|
+
const decorators_1 = require("./decorators");
|
|
21
|
+
Object.defineProperty(exports, "ApiBearerAuth", { enumerable: true, get: function () { return decorators_1.ApiBearerAuth; } });
|
|
22
|
+
Object.defineProperty(exports, "ApiDescription", { enumerable: true, get: function () { return decorators_1.ApiDescription; } });
|
|
23
|
+
Object.defineProperty(exports, "ApiOperationId", { enumerable: true, get: function () { return decorators_1.ApiOperationId; } });
|
|
24
|
+
Object.defineProperty(exports, "ApiParameter", { enumerable: true, get: function () { return decorators_1.ApiParameter; } });
|
|
25
|
+
Object.defineProperty(exports, "ApiRequestBody", { enumerable: true, get: function () { return decorators_1.ApiRequestBody; } });
|
|
26
|
+
Object.defineProperty(exports, "ApiResponse", { enumerable: true, get: function () { return decorators_1.ApiResponse; } });
|
|
27
|
+
Object.defineProperty(exports, "ApiSecurity", { enumerable: true, get: function () { return decorators_1.ApiSecurity; } });
|
|
28
|
+
Object.defineProperty(exports, "ApiSummary", { enumerable: true, get: function () { return decorators_1.ApiSummary; } });
|
|
29
|
+
Object.defineProperty(exports, "ApiTag", { enumerable: true, get: function () { return decorators_1.ApiTag; } });
|
|
30
|
+
Object.defineProperty(exports, "ApiMethod", { enumerable: true, get: function () { return decorators_1.ApiMethod; } });
|
|
31
|
+
Object.defineProperty(exports, "ApiNamespace", { enumerable: true, get: function () { return decorators_1.ApiNamespace; } });
|
|
32
|
+
Object.defineProperty(exports, "ApiIgnore", { enumerable: true, get: function () { return decorators_1.ApiIgnore; } });
|
|
33
|
+
exports.OpenApi = {
|
|
34
|
+
Summary: decorators_1.ApiSummary,
|
|
35
|
+
Description: decorators_1.ApiDescription,
|
|
36
|
+
OperationId: decorators_1.ApiOperationId,
|
|
37
|
+
Tag: decorators_1.ApiTag,
|
|
38
|
+
Response: decorators_1.ApiResponse,
|
|
39
|
+
Parameter: decorators_1.ApiParameter,
|
|
40
|
+
RequestBody: decorators_1.ApiRequestBody,
|
|
41
|
+
Security: decorators_1.ApiSecurity,
|
|
42
|
+
BearerAuth: decorators_1.ApiBearerAuth,
|
|
43
|
+
Method: decorators_1.ApiMethod,
|
|
44
|
+
Namespace: decorators_1.ApiNamespace,
|
|
45
|
+
Ignore: decorators_1.ApiIgnore,
|
|
46
|
+
};
|
|
47
|
+
const tree_1 = require("../tree/tree");
|
|
48
|
+
const metadata_registry_1 = require("./metadata.registry");
|
|
49
|
+
// --- Registration ---
|
|
50
|
+
const collectors_1 = require("./collectors");
|
|
51
|
+
metadata_registry_1.openApiRegistry.registerCollector("class", collectors_1.collectClassMetadata);
|
|
52
|
+
metadata_registry_1.openApiRegistry.registerCollector("method", collectors_1.collectMethodMetadata);
|
|
53
|
+
/**
|
|
54
|
+
* Generates an OpenAPI specification object from a HyperApp class.
|
|
55
|
+
*
|
|
56
|
+
* @param App The Root Application Class
|
|
57
|
+
* @param options Generator options
|
|
58
|
+
* @returns OpenAPI Spec Object
|
|
59
|
+
*/
|
|
60
|
+
function getOpenAPI(App, options = {}) {
|
|
61
|
+
const tree = (0, tree_1.getAppTree)(App);
|
|
62
|
+
const spec = {
|
|
63
|
+
openapi: "3.0.0",
|
|
64
|
+
info: {
|
|
65
|
+
title: tree.app.name || "HyperApp API",
|
|
66
|
+
version: tree.app.version || "1.0.0",
|
|
67
|
+
},
|
|
68
|
+
paths: {},
|
|
69
|
+
};
|
|
70
|
+
const processController = (ctrl, parentNamespace) => {
|
|
71
|
+
const ctrlOpenApi = ctrl.openapi;
|
|
72
|
+
if (ctrlOpenApi === null || ctrlOpenApi === void 0 ? void 0 : ctrlOpenApi.ignore)
|
|
73
|
+
return;
|
|
74
|
+
const ctrlNamespace = (ctrlOpenApi === null || ctrlOpenApi === void 0 ? void 0 : ctrlOpenApi.namespace) || parentNamespace;
|
|
75
|
+
ctrl.routes.forEach((route) => {
|
|
76
|
+
var _a, _b;
|
|
77
|
+
const routeOpenApi = route.openapi;
|
|
78
|
+
if (!routeOpenApi || routeOpenApi.ignore)
|
|
79
|
+
return;
|
|
80
|
+
const path = normalizePath(route.fullPath);
|
|
81
|
+
if (!spec.paths[path])
|
|
82
|
+
spec.paths[path] = {};
|
|
83
|
+
const methodNamespace = routeOpenApi.namespace || ctrlNamespace;
|
|
84
|
+
// Filtering logic
|
|
85
|
+
if (options.includeNamespaces && options.includeNamespaces.length > 0) {
|
|
86
|
+
if (!methodNamespace || !options.includeNamespaces.includes(methodNamespace))
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
if (options.excludeNamespaces && options.excludeNamespaces.length > 0) {
|
|
90
|
+
if (methodNamespace && options.excludeNamespaces.includes(methodNamespace))
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
// --- Merge Metadata Inheritance ---
|
|
94
|
+
const ctrlData = (ctrl.openapi || {});
|
|
95
|
+
const finalOperation = Object.assign(Object.assign(Object.assign({ responses: {} }, ctrlData), routeOpenApi), {
|
|
96
|
+
// Merge Tags (unique by name)
|
|
97
|
+
tags: Array.from(new Map([
|
|
98
|
+
...(ctrlData.tags || []).map(t => [t.name, t]),
|
|
99
|
+
...(routeOpenApi.tags || []).map(t => [t.name, t])
|
|
100
|
+
]).values()),
|
|
101
|
+
// Merge Security (additive)
|
|
102
|
+
security: [
|
|
103
|
+
...(ctrlData.security || []),
|
|
104
|
+
...(routeOpenApi.security || [])
|
|
105
|
+
] });
|
|
106
|
+
// Remove empty fields to keep spec clean
|
|
107
|
+
if (((_a = finalOperation.tags) === null || _a === void 0 ? void 0 : _a.length) === 0)
|
|
108
|
+
delete finalOperation.tags;
|
|
109
|
+
if (((_b = finalOperation.security) === null || _b === void 0 ? void 0 : _b.length) === 0)
|
|
110
|
+
delete finalOperation.security;
|
|
111
|
+
spec.paths[path] = Object.assign(Object.assign({}, spec.paths[path]), { [route.method.toLowerCase()]: finalOperation });
|
|
112
|
+
});
|
|
113
|
+
// Clean up empty paths if all methods were filtered out
|
|
114
|
+
Object.keys(spec.paths).forEach(path => {
|
|
115
|
+
if (Object.keys(spec.paths[path]).length === 0) {
|
|
116
|
+
delete spec.paths[path];
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
};
|
|
120
|
+
function normalizePath(path) {
|
|
121
|
+
let normalized = path.replace(/:([a-zA-Z0-9_]+)/g, '{$1}');
|
|
122
|
+
// Remove trailing slash if it's not the root path
|
|
123
|
+
if (normalized.length > 1 && normalized.endsWith('/')) {
|
|
124
|
+
normalized = normalized.slice(0, -1);
|
|
125
|
+
}
|
|
126
|
+
return normalized;
|
|
127
|
+
}
|
|
128
|
+
const processModule = (mod) => {
|
|
129
|
+
var _a;
|
|
130
|
+
const modNamespace = (_a = mod.openapi) === null || _a === void 0 ? void 0 : _a.namespace;
|
|
131
|
+
Object.values(mod.controllers).forEach(ctrl => processController(ctrl, modNamespace));
|
|
132
|
+
Object.values(mod.modules).forEach(processModule);
|
|
133
|
+
};
|
|
134
|
+
Object.values(tree.modules).forEach(processModule);
|
|
135
|
+
return spec;
|
|
136
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SwaggerMeta = void 0;
|
|
4
|
+
const meta_store_1 = require("../../__internals/stores/meta.store");
|
|
5
|
+
/**
|
|
6
|
+
* 🚀 Metadata accessor for OpenAPI/Swagger documentation
|
|
7
|
+
*/
|
|
8
|
+
exports.SwaggerMeta = meta_store_1.Metadata.prefix('hyper:openapi');
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AppTree } from "
|
|
1
|
+
import { AppTree } from "../tree/tree";
|
|
2
2
|
export type CollectorType = "class" | "method" | "param";
|
|
3
3
|
export type CollectorFn = (target: any, propertyKey?: string) => any;
|
|
4
4
|
export type TreeProcessorFn = (tree: AppTree) => void;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Request } from "hyper-express/types";
|
|
2
|
+
/**
|
|
3
|
+
* File upload restrictions
|
|
4
|
+
*/
|
|
5
|
+
export interface FileUploadRestrictions {
|
|
6
|
+
allowedMimeTypes: string[];
|
|
7
|
+
maxFileSize: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* File restrictions resolver
|
|
11
|
+
*/
|
|
12
|
+
export type FileRestrictions = FileUploadRestrictions | ((request: Request) => FileUploadRestrictions | Promise<FileUploadRestrictions>);
|
|
13
|
+
/**
|
|
14
|
+
* File decorator options
|
|
15
|
+
*/
|
|
16
|
+
export interface FileOptions {
|
|
17
|
+
fieldName: string | string[];
|
|
18
|
+
restrictions?: FileRestrictions;
|
|
19
|
+
required?: boolean;
|
|
20
|
+
}
|
|
21
|
+
export interface UploadedFile {
|
|
22
|
+
field: string;
|
|
23
|
+
name: string;
|
|
24
|
+
filename: string;
|
|
25
|
+
mimeType: string;
|
|
26
|
+
size: number;
|
|
27
|
+
extension: string;
|
|
28
|
+
buffer: Buffer;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Decorator to extract file from the request
|
|
32
|
+
*/
|
|
33
|
+
export declare const File: {
|
|
34
|
+
(options: FileOptions | string): (target: object, propertyKey: string | symbol, index: number) => void;
|
|
35
|
+
options(options: FileOptions, required?: boolean): (fieldName: string | string[]) => (target: object, propertyKey: string | symbol, index: number) => void;
|
|
36
|
+
restrictions(restrictions: FileRestrictions): (fieldName: string | string[], required?: boolean) => (target: object, propertyKey: string | symbol, index: number) => void;
|
|
37
|
+
};
|
|
@@ -8,46 +8,37 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
+
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
12
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
13
|
+
var m = o[Symbol.asyncIterator], i;
|
|
14
|
+
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
|
15
|
+
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
|
16
|
+
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
17
|
+
};
|
|
11
18
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
19
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
20
|
};
|
|
14
21
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
22
|
exports.File = void 0;
|
|
16
23
|
const Http_1 = require("./Http");
|
|
17
|
-
const consumers_1 = require("stream/consumers");
|
|
18
24
|
const HyperFileException_1 = __importDefault(require("../exeptions/HyperFileException"));
|
|
19
25
|
/**
|
|
20
26
|
* Decorator to extract file from the request
|
|
21
|
-
*
|
|
22
|
-
* @param param0
|
|
23
27
|
*/
|
|
24
28
|
const File = (options) => {
|
|
25
29
|
const _options = typeof options === "string" ? { fieldName: options } : options;
|
|
26
30
|
return (0, Http_1.createCustomRequestDecorator)("File", (request) => __awaiter(void 0, void 0, void 0, function* () {
|
|
27
|
-
var _a
|
|
31
|
+
var _a;
|
|
28
32
|
const { allowedMimeTypes, maxFileSize } = yield resolveRestrictions(request, _options.restrictions);
|
|
29
33
|
const passTypes = allowedMimeTypes.includes("*") || allowedMimeTypes.length === 0;
|
|
30
34
|
const passSize = maxFileSize === Infinity;
|
|
31
35
|
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
36
|
const isMultipart = contentType === null || contentType === void 0 ? void 0 : contentType.includes("multipart/form-data");
|
|
34
37
|
if (!isMultipart) {
|
|
35
38
|
throw new HyperFileException_1.default("Invalid request, expected multipart form data", {
|
|
36
39
|
fieldName: _options.fieldName,
|
|
37
40
|
});
|
|
38
41
|
}
|
|
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
42
|
const files = yield extractFiles(request, {
|
|
52
43
|
maxSize: passSize ? undefined : maxFileSize,
|
|
53
44
|
mimeTypes: passTypes ? undefined : allowedMimeTypes,
|
|
@@ -64,35 +55,16 @@ const File = (options) => {
|
|
|
64
55
|
}));
|
|
65
56
|
};
|
|
66
57
|
exports.File = File;
|
|
67
|
-
/**
|
|
68
|
-
*
|
|
69
|
-
* Helper function to create a file decorator with options
|
|
70
|
-
*
|
|
71
|
-
* @param options
|
|
72
|
-
* @returns
|
|
73
|
-
*/
|
|
74
58
|
exports.File.options = (options, required = false) => {
|
|
75
59
|
return (fieldName) => {
|
|
76
60
|
return (0, exports.File)(Object.assign(Object.assign({}, options), { required, fieldName }));
|
|
77
61
|
};
|
|
78
62
|
};
|
|
79
|
-
/**
|
|
80
|
-
* Helper function to create a file decorator with restrictions
|
|
81
|
-
*
|
|
82
|
-
* @param restrictions
|
|
83
|
-
* @returns
|
|
84
|
-
*/
|
|
85
63
|
exports.File.restrictions = (restrictions) => {
|
|
86
64
|
return (fieldName, required = false) => {
|
|
87
65
|
return (0, exports.File)({ fieldName, restrictions, required });
|
|
88
66
|
};
|
|
89
67
|
};
|
|
90
|
-
/////////////////////////////
|
|
91
|
-
// Types
|
|
92
|
-
/////////////////////////////
|
|
93
|
-
/////////////////////////////
|
|
94
|
-
/// Utility
|
|
95
|
-
/////////////////////////////
|
|
96
68
|
const resolveRestrictions = (request, restrictions) => __awaiter(void 0, void 0, void 0, function* () {
|
|
97
69
|
if (typeof restrictions === "function") {
|
|
98
70
|
return yield restrictions(request);
|
|
@@ -103,63 +75,78 @@ const resolveRestrictions = (request, restrictions) => __awaiter(void 0, void 0,
|
|
|
103
75
|
});
|
|
104
76
|
});
|
|
105
77
|
/**
|
|
106
|
-
* Extract files from a request with validation
|
|
107
|
-
*
|
|
108
|
-
* @param request
|
|
109
|
-
* @param options Validation and transformation options
|
|
110
|
-
* @returns Transformed or raw file details
|
|
78
|
+
* Extract files from a request with validation and secure streaming.
|
|
111
79
|
*/
|
|
112
80
|
const extractFiles = (request, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
113
81
|
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
82
|
const filesMap = {};
|
|
83
|
+
// Track if we are already over total limit (Content-Length check as first line of defense)
|
|
84
|
+
const totalLength = Number((_a = request.headers) === null || _a === void 0 ? void 0 : _a["content-length"]);
|
|
85
|
+
if ((options === null || options === void 0 ? void 0 : options.maxSize) && !isNaN(totalLength) && totalLength > options.maxSize + 1024 * 10) { // Buffer for boundaries
|
|
86
|
+
// Content-Length is significantly larger than allowed file size
|
|
87
|
+
// We don't throw yet because multipart might have multiple files or large fields
|
|
88
|
+
}
|
|
119
89
|
yield request.multipart((field) => __awaiter(void 0, void 0, void 0, function* () {
|
|
120
|
-
var _a, _b, _c
|
|
90
|
+
var _a, e_1, _b, _c;
|
|
91
|
+
var _d, _e;
|
|
121
92
|
if (field.file && field.file.stream) {
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
93
|
+
const chunks = [];
|
|
94
|
+
let totalRead = 0;
|
|
95
|
+
try {
|
|
96
|
+
// Safe stream reading with early exit
|
|
97
|
+
for (var _f = true, _g = __asyncValues(field.file.stream), _h; _h = yield _g.next(), _a = _h.done, !_a; _f = true) {
|
|
98
|
+
_c = _h.value;
|
|
99
|
+
_f = false;
|
|
100
|
+
const chunk = _c;
|
|
101
|
+
totalRead += chunk.length;
|
|
102
|
+
if ((options === null || options === void 0 ? void 0 : options.maxSize) && totalRead > options.maxSize) {
|
|
103
|
+
throw new HyperFileException_1.default(`File '${field.name}' exceeds the maximum limit of ${options.maxSize} bytes`, { field: field.name, maxSize: options.maxSize });
|
|
104
|
+
}
|
|
105
|
+
chunks.push(chunk);
|
|
106
|
+
}
|
|
128
107
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
allowedMimeTypes: options.mimeTypes,
|
|
136
|
-
mimeType,
|
|
137
|
-
});
|
|
108
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
109
|
+
finally {
|
|
110
|
+
try {
|
|
111
|
+
if (!_f && !_a && (_b = _g.return)) yield _b.call(_g);
|
|
112
|
+
}
|
|
113
|
+
finally { if (e_1) throw e_1.error; }
|
|
138
114
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
115
|
+
const bufferFile = Buffer.concat(chunks);
|
|
116
|
+
const { fileTypeFromBuffer } = yield import("file-type");
|
|
117
|
+
const type = yield fileTypeFromBuffer(bufferFile);
|
|
118
|
+
const mimeType = (type === null || type === void 0 ? void 0 : type.mime) || "unknown/unrecognized";
|
|
119
|
+
const extension = (type === null || type === void 0 ? void 0 : type.ext) || "bin";
|
|
120
|
+
// Validate MIME type early if unrecognized
|
|
121
|
+
if (!type && (options === null || options === void 0 ? void 0 : options.mimeTypes) && options.mimeTypes.length > 0) {
|
|
122
|
+
throw new HyperFileException_1.default(`Invalid file type for field '${field.name}'. Could not recognize file signature. Expected one of: ${options.mimeTypes.join(", ")}`, { field: field.name, allowedMimeTypes: options.mimeTypes });
|
|
143
123
|
}
|
|
144
|
-
|
|
145
|
-
|
|
124
|
+
// Validate MIME type if recognized
|
|
125
|
+
if ((options === null || options === void 0 ? void 0 : options.mimeTypes) && !options.mimeTypes.includes(mimeType)) {
|
|
126
|
+
throw new HyperFileException_1.default(`Invalid file type for field '${field.name}'. Expected: ${options.mimeTypes.join(", ")}, Received: ${mimeType}`, {
|
|
146
127
|
field: field.name,
|
|
147
|
-
|
|
128
|
+
allowedMimeTypes: options.mimeTypes,
|
|
129
|
+
receivedMimeType: mimeType,
|
|
148
130
|
});
|
|
149
131
|
}
|
|
150
|
-
if ((options === null || options === void 0 ? void 0 : options.requireName) && !((
|
|
151
|
-
throw new HyperFileException_1.default(`File name is required`, {
|
|
132
|
+
if ((options === null || options === void 0 ? void 0 : options.requireName) && !((_d = field.file) === null || _d === void 0 ? void 0 : _d.name)) {
|
|
133
|
+
throw new HyperFileException_1.default(`File name is required for field '${field.name}'`, {
|
|
152
134
|
field: field.name,
|
|
153
135
|
});
|
|
154
136
|
}
|
|
155
|
-
//
|
|
156
|
-
const
|
|
157
|
-
|
|
137
|
+
// Secure filename resolution
|
|
138
|
+
const rawName = ((_e = field.file) === null || _e === void 0 ? void 0 : _e.name) || field.name;
|
|
139
|
+
// Sanitize: remove null bytes, path traversal sequences, and extract base name
|
|
140
|
+
const sanitizedBase = rawName.replace(/\0/g, "").split(/[\\/]/).pop() || "file";
|
|
141
|
+
const nameOnly = sanitizedBase.includes(".")
|
|
142
|
+
? sanitizedBase.substring(0, sanitizedBase.lastIndexOf("."))
|
|
143
|
+
: sanitizedBase;
|
|
144
|
+
const filename = `${nameOnly}.${extension}`;
|
|
158
145
|
filesMap[field.name] = {
|
|
159
146
|
field: field.name,
|
|
160
|
-
name:
|
|
147
|
+
name: nameOnly,
|
|
161
148
|
filename: filename,
|
|
162
|
-
|
|
149
|
+
extension: extension,
|
|
163
150
|
size: bufferFile.byteLength,
|
|
164
151
|
mimeType: mimeType,
|
|
165
152
|
buffer: bufferFile,
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ParameterResolver } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* 🛠️ Helper to create parameter decorators
|
|
4
|
+
*/
|
|
5
|
+
export declare function createParamDecorator(source: "body" | "query" | "params" | "headers" | "req" | "res", decorator: string, keyOrSchema?: string | object | Function, schemaOrTransform?: object | Function, isWholeSource?: boolean, customResolver?: ParameterResolver): (target: object, propertyKey: string | symbol, index: number) => void;
|
|
6
|
+
export declare function Query(keyOrSchema?: string | object | Function, schemaOrTransform?: object | Function): (target: object, propertyKey: string | symbol, index: number) => void;
|
|
7
|
+
export declare function Body(keyOrSchema?: string | object | Function, schemaOrTransform?: object | Function): (target: object, propertyKey: string | symbol, index: number) => void;
|
|
8
|
+
export declare function Param(keyOrSchema: string | object | Function, schemaOrTransform?: object | Function): (target: object, propertyKey: string | symbol, index: number) => void;
|
|
9
|
+
export declare function Headers(keyOrSchema?: string | object | Function, schemaOrTransform?: object | Function): (target: object, propertyKey: string | symbol, index: number) => void;
|
|
10
|
+
export declare const Req: () => (target: object, propertyKey: string | symbol, index: number) => void;
|
|
11
|
+
export declare const Res: () => (target: object, propertyKey: string | symbol, index: number) => void;
|
|
12
|
+
export declare const createCustomRequestDecorator: (decoratorName: string, resolver: ParameterResolver) => (target: object, propertyKey: string | symbol, index: number) => void;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createCustomRequestDecorator = exports.Res = exports.Req = void 0;
|
|
4
|
+
exports.createParamDecorator = createParamDecorator;
|
|
5
|
+
exports.Query = Query;
|
|
6
|
+
exports.Body = Body;
|
|
7
|
+
exports.Param = Param;
|
|
8
|
+
exports.Headers = Headers;
|
|
9
|
+
const metadata_1 = require("./metadata");
|
|
10
|
+
/**
|
|
11
|
+
* 🛠️ Helper to create parameter decorators
|
|
12
|
+
*/
|
|
13
|
+
function createParamDecorator(source, decorator, keyOrSchema, schemaOrTransform, isWholeSource = false, customResolver) {
|
|
14
|
+
return (target, propertyKey, index) => {
|
|
15
|
+
var _a;
|
|
16
|
+
const root = metadata_1.HyperMeta.get(target, propertyKey);
|
|
17
|
+
const params = ((_a = root.params) === null || _a === void 0 ? void 0 : _a.params) || [];
|
|
18
|
+
const picker = typeof keyOrSchema === 'string' ? keyOrSchema : undefined;
|
|
19
|
+
const schema = (typeof keyOrSchema === 'object' || typeof keyOrSchema === 'function')
|
|
20
|
+
? keyOrSchema
|
|
21
|
+
: schemaOrTransform;
|
|
22
|
+
params.push({
|
|
23
|
+
index,
|
|
24
|
+
type: (Reflect.getMetadata("design:paramtypes", target, propertyKey) || [])[index],
|
|
25
|
+
source,
|
|
26
|
+
picker,
|
|
27
|
+
schema,
|
|
28
|
+
isWholeSource: isWholeSource || (picker === undefined && keyOrSchema !== undefined),
|
|
29
|
+
decorator,
|
|
30
|
+
resolver: customResolver,
|
|
31
|
+
});
|
|
32
|
+
metadata_1.HyperMeta.set(target, propertyKey, {
|
|
33
|
+
params: { params }
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function Query(keyOrSchema, schemaOrTransform) {
|
|
38
|
+
return createParamDecorator("query", "Query", keyOrSchema, schemaOrTransform);
|
|
39
|
+
}
|
|
40
|
+
function Body(keyOrSchema, schemaOrTransform) {
|
|
41
|
+
return createParamDecorator("body", "Body", keyOrSchema, schemaOrTransform);
|
|
42
|
+
}
|
|
43
|
+
function Param(keyOrSchema, schemaOrTransform) {
|
|
44
|
+
return createParamDecorator("params", "Param", keyOrSchema, schemaOrTransform);
|
|
45
|
+
}
|
|
46
|
+
function Headers(keyOrSchema, schemaOrTransform) {
|
|
47
|
+
return createParamDecorator("headers", "Headers", keyOrSchema, schemaOrTransform);
|
|
48
|
+
}
|
|
49
|
+
const Req = () => createParamDecorator("req", "Req", undefined, undefined, true, (req) => req);
|
|
50
|
+
exports.Req = Req;
|
|
51
|
+
const Res = () => createParamDecorator("res", "Res", undefined, undefined, true, (_req, res) => res);
|
|
52
|
+
exports.Res = Res;
|
|
53
|
+
const createCustomRequestDecorator = (decoratorName, resolver) => {
|
|
54
|
+
return createParamDecorator("req", decoratorName, undefined, undefined, true, resolver);
|
|
55
|
+
};
|
|
56
|
+
exports.createCustomRequestDecorator = createCustomRequestDecorator;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { HyperAppMetadata, Constructor } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* 🚀 HyperApp Decorator
|
|
4
|
+
* Purely injects metadata and a prepare method into the target class.
|
|
5
|
+
* No class wrapping or modification of the original constructor.
|
|
6
|
+
*/
|
|
7
|
+
export declare function HyperApp(options: HyperAppMetadata): (Target: Constructor) => void;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HyperApp = HyperApp;
|
|
4
|
+
const metadata_1 = require("./metadata");
|
|
5
|
+
/**
|
|
6
|
+
* 🚀 HyperApp Decorator
|
|
7
|
+
* Purely injects metadata and a prepare method into the target class.
|
|
8
|
+
* No class wrapping or modification of the original constructor.
|
|
9
|
+
*/
|
|
10
|
+
function HyperApp(options) {
|
|
11
|
+
return (Target) => {
|
|
12
|
+
metadata_1.HyperMeta.set(Target, undefined, Object.assign({ type: "app" }, options));
|
|
13
|
+
};
|
|
14
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HyperController = HyperController;
|
|
4
|
+
const metadata_1 = require("./metadata");
|
|
5
|
+
/**
|
|
6
|
+
* 🚀 HyperController Decorator
|
|
7
|
+
* Purely injects metadata into the target class.
|
|
8
|
+
*/
|
|
9
|
+
function HyperController(options) {
|
|
10
|
+
return (Target) => {
|
|
11
|
+
const isString = typeof options === "string";
|
|
12
|
+
const data = isString ? { path: options } : (options !== null && options !== void 0 ? options : {});
|
|
13
|
+
metadata_1.HyperMeta.set(Target, undefined, Object.assign({ type: "controller" }, data));
|
|
14
|
+
};
|
|
15
|
+
}
|