@carno.js/core 0.2.5 → 0.2.7
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/dist/commons/decorators/http.decorators.js +26 -7
- package/dist/container/InjectorService.js +2 -2
- package/dist/container/MethodInvoker.d.ts +3 -0
- package/dist/container/MethodInvoker.js +29 -2
- package/dist/route/ParamResolverFactory.d.ts +3 -1
- package/dist/route/ParamResolverFactory.js +26 -8
- package/package.json +2 -2
|
@@ -4,6 +4,11 @@ exports.Patch = exports.Delete = exports.Put = exports.Post = exports.Get = expo
|
|
|
4
4
|
exports.createParamDecorator = createParamDecorator;
|
|
5
5
|
const Metadata_1 = require("../../domain/Metadata");
|
|
6
6
|
const constants_1 = require("../../constants");
|
|
7
|
+
const PARAM_TYPE_KEY = "__carnoParamType";
|
|
8
|
+
const markParamType = (func, paramType) => {
|
|
9
|
+
func[PARAM_TYPE_KEY] = paramType;
|
|
10
|
+
return func;
|
|
11
|
+
};
|
|
7
12
|
const createMethodDecorator = (methodType) => {
|
|
8
13
|
return (path = "") => {
|
|
9
14
|
return (target, propertyKey) => {
|
|
@@ -27,16 +32,30 @@ const createMethodDecorator = (methodType) => {
|
|
|
27
32
|
function createParamDecorator(func) {
|
|
28
33
|
return (data) => (target, propertyKey, parameterIndex) => {
|
|
29
34
|
const existingArgs = Metadata_1.Metadata.get(constants_1.ROUTE_PARAM, target.constructor, propertyKey) || {};
|
|
30
|
-
existingArgs[parameterIndex] = {
|
|
35
|
+
existingArgs[parameterIndex] = {
|
|
36
|
+
fun: func,
|
|
37
|
+
param: data,
|
|
38
|
+
type: func[PARAM_TYPE_KEY],
|
|
39
|
+
};
|
|
31
40
|
Metadata_1.Metadata.set(constants_1.ROUTE_PARAM, existingArgs, target.constructor, propertyKey);
|
|
32
41
|
};
|
|
33
42
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
43
|
+
const bodyResolver = markParamType((context, data) => data ? context.body[data] : context.body || {}, "body");
|
|
44
|
+
const queryResolver = markParamType((context, data) => data ? context.query[data] : context.query || {}, "query");
|
|
45
|
+
const paramResolver = markParamType((context, data) => data ? context.param[data] : null, "param");
|
|
46
|
+
const reqResolver = markParamType((context) => context.req, "req");
|
|
47
|
+
const headersResolver = markParamType((context, data) => data
|
|
48
|
+
? context.headers.has(data)
|
|
49
|
+
? context.headers.get(data)
|
|
50
|
+
: undefined
|
|
51
|
+
: context.headers || {}, "headers");
|
|
52
|
+
const localsResolver = markParamType((context) => context.locals || {}, "locals");
|
|
53
|
+
exports.Body = createParamDecorator(bodyResolver);
|
|
54
|
+
exports.Query = createParamDecorator(queryResolver);
|
|
55
|
+
exports.Param = createParamDecorator(paramResolver);
|
|
56
|
+
exports.Req = createParamDecorator(reqResolver);
|
|
57
|
+
exports.Headers = createParamDecorator(headersResolver);
|
|
58
|
+
exports.Locals = createParamDecorator(localsResolver);
|
|
40
59
|
exports.Get = createMethodDecorator("GET");
|
|
41
60
|
exports.Post = createMethodDecorator("POST");
|
|
42
61
|
exports.Put = createMethodDecorator("PUT");
|
|
@@ -49,10 +49,10 @@ let InjectorService = InjectorService_1 = class InjectorService {
|
|
|
49
49
|
this.saveInjector();
|
|
50
50
|
this.routeResolver.resolveControllers();
|
|
51
51
|
this.cacheControllerScopes();
|
|
52
|
-
this.preInstantiateSingletonControllers();
|
|
53
52
|
this.cacheHooks();
|
|
54
|
-
this.compileRoutes();
|
|
55
53
|
await this.callHook(on_event_1.EventType.OnApplicationInit);
|
|
54
|
+
this.preInstantiateSingletonControllers();
|
|
55
|
+
this.compileRoutes();
|
|
56
56
|
}
|
|
57
57
|
initializeResolvers() {
|
|
58
58
|
this.routeResolver = new RouteResolver_1.RouteResolver(this.router, this.applicationConfig.globalMiddlewares);
|
|
@@ -12,6 +12,9 @@ export declare class MethodInvoker {
|
|
|
12
12
|
private cacheMethodInfo;
|
|
13
13
|
private setCachedMethod;
|
|
14
14
|
private resolveMethodServices;
|
|
15
|
+
private ensureBodyParsed;
|
|
16
|
+
private hasBodyParam;
|
|
17
|
+
private isBodyParam;
|
|
15
18
|
private resolveService;
|
|
16
19
|
private validateAndTransform;
|
|
17
20
|
}
|
|
@@ -15,6 +15,7 @@ class MethodInvoker {
|
|
|
15
15
|
}
|
|
16
16
|
async invoke(instance, methodName, locals, context, invokeCallback) {
|
|
17
17
|
const methodInfo = this.getMethodInfo(instance, methodName);
|
|
18
|
+
await this.ensureBodyParsed(methodInfo, context);
|
|
18
19
|
const services = this.resolveMethodServices(methodInfo, context, locals, invokeCallback);
|
|
19
20
|
return instance[methodName](...services);
|
|
20
21
|
}
|
|
@@ -29,7 +30,8 @@ class MethodInvoker {
|
|
|
29
30
|
cacheMethodInfo(instance, methodName) {
|
|
30
31
|
const args = (0, getMethodArgTypes_1.getMethodArgTypes)(instance, methodName);
|
|
31
32
|
const params = Metadata_1.Metadata.getParamDecoratorFunc(instance, methodName);
|
|
32
|
-
const
|
|
33
|
+
const needsBody = this.hasBodyParam(params);
|
|
34
|
+
const methodInfo = { args, params, needsBody };
|
|
33
35
|
this.setCachedMethod(instance, methodName, methodInfo);
|
|
34
36
|
return methodInfo;
|
|
35
37
|
}
|
|
@@ -47,6 +49,30 @@ class MethodInvoker {
|
|
|
47
49
|
}
|
|
48
50
|
return services;
|
|
49
51
|
}
|
|
52
|
+
async ensureBodyParsed(methodInfo, context) {
|
|
53
|
+
if (!methodInfo.needsBody) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (context.isBodyParsed()) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
await context.getBody();
|
|
60
|
+
}
|
|
61
|
+
hasBodyParam(params) {
|
|
62
|
+
if (!params) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
return Object.values(params).some((param) => this.isBodyParam(param));
|
|
66
|
+
}
|
|
67
|
+
isBodyParam(param) {
|
|
68
|
+
if (param?.type === "body") {
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
if (!param?.fun) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
return String(param.fun).includes("context.body");
|
|
75
|
+
}
|
|
50
76
|
resolveService(token, param, context, locals, invokeCallback) {
|
|
51
77
|
if (!param) {
|
|
52
78
|
return invokeCallback((0, getClassOrSymbol_1.getClassOrSymbol)(token), locals);
|
|
@@ -59,7 +85,8 @@ class MethodInvoker {
|
|
|
59
85
|
validateAndTransform(token, value) {
|
|
60
86
|
const obj = (0, class_transformer_1.plainToInstance)(token, value);
|
|
61
87
|
const errors = (0, class_validator_1.validateSync)(obj, this.applicationConfig.validation);
|
|
62
|
-
// todo: deve retornar apenas os erros e
|
|
88
|
+
// todo: deve retornar apenas os erros e no o objeto class-validator intei
|
|
89
|
+
// ro.
|
|
63
90
|
if (errors.length > 0) {
|
|
64
91
|
throw new HttpException_1.HttpException(errors, 400);
|
|
65
92
|
}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { type ValidatorOptions } from 'class-validator';
|
|
2
2
|
import type { Context } from '../domain/Context';
|
|
3
3
|
import type { ParamResolver, AsyncParamResolver } from './CompiledRoute';
|
|
4
|
+
export type ParamDecoratorType = 'body' | 'query' | 'param' | 'headers' | 'req' | 'locals';
|
|
4
5
|
export interface ParamDecoratorMeta {
|
|
5
6
|
fun: (context: Context, data?: any) => any;
|
|
6
7
|
param?: any;
|
|
8
|
+
type?: ParamDecoratorType;
|
|
7
9
|
}
|
|
8
10
|
export interface ParamInfo {
|
|
9
|
-
type:
|
|
11
|
+
type: ParamDecoratorType | 'di';
|
|
10
12
|
key?: string;
|
|
11
13
|
needsValidation: boolean;
|
|
12
14
|
token?: any;
|
|
@@ -12,28 +12,46 @@ function analyzeParamDecorator(decoratorMeta, token) {
|
|
|
12
12
|
if (!decoratorMeta) {
|
|
13
13
|
return { type: 'di', needsValidation: false, token };
|
|
14
14
|
}
|
|
15
|
-
const
|
|
15
|
+
const paramType = resolveParamType(decoratorMeta);
|
|
16
16
|
const key = decoratorMeta.param;
|
|
17
17
|
const needsValidation = typeof token === 'function' && (0, ValidationCache_1.isValidatable)(token);
|
|
18
|
+
if (paramType) {
|
|
19
|
+
return {
|
|
20
|
+
type: paramType,
|
|
21
|
+
key,
|
|
22
|
+
needsValidation,
|
|
23
|
+
token,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
return { type: 'di', needsValidation: false, token };
|
|
27
|
+
}
|
|
28
|
+
function resolveParamType(decoratorMeta) {
|
|
29
|
+
if (decoratorMeta.type) {
|
|
30
|
+
return decoratorMeta.type;
|
|
31
|
+
}
|
|
32
|
+
return inferTypeFromSource(decoratorMeta.fun);
|
|
33
|
+
}
|
|
34
|
+
function inferTypeFromSource(resolver) {
|
|
35
|
+
const funcStr = resolver.toString();
|
|
18
36
|
if (funcStr.includes('context.body')) {
|
|
19
|
-
return
|
|
37
|
+
return 'body';
|
|
20
38
|
}
|
|
21
39
|
if (funcStr.includes('context.query')) {
|
|
22
|
-
return
|
|
40
|
+
return 'query';
|
|
23
41
|
}
|
|
24
42
|
if (funcStr.includes('context.param')) {
|
|
25
|
-
return
|
|
43
|
+
return 'param';
|
|
26
44
|
}
|
|
27
45
|
if (funcStr.includes('context.headers')) {
|
|
28
|
-
return
|
|
46
|
+
return 'headers';
|
|
29
47
|
}
|
|
30
48
|
if (funcStr.includes('context.req')) {
|
|
31
|
-
return
|
|
49
|
+
return 'req';
|
|
32
50
|
}
|
|
33
51
|
if (funcStr.includes('context.locals')) {
|
|
34
|
-
return
|
|
52
|
+
return 'locals';
|
|
35
53
|
}
|
|
36
|
-
return
|
|
54
|
+
return null;
|
|
37
55
|
}
|
|
38
56
|
function createValidationResolver(extractFn, token, validationConfig) {
|
|
39
57
|
return (context) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@carno.js/core",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.7",
|
|
4
4
|
"description": "Carno.js is a framework for building web applications object oriented with TypeScript and Bun.sh",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bun",
|
|
@@ -51,5 +51,5 @@
|
|
|
51
51
|
"publishConfig": {
|
|
52
52
|
"access": "public"
|
|
53
53
|
},
|
|
54
|
-
"gitHead": "
|
|
54
|
+
"gitHead": "4abd763d3be38f53df2073a55bbc03e5deb3eeb6"
|
|
55
55
|
}
|