@trapi/metadata 0.1.4 → 0.1.5
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/package.json +11 -8
- package/src/cache/driver.ts +0 -97
- package/src/cache/index.ts +0 -10
- package/src/cache/type.ts +0 -43
- package/src/cache/utils.ts +0 -49
- package/src/config/index.ts +0 -8
- package/src/config/path.ts +0 -29
- package/src/decorator/functions.ts +0 -142
- package/src/decorator/index.ts +0 -13
- package/src/decorator/mapper/index.ts +0 -153
- package/src/decorator/mapper/maps/decorators-express.ts +0 -117
- package/src/decorator/mapper/maps/internal.ts +0 -95
- package/src/decorator/mapper/maps/typescript-rest.ts +0 -150
- package/src/decorator/mapper/utils.ts +0 -88
- package/src/decorator/representation/index.ts +0 -82
- package/src/decorator/representation/property/utils.ts +0 -146
- package/src/decorator/type.ts +0 -235
- package/src/decorator/utils/index.ts +0 -9
- package/src/decorator/utils/node.ts +0 -59
- package/src/decorator/utils/validator.ts +0 -104
- package/src/generator/controller.ts +0 -65
- package/src/generator/endpoint.ts +0 -212
- package/src/generator/index.ts +0 -219
- package/src/generator/method.ts +0 -198
- package/src/generator/parameter.ts +0 -392
- package/src/index.ts +0 -13
- package/src/resolver/error.ts +0 -38
- package/src/resolver/index.ts +0 -11
- package/src/resolver/type-node.ts +0 -1287
- package/src/resolver/type.ts +0 -257
- package/src/resolver/utils/index.ts +0 -9
- package/src/resolver/utils/initializer.ts +0 -84
- package/src/resolver/utils/validator.ts +0 -144
- package/src/type.ts +0 -185
- package/src/utils/generator.ts +0 -42
- package/src/utils/index.ts +0 -10
- package/src/utils/js-doc.ts +0 -125
- package/src/utils/validator.ts +0 -43
- package/test/data/library/@decorators-express/decorators.ts +0 -7
- package/test/data/library/self/api.ts +0 -37
- package/test/data/library/type.ts +0 -138
- package/test/data/library/typescript-rest/api.ts +0 -366
- package/test/data/library/typescript-rest/decorators/index.ts +0 -10
- package/test/data/library/typescript-rest/decorators/methods.ts +0 -34
- package/test/data/library/typescript-rest/decorators/parameters.ts +0 -62
- package/test/data/library/typescript-rest/decorators/services.ts +0 -47
- package/test/data/library/typescript-rest/return-types.ts +0 -94
- package/test/data/library/utils.ts +0 -7
- package/test/jest.config.js +0 -49
- package/test/unit/cache.spec.ts +0 -48
- package/test/unit/decorator/mapper/index.spec.ts +0 -83
- package/test/unit/decorator/representation/index.spec.ts +0 -102
- package/test/unit/decorator/utils/node.spec.ts +0 -47
- package/test/unit/library/typescript-rest.spec.ts +0 -342
- package/test/unit/resolver/type.spec.ts +0 -134
- package/test/unit/utils/generator.spec.ts +0 -41
- package/test/unit/utils/js-doc.spec.ts +0 -104
- package/tsconfig.build.json +0 -11
- package/tsconfig.json +0 -9
- package/writable/.gitignore +0 -3
package/src/decorator/type.ts
DELETED
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright (c) 2021.
|
|
3
|
-
* Author Peter Placzek (tada5hi)
|
|
4
|
-
* For the full copyright and license information,
|
|
5
|
-
* view the LICENSE file that was distributed with this source code.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
export namespace Decorator {
|
|
9
|
-
export interface Data {
|
|
10
|
-
text: string;
|
|
11
|
-
arguments: any[];
|
|
12
|
-
typeArguments: any[];
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
// -------------------------------------------
|
|
16
|
-
|
|
17
|
-
export interface Config {
|
|
18
|
-
/**
|
|
19
|
-
* Use a pre defined third party TypeRepresentationMap in full scope or
|
|
20
|
-
* only use a partial amount of defined type representations.
|
|
21
|
-
*
|
|
22
|
-
* Default: []
|
|
23
|
-
*/
|
|
24
|
-
library?: ConfigLibrary;
|
|
25
|
-
/**
|
|
26
|
-
* Use all internal defined type representations or only use a subset.
|
|
27
|
-
* Default: true
|
|
28
|
-
*/
|
|
29
|
-
internal?: TypeRepresentationConfig;
|
|
30
|
-
/**
|
|
31
|
-
* Set up self defined type representations.
|
|
32
|
-
*/
|
|
33
|
-
map?: Partial<TypeRepresentationMap>;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// -------------------------------------------
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* These are the current by default supported third party libraries.
|
|
40
|
-
*/
|
|
41
|
-
export type Library = 'typescript-rest' | 'decorators-express';
|
|
42
|
-
export type ConfigLibrary = Library | Library[] | Record<string, TypeRepresentationConfig>;
|
|
43
|
-
|
|
44
|
-
// -------------------------------------------
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Activate/Deactivate specific type representations of a TypeRepresentationMap.
|
|
48
|
-
*/
|
|
49
|
-
export type TypeRepresentationConfig = boolean | Type | Type[] | { [K in Type]?: boolean };
|
|
50
|
-
|
|
51
|
-
// -------------------------------------------
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* This type maps a decorator type to its representation config.
|
|
55
|
-
*/
|
|
56
|
-
export type TypeRepresentationMap = {
|
|
57
|
-
[T in keyof TypePropertyMap]: Representation<T> | Array<Representation<T>>;
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* The id property is the name/text of the defined decorator.
|
|
62
|
-
*/
|
|
63
|
-
export interface Representation<T extends keyof TypePropertyMap> {
|
|
64
|
-
id: string;
|
|
65
|
-
properties?: RepresentationProperties<TypePropertyMap[T]>;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export type RepresentationProperties<P> = {
|
|
69
|
-
[K in keyof P]: Property
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* A decorator type is an identifier which is associated
|
|
75
|
-
* to specific decorator names.
|
|
76
|
-
*/
|
|
77
|
-
|
|
78
|
-
export interface TypePropertyMap {
|
|
79
|
-
// Class Type
|
|
80
|
-
SWAGGER_TAGS: {
|
|
81
|
-
DEFAULT: string[]
|
|
82
|
-
};
|
|
83
|
-
CLASS_PATH: {
|
|
84
|
-
DEFAULT: string
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
// Method and Class
|
|
88
|
-
REQUEST_ACCEPT: undefined;
|
|
89
|
-
RESPONSE_EXAMPLE: {
|
|
90
|
-
TYPE: unknown,
|
|
91
|
-
PAYLOAD: unknown | unknown[]
|
|
92
|
-
};
|
|
93
|
-
RESPONSE_DESCRIPTION: {
|
|
94
|
-
TYPE: unknown;
|
|
95
|
-
STATUS_CODE: number | string;
|
|
96
|
-
DESCRIPTION: string;
|
|
97
|
-
PAYLOAD: unknown | unknown[];
|
|
98
|
-
};
|
|
99
|
-
REQUEST_CONSUMES: {
|
|
100
|
-
DEFAULT: string[]
|
|
101
|
-
};
|
|
102
|
-
RESPONSE_PRODUCES: {
|
|
103
|
-
DEFAULT: string[]
|
|
104
|
-
};
|
|
105
|
-
HIDDEN: {};
|
|
106
|
-
EXTENSION: {
|
|
107
|
-
KEY: string,
|
|
108
|
-
VALUE: unknown | unknown[]
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
// Method
|
|
112
|
-
METHOD_PATH: {
|
|
113
|
-
DEFAULT: string
|
|
114
|
-
};
|
|
115
|
-
DEPRECATED: undefined;
|
|
116
|
-
|
|
117
|
-
// METHOD HTTP
|
|
118
|
-
ALL: {
|
|
119
|
-
DEFAULT?: string
|
|
120
|
-
};
|
|
121
|
-
GET: {
|
|
122
|
-
DEFAULT?: string
|
|
123
|
-
};
|
|
124
|
-
POST: {
|
|
125
|
-
DEFAULT?: string
|
|
126
|
-
};
|
|
127
|
-
PUT: {
|
|
128
|
-
DEFAULT?: string
|
|
129
|
-
};
|
|
130
|
-
DELETE: {
|
|
131
|
-
DEFAULT?: string
|
|
132
|
-
};
|
|
133
|
-
PATCH: {
|
|
134
|
-
DEFAULT?: string
|
|
135
|
-
};
|
|
136
|
-
OPTIONS: {
|
|
137
|
-
DEFAULT?: string
|
|
138
|
-
};
|
|
139
|
-
HEAD: {
|
|
140
|
-
DEFAULT?: string
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
// Parameter
|
|
144
|
-
IS_INT: undefined;
|
|
145
|
-
IS_LONG: undefined;
|
|
146
|
-
IS_FlOAT: undefined;
|
|
147
|
-
IS_DOUBLE: undefined;
|
|
148
|
-
|
|
149
|
-
// Parameter Server
|
|
150
|
-
SERVER_CONTEXT: {};
|
|
151
|
-
SERVER_PARAMS: {
|
|
152
|
-
// typescript-rest
|
|
153
|
-
DEFAULT?: string
|
|
154
|
-
};
|
|
155
|
-
SERVER_QUERY: {
|
|
156
|
-
// typescript-rest
|
|
157
|
-
DEFAULT?: string,
|
|
158
|
-
OPTIONS?: Record<string, any>
|
|
159
|
-
} | undefined;
|
|
160
|
-
SERVER_FORM: {
|
|
161
|
-
// typescript-rest
|
|
162
|
-
DEFAULT?: string
|
|
163
|
-
} | undefined;
|
|
164
|
-
SERVER_BODY: {
|
|
165
|
-
// typescript-rest
|
|
166
|
-
DEFAULT?: string
|
|
167
|
-
};
|
|
168
|
-
SERVER_HEADERS: {
|
|
169
|
-
// typescript-rest
|
|
170
|
-
DEFAULT?: string
|
|
171
|
-
};
|
|
172
|
-
SERVER_COOKIES: {
|
|
173
|
-
// typescript-rest
|
|
174
|
-
DEFAULT?: string
|
|
175
|
-
};
|
|
176
|
-
SERVER_PATH_PARAMS: {
|
|
177
|
-
// typescript-rest
|
|
178
|
-
DEFAULT?: string
|
|
179
|
-
};
|
|
180
|
-
SERVER_FILE_PARAM: {
|
|
181
|
-
// typescript-rest
|
|
182
|
-
DEFAULT?: string
|
|
183
|
-
};
|
|
184
|
-
SERVER_FILES_PARAM: {
|
|
185
|
-
// typescript-rest
|
|
186
|
-
DEFAULT?: string
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
export type Type = keyof TypePropertyMap;
|
|
191
|
-
|
|
192
|
-
export type MethodHttpVerbType = Extract<Type, 'ALL' | 'GET' | 'POST' | 'PUT' | 'DELETE' |
|
|
193
|
-
'PATCH' | 'OPTIONS' | 'HEAD'>;
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
export type ParameterServerType = Extract<Type, 'SERVER_CONTEXT' | 'SERVER_PARAMS' | 'SERVER_QUERY' | 'SERVER_FORM' |
|
|
197
|
-
'SERVER_BODY' | 'SERVER_HEADERS' | 'SERVER_COOKIES' | 'SERVER_PATH_PARAMS' |
|
|
198
|
-
'SERVER_FILE_PARAM' | 'SERVER_FILES_PARAM'>;
|
|
199
|
-
|
|
200
|
-
// -------------------------------------------
|
|
201
|
-
|
|
202
|
-
export type PropertyStrategy = 'merge' | 'none' | ((...items: unknown[] | unknown[][]) => unknown | unknown[]);
|
|
203
|
-
|
|
204
|
-
export interface Property {
|
|
205
|
-
/**
|
|
206
|
-
* Default: 'element'
|
|
207
|
-
*/
|
|
208
|
-
type?: 'element' | 'array';
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* Default: false
|
|
212
|
-
*/
|
|
213
|
-
isType?: boolean;
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* Default: 'argument'
|
|
217
|
-
*/
|
|
218
|
-
srcArgumentType?: 'argument' | 'typeArgument';
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Default: 0
|
|
222
|
-
*/
|
|
223
|
-
srcPosition?: number;
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* Default: undefined
|
|
227
|
-
*/
|
|
228
|
-
srcAmount?: number;
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* Default: 'none'
|
|
232
|
-
*/
|
|
233
|
-
srcStrategy?: PropertyStrategy
|
|
234
|
-
}
|
|
235
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright (c) 2021.
|
|
3
|
-
* Author Peter Placzek (tada5hi)
|
|
4
|
-
* For the full copyright and license information,
|
|
5
|
-
* view the LICENSE file that was distributed with this source code.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import {isCallExpression, isNumericLiteral, isStringLiteral, Node} from 'typescript';
|
|
9
|
-
import {Decorator} from "../type";
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Get Decorators for a specific node.
|
|
13
|
-
*
|
|
14
|
-
* @param node
|
|
15
|
-
* @param isMatching
|
|
16
|
-
*/
|
|
17
|
-
export function getNodeDecorators(
|
|
18
|
-
node: Node,
|
|
19
|
-
isMatching?: (data: Decorator.Data) => boolean
|
|
20
|
-
): Decorator.Data[] {
|
|
21
|
-
const decorators = node.decorators;
|
|
22
|
-
if (!decorators || !decorators.length) {
|
|
23
|
-
return [];
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const items = decorators
|
|
27
|
-
.map(d => {
|
|
28
|
-
const result: any = {
|
|
29
|
-
arguments: [],
|
|
30
|
-
typeArguments: []
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
let x: any = d.expression;
|
|
34
|
-
|
|
35
|
-
if (isCallExpression(x)) {
|
|
36
|
-
if (x.arguments) {
|
|
37
|
-
result.arguments = x.arguments.map((argument: any) => {
|
|
38
|
-
if (isStringLiteral(argument) || isNumericLiteral(argument)) {
|
|
39
|
-
return argument.text;
|
|
40
|
-
} else {
|
|
41
|
-
return argument;
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (x.typeArguments) {
|
|
47
|
-
result.typeArguments = x.typeArguments;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
x = x.expression;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
result.text = x.text || x.name.text;
|
|
54
|
-
|
|
55
|
-
return result as Decorator.Data;
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
return typeof isMatching === 'undefined' ? items : items.filter(isMatching);
|
|
59
|
-
}
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright (c) 2021.
|
|
3
|
-
* Author Peter Placzek (tada5hi)
|
|
4
|
-
* For the full copyright and license information,
|
|
5
|
-
* view the LICENSE file that was distributed with this source code.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import {array, boolean, lazy, mixed, number, object, SchemaOf, string} from "yup";
|
|
9
|
-
import {mapYupRuleForDictionary} from "@trapi/metadata-utils";
|
|
10
|
-
import {Decorator} from "../type";
|
|
11
|
-
|
|
12
|
-
let validatorInstance : undefined | SchemaOf<Decorator.Config>;
|
|
13
|
-
|
|
14
|
-
export function useDecoratorConfigValidator() : SchemaOf<Decorator.Config> {
|
|
15
|
-
if(typeof validatorInstance !== 'undefined') {
|
|
16
|
-
return validatorInstance;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const configMappingOptionValidator : SchemaOf<Decorator.TypeRepresentationConfig> = lazy(value => {
|
|
20
|
-
if(typeof value === 'boolean') {
|
|
21
|
-
return boolean();
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
if(typeof value === 'string') {
|
|
25
|
-
return string();
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if(Array.isArray(value)) {
|
|
29
|
-
return array().of(string());
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if(Object.prototype.toString.call(value) === '[object Object]') {
|
|
33
|
-
// todo: setup type key check :)
|
|
34
|
-
return object(mapYupRuleForDictionary(value, boolean())).optional().default({});
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return mixed().optional().default(undefined);
|
|
38
|
-
}) as unknown as SchemaOf<Decorator.TypeRepresentationConfig>;
|
|
39
|
-
|
|
40
|
-
const useLibraryValidator : SchemaOf<Decorator.ConfigLibrary> = lazy(value => {
|
|
41
|
-
if(typeof value === 'string') {
|
|
42
|
-
return string();
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if(Array.isArray(value)) {
|
|
46
|
-
return array().of(string());
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
if(Object.prototype.toString.call(value) === '[object Object]') {
|
|
50
|
-
// todo: setup library key check :)
|
|
51
|
-
return object(mapYupRuleForDictionary(value, configMappingOptionValidator));
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return mixed().optional().default(undefined);
|
|
55
|
-
}) as unknown as SchemaOf<Decorator.ConfigLibrary>;
|
|
56
|
-
|
|
57
|
-
const representationPropertyValidator : SchemaOf<Decorator.Property> = object({
|
|
58
|
-
type: mixed().oneOf(['element', 'array'] as Array<Decorator.Property['type']>),
|
|
59
|
-
isType: boolean().optional().default(undefined),
|
|
60
|
-
srcArgumentType: mixed().oneOf(['argument', 'typeArgument'] as Array<Decorator.Property['srcArgumentType']>),
|
|
61
|
-
srcPosition: number().min(0).optional().default(0),
|
|
62
|
-
srcAmount: number().optional().default(undefined),
|
|
63
|
-
// todo: check if 'merge', 'none' or function
|
|
64
|
-
srcStrategy: mixed().optional().default(undefined),
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
const representationValidator : SchemaOf<Decorator.Representation<any>> = object({
|
|
68
|
-
id: string().required(),
|
|
69
|
-
properties: lazy(value => {
|
|
70
|
-
if(Object.prototype.toString.call(value) === '[object Object]') {
|
|
71
|
-
return object(mapYupRuleForDictionary(value, representationPropertyValidator)).optional().default({});
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
return mixed().optional().default(undefined);
|
|
75
|
-
})
|
|
76
|
-
}) as unknown as SchemaOf<Decorator.Representation<any>>;
|
|
77
|
-
|
|
78
|
-
const overrideValidator : SchemaOf<Decorator.TypeRepresentationMap> = lazy(value => {
|
|
79
|
-
if(Object.prototype.toString.call(value) === '[object Object]') {
|
|
80
|
-
return object(mapYupRuleForDictionary(value, lazy(val => {
|
|
81
|
-
if (Array.isArray(val)) {
|
|
82
|
-
return array().of(representationValidator);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
return representationValidator;
|
|
86
|
-
}))
|
|
87
|
-
);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
return mixed().optional().default(undefined);
|
|
91
|
-
}) as unknown as SchemaOf<Decorator.TypeRepresentationMap>;
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
validatorInstance = object({
|
|
95
|
-
library: useLibraryValidator,
|
|
96
|
-
internal: configMappingOptionValidator,
|
|
97
|
-
map: overrideValidator
|
|
98
|
-
}).optional().default({
|
|
99
|
-
library: ['typescript-rest', '@decorators/express'],
|
|
100
|
-
internal: true
|
|
101
|
-
} as Decorator.Config);
|
|
102
|
-
|
|
103
|
-
return validatorInstance;
|
|
104
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright (c) 2021.
|
|
3
|
-
* Author Peter Placzek (tada5hi)
|
|
4
|
-
* For the full copyright and license information,
|
|
5
|
-
* view the LICENSE file that was distributed with this source code.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import {ClassDeclaration, MethodDeclaration, SyntaxKind} from 'typescript';
|
|
9
|
-
import {EndpointGenerator} from './endpoint';
|
|
10
|
-
import {MetadataGenerator} from './index';
|
|
11
|
-
import {MethodGenerator} from './method';
|
|
12
|
-
import {Controller, Method} from "../type";
|
|
13
|
-
|
|
14
|
-
export class ControllerGenerator extends EndpointGenerator<ClassDeclaration> {
|
|
15
|
-
private genMethods: Set<string> = new Set<string>();
|
|
16
|
-
|
|
17
|
-
// --------------------------------------------------------------------
|
|
18
|
-
|
|
19
|
-
constructor(node: ClassDeclaration, current: MetadataGenerator) {
|
|
20
|
-
super(node, current);
|
|
21
|
-
|
|
22
|
-
this.generatePath('CLASS_PATH');
|
|
23
|
-
}
|
|
24
|
-
public isValid() {
|
|
25
|
-
return !!this.path || this.path === '';
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
public generate(): Controller {
|
|
29
|
-
if (!this.node.parent) { throw new Error('Controller node doesn\'t have a valid parent source file.'); }
|
|
30
|
-
if (!this.node.name) { throw new Error('Controller node doesn\'t have a valid name.'); }
|
|
31
|
-
|
|
32
|
-
const sourceFile = this.node.parent.getSourceFile();
|
|
33
|
-
|
|
34
|
-
return {
|
|
35
|
-
consumes: this.getConsumes(),
|
|
36
|
-
location: sourceFile.fileName,
|
|
37
|
-
methods: this.buildMethods(),
|
|
38
|
-
name: this.getCurrentLocation(),
|
|
39
|
-
path: this.path || '',
|
|
40
|
-
produces: this.getProduces(),
|
|
41
|
-
responses: this.getResponses(),
|
|
42
|
-
security: this.getSecurity(),
|
|
43
|
-
tags: this.getTags(),
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
protected getCurrentLocation(): string {
|
|
48
|
-
return (this.node as ClassDeclaration).name.text;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
private buildMethods() : Method[] {
|
|
52
|
-
return this.node.members
|
|
53
|
-
.filter((method: { kind: unknown; }) => (method.kind === SyntaxKind.MethodDeclaration))
|
|
54
|
-
.filter((method: MethodDeclaration) => !this.isHidden(method))
|
|
55
|
-
.map((method: MethodDeclaration) => new MethodGenerator(method, this.current,this.path || ''))
|
|
56
|
-
.filter((generator: MethodGenerator) => {
|
|
57
|
-
if (generator.isValid() && !this.genMethods.has(generator.getMethodName())) {
|
|
58
|
-
this.genMethods.add(generator.getMethodName());
|
|
59
|
-
return true;
|
|
60
|
-
}
|
|
61
|
-
return false;
|
|
62
|
-
})
|
|
63
|
-
.map((generator: MethodGenerator) => generator.generate());
|
|
64
|
-
}
|
|
65
|
-
}
|
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright (c) 2021.
|
|
3
|
-
* Author Peter Placzek (tada5hi)
|
|
4
|
-
* For the full copyright and license information,
|
|
5
|
-
* view the LICENSE file that was distributed with this source code.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
'use strict';
|
|
9
|
-
|
|
10
|
-
import {ArrayLiteralExpression, isArrayLiteralExpression, Node, TypeNode} from 'typescript';
|
|
11
|
-
import {normalizePath} from "@trapi/metadata-utils";
|
|
12
|
-
|
|
13
|
-
import {Decorator} from "../decorator";
|
|
14
|
-
import {MetadataGenerator} from './index';
|
|
15
|
-
import {getInitializerValue, TypeNodeResolver} from '../resolver';
|
|
16
|
-
import {isExistJSDocTag} from "../utils";
|
|
17
|
-
import {Response} from "../type";
|
|
18
|
-
import {getNodeDecorators} from "../decorator";
|
|
19
|
-
|
|
20
|
-
export abstract class EndpointGenerator<T extends Node> {
|
|
21
|
-
protected path: string | undefined;
|
|
22
|
-
protected node: T;
|
|
23
|
-
|
|
24
|
-
// -------------------------------------------
|
|
25
|
-
|
|
26
|
-
protected constructor(node: T, protected current: MetadataGenerator) {
|
|
27
|
-
this.node = node;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// --------------------------------------------------------------------
|
|
31
|
-
|
|
32
|
-
protected generatePath(
|
|
33
|
-
key: Extract<Decorator.Type, 'CLASS_PATH' | 'METHOD_PATH'>
|
|
34
|
-
) : void {
|
|
35
|
-
const values : string[] = [];
|
|
36
|
-
|
|
37
|
-
const representation = this.current.decoratorMapper.match(key, this.node);
|
|
38
|
-
if(typeof representation !== 'undefined') {
|
|
39
|
-
const value = representation.getPropertyValue('DEFAULT');
|
|
40
|
-
if(typeof value !== 'undefined') {
|
|
41
|
-
values.push(value);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
this.path = normalizePath(values.join('/'));
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// --------------------------------------------------------------------
|
|
49
|
-
|
|
50
|
-
protected getDecoratorValues(decoratorName: string, acceptMultiple: boolean = false) : any[] {
|
|
51
|
-
const decorators = getNodeDecorators(this.node, decorator => decorator.text === decoratorName);
|
|
52
|
-
|
|
53
|
-
if (!decorators || !decorators.length) { return []; }
|
|
54
|
-
|
|
55
|
-
if (!acceptMultiple && decorators.length > 1) {
|
|
56
|
-
throw new Error(`Only one ${decoratorName} decorator allowed in ${this.getCurrentLocation()}.`);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
let result: any[];
|
|
60
|
-
|
|
61
|
-
if (acceptMultiple) {
|
|
62
|
-
result = decorators.map(d => d.arguments);
|
|
63
|
-
} else {
|
|
64
|
-
const d = decorators[0];
|
|
65
|
-
result = d.arguments;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return result;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// -------------------------------------------
|
|
72
|
-
|
|
73
|
-
protected getSecurity() {
|
|
74
|
-
const securities = this.getDecoratorValues('Security', true);
|
|
75
|
-
if (!securities || !securities.length) { return undefined; }
|
|
76
|
-
|
|
77
|
-
return securities.map(security => {
|
|
78
|
-
const rolesArray : string[] = security[0] ? this.handleRolesArray(security[0]) : [];
|
|
79
|
-
|
|
80
|
-
return {
|
|
81
|
-
name: security[1] ? security[1] : 'default',
|
|
82
|
-
scopes: rolesArray
|
|
83
|
-
};
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
protected handleRolesArray(argument: ArrayLiteralExpression): string[] {
|
|
88
|
-
if (isArrayLiteralExpression(argument)) {
|
|
89
|
-
return argument.elements.map(value => value.getText())
|
|
90
|
-
.map(val => (val && val.startsWith('\'') && val.endsWith('\'')) ? val.slice(1, -1) : val);
|
|
91
|
-
} else {
|
|
92
|
-
return argument;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// -------------------------------------------
|
|
97
|
-
|
|
98
|
-
protected getExamplesValue(argument: any) : unknown[] {
|
|
99
|
-
let example: any = {};
|
|
100
|
-
|
|
101
|
-
if(typeof argument === 'undefined') {
|
|
102
|
-
return example;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (argument.properties) {
|
|
106
|
-
argument.properties.forEach((p: any) => {
|
|
107
|
-
example[p.name.text] = getInitializerValue(p.initializer, this.current.typeChecker);
|
|
108
|
-
});
|
|
109
|
-
} else {
|
|
110
|
-
example = getInitializerValue(argument, this.current.typeChecker);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
return example;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// -------------------------------------------
|
|
117
|
-
|
|
118
|
-
protected getResponses(): Response[] {
|
|
119
|
-
const representation = this.current.decoratorMapper.match('RESPONSE_DESCRIPTION', this.node);
|
|
120
|
-
if(typeof representation === 'undefined') {
|
|
121
|
-
return [];
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const responses : Response[] = [];
|
|
125
|
-
|
|
126
|
-
for(let i=0; i<representation.decorators.length; i++) {
|
|
127
|
-
const description = representation.getPropertyValue('DESCRIPTION', i) || 'Ok';
|
|
128
|
-
const status = representation. getPropertyValue('STATUS_CODE', i) || '200';
|
|
129
|
-
let examples : unknown | unknown[] = representation. getPropertyValue('PAYLOAD', i);
|
|
130
|
-
|
|
131
|
-
const type = representation.getPropertyValue('TYPE');
|
|
132
|
-
|
|
133
|
-
const response : Response = {
|
|
134
|
-
description: description,
|
|
135
|
-
examples: examples,
|
|
136
|
-
schema: type ? new TypeNodeResolver(type as TypeNode, this.current).resolve() : undefined,
|
|
137
|
-
status: status as string,
|
|
138
|
-
name: status as string
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
responses.push(response);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
return responses;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// -------------------------------------------
|
|
148
|
-
|
|
149
|
-
public getProduces() : string[] {
|
|
150
|
-
const representation = this.current.decoratorMapper.match('RESPONSE_PRODUCES', this.node);
|
|
151
|
-
if(typeof representation === 'undefined') {
|
|
152
|
-
return [];
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
const value : string[] = representation.getPropertyValue('DEFAULT');
|
|
156
|
-
if(typeof value === 'undefined') {
|
|
157
|
-
return [];
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
return Array.isArray(value) ? value : [value];
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
public getConsumes() : string[] {
|
|
164
|
-
const representation = this.current.decoratorMapper.match('REQUEST_CONSUMES', this.node);
|
|
165
|
-
if(typeof representation === 'undefined') {
|
|
166
|
-
return [];
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
let value : string[] = representation.getPropertyValue('DEFAULT');
|
|
170
|
-
if(typeof value === 'undefined') {
|
|
171
|
-
return [];
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
value = Array.isArray(value) ? value : [value];
|
|
175
|
-
|
|
176
|
-
return value;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
public getTags() : string[] {
|
|
180
|
-
const representation = this.current.decoratorMapper.match('SWAGGER_TAGS', this.node);
|
|
181
|
-
if(typeof representation === 'undefined') {
|
|
182
|
-
return [];
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
let value : string[] = representation.getPropertyValue('DEFAULT');
|
|
186
|
-
if(typeof value === 'undefined') {
|
|
187
|
-
return [];
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
value = Array.isArray(value) ? value : [value];
|
|
191
|
-
|
|
192
|
-
return value;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// -------------------------------------------
|
|
196
|
-
|
|
197
|
-
protected abstract getCurrentLocation(): string;
|
|
198
|
-
|
|
199
|
-
// -------------------------------------------
|
|
200
|
-
|
|
201
|
-
public isHidden(node: Node) : boolean {
|
|
202
|
-
return typeof this.current.decoratorMapper.match('HIDDEN', node) !== 'undefined';
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
public isDeprecated(node: Node) : boolean {
|
|
206
|
-
if (isExistJSDocTag(node, tag => tag.tagName.text === 'deprecated')) {
|
|
207
|
-
return true;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
return typeof this.current.decoratorMapper.match('DEPRECATED', node) !== 'undefined';
|
|
211
|
-
}
|
|
212
|
-
}
|