@nestia/core 12.0.0 → 12.1.0

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.
Files changed (60) hide show
  1. package/lib/adaptors/McpAdaptor.js +21 -18
  2. package/lib/adaptors/McpAdaptor.js.map +1 -1
  3. package/lib/decorators/EncryptedBody.js +2 -7
  4. package/lib/decorators/EncryptedBody.js.map +1 -1
  5. package/lib/decorators/EncryptedRoute.js +1 -1
  6. package/lib/decorators/EncryptedRoute.js.map +1 -1
  7. package/lib/decorators/McpRoute.js +1 -1
  8. package/lib/decorators/McpRoute.js.map +1 -1
  9. package/lib/decorators/NoTransformConfigurationError.js +2 -2
  10. package/lib/decorators/PlainBody.js +2 -7
  11. package/lib/decorators/PlainBody.js.map +1 -1
  12. package/lib/decorators/SwaggerCustomizer.js +2 -2
  13. package/lib/decorators/SwaggerCustomizer.js.map +1 -1
  14. package/lib/decorators/SwaggerExample.d.ts +37 -40
  15. package/lib/decorators/SwaggerExample.js +24 -26
  16. package/lib/decorators/SwaggerExample.js.map +1 -1
  17. package/lib/decorators/TypedBody.js +3 -7
  18. package/lib/decorators/TypedBody.js.map +1 -1
  19. package/lib/decorators/TypedException.d.ts +1 -1
  20. package/lib/decorators/TypedFormData.js +2 -7
  21. package/lib/decorators/TypedFormData.js.map +1 -1
  22. package/lib/decorators/TypedQuery.js +2 -9
  23. package/lib/decorators/TypedQuery.js.map +1 -1
  24. package/lib/decorators/WebSocketRoute.js +1 -1
  25. package/lib/decorators/WebSocketRoute.js.map +1 -1
  26. package/lib/decorators/internal/get_path_and_querify.js +1 -1
  27. package/lib/decorators/internal/get_path_and_querify.js.map +1 -1
  28. package/lib/decorators/internal/is_media_type.d.ts +1 -0
  29. package/lib/decorators/internal/is_media_type.js +11 -0
  30. package/lib/decorators/internal/is_media_type.js.map +1 -0
  31. package/lib/decorators/internal/validate_request_query.js.map +1 -1
  32. package/native/plugin/plan.go +17 -0
  33. package/native/transform/build.go +39 -80
  34. package/native/transform/contributor.go +4 -64
  35. package/native/transform/core_transform.go +42 -705
  36. package/native/transform/node_transform.go +3 -5
  37. package/native/transform/printer.go +0 -217
  38. package/native/transform/transform.go +2 -91
  39. package/native/transform/typia_fast.go +0 -320
  40. package/package.json +8 -8
  41. package/src/adaptors/McpAdaptor.ts +29 -21
  42. package/src/decorators/EncryptedBody.ts +2 -9
  43. package/src/decorators/EncryptedRoute.ts +1 -1
  44. package/src/decorators/McpRoute.ts +6 -5
  45. package/src/decorators/NoTransformConfigurationError.ts +2 -2
  46. package/src/decorators/PlainBody.ts +2 -9
  47. package/src/decorators/SwaggerCustomizer.ts +8 -2
  48. package/src/decorators/SwaggerExample.ts +43 -45
  49. package/src/decorators/TypedBody.ts +5 -9
  50. package/src/decorators/TypedException.ts +1 -1
  51. package/src/decorators/TypedFormData.ts +7 -9
  52. package/src/decorators/TypedQuery.ts +7 -12
  53. package/src/decorators/WebSocketRoute.ts +1 -1
  54. package/src/decorators/internal/get_path_and_querify.ts +1 -1
  55. package/src/decorators/internal/is_media_type.ts +10 -0
  56. package/src/decorators/internal/validate_request_query.ts +2 -1
  57. package/native/transform/cleanup.go +0 -408
  58. package/native/transform/exports.go +0 -13
  59. package/native/transform/rewrite.go +0 -668
  60. package/native/transform/typia_replacement.go +0 -24
@@ -1,11 +1,7 @@
1
1
  package transform
2
2
 
3
3
  import (
4
- "path/filepath"
5
- "strings"
6
-
7
4
  shimast "github.com/microsoft/typescript-go/shim/ast"
8
- shimchecker "github.com/microsoft/typescript-go/shim/checker"
9
5
  shimprinter "github.com/microsoft/typescript-go/shim/printer"
10
6
  shimscanner "github.com/microsoft/typescript-go/shim/scanner"
11
7
  "github.com/samchon/ttsc/packages/ttsc/driver"
@@ -57,319 +53,3 @@ func nestiaTypiaDiagnosticFrom(diag *nativecontext.ITypiaDiagnostic) Diagnostic
57
53
  }
58
54
  return out
59
55
  }
60
-
61
- type nestiaTypiaImportRoot struct {
62
- module string
63
- }
64
-
65
- func collectNestiaTypiaCallSites(files []*shimast.SourceFile, checker *shimchecker.Checker) []typiaadapter.CallSite {
66
- sites := []typiaadapter.CallSite{}
67
- for _, file := range files {
68
- if file == nil || file.IsDeclarationFile {
69
- continue
70
- }
71
- roots, fallback := nestiaTypiaImportRoots(file)
72
- if len(roots) == 0 {
73
- if fallback {
74
- sites = append(sites, typiaadapter.CollectCallSites([]*shimast.SourceFile{file}, checker)...)
75
- }
76
- continue
77
- }
78
- file.ForEachChild(func(node *shimast.Node) bool {
79
- visitNestiaTypiaCallSite(file, checker, roots, node, &sites)
80
- return false
81
- })
82
- }
83
- return sites
84
- }
85
-
86
- func visitNestiaTypiaCallSite(
87
- file *shimast.SourceFile,
88
- checker *shimchecker.Checker,
89
- roots map[string]nestiaTypiaImportRoot,
90
- node *shimast.Node,
91
- sites *[]typiaadapter.CallSite,
92
- ) {
93
- if node == nil {
94
- return
95
- }
96
- if node.Kind == shimast.KindCallExpression {
97
- call := node.AsCallExpression()
98
- if call != nil && nestiaTypiaCallLooksPossible(call, roots) {
99
- if site, ok := tryNestiaTypiaCallSite(file, checker, node); ok {
100
- *sites = append(*sites, site)
101
- }
102
- }
103
- }
104
- node.ForEachChild(func(child *shimast.Node) bool {
105
- visitNestiaTypiaCallSite(file, checker, roots, child, sites)
106
- return false
107
- })
108
- }
109
-
110
- func nestiaTypiaImportRoots(file *shimast.SourceFile) (map[string]nestiaTypiaImportRoot, bool) {
111
- roots := map[string]nestiaTypiaImportRoot{}
112
- fallback := false
113
- if file == nil || file.Statements == nil {
114
- return roots, fallback
115
- }
116
- for _, stmt := range file.Statements.Nodes {
117
- if stmt == nil || stmt.Kind != shimast.KindImportDeclaration {
118
- continue
119
- }
120
- decl := stmt.AsImportDeclaration()
121
- if decl == nil || decl.ImportClause == nil || decl.ModuleSpecifier == nil || decl.ModuleSpecifier.Kind != shimast.KindStringLiteral {
122
- continue
123
- }
124
- moduleText := decl.ModuleSpecifier.Text()
125
- module, ok := nestiaTypiaImportModule(moduleText)
126
- if ok == false {
127
- continue
128
- }
129
- clause := decl.ImportClause.AsImportClause()
130
- if clause == nil || clause.PhaseModifier == shimast.KindTypeKeyword {
131
- continue
132
- }
133
- if name := clause.Name(); name != nil {
134
- roots[name.Text()] = nestiaTypiaImportRoot{module: module}
135
- }
136
- if clause.NamedBindings == nil {
137
- continue
138
- }
139
- if clause.NamedBindings.Kind == shimast.KindNamespaceImport {
140
- if name := clause.NamedBindings.Name(); name != nil {
141
- roots[name.Text()] = nestiaTypiaImportRoot{module: module}
142
- }
143
- continue
144
- }
145
- if clause.NamedBindings.Kind != shimast.KindNamedImports {
146
- continue
147
- }
148
- named := clause.NamedBindings.AsNamedImports()
149
- if named == nil || named.Elements == nil {
150
- continue
151
- }
152
- for _, elem := range named.Elements.Nodes {
153
- if elem == nil {
154
- continue
155
- }
156
- spec := elem.AsImportSpecifier()
157
- if spec == nil || spec.IsTypeOnly {
158
- continue
159
- }
160
- name := spec.Name()
161
- if name == nil {
162
- continue
163
- }
164
- imported := name.Text()
165
- if spec.PropertyName != nil {
166
- imported = spec.PropertyName.Text()
167
- }
168
- if module == "" {
169
- if nestiaTypiaKnownModule(imported) == false {
170
- continue
171
- }
172
- roots[name.Text()] = nestiaTypiaImportRoot{module: imported}
173
- } else {
174
- roots[name.Text()] = nestiaTypiaImportRoot{module: module}
175
- }
176
- }
177
- }
178
- return roots, fallback
179
- }
180
-
181
- func nestiaTypiaImportModule(specifier string) (string, bool) {
182
- switch specifier {
183
- case "typia":
184
- return "", true
185
- }
186
- for _, prefix := range []string{"typia/lib/", "typia/src/"} {
187
- if strings.HasPrefix(specifier, prefix) {
188
- name := strings.TrimPrefix(specifier, prefix)
189
- if strings.Contains(name, "/") || nestiaTypiaKnownModule(name) == false {
190
- return "", false
191
- }
192
- return name, true
193
- }
194
- }
195
- return "", false
196
- }
197
-
198
- func nestiaTypiaKnownModule(name string) bool {
199
- switch name {
200
- case "functional", "http", "json", "llm", "misc", "module", "notations", "protobuf", "reflect":
201
- return true
202
- default:
203
- return false
204
- }
205
- }
206
-
207
- func nestiaTypiaCallLooksPossible(call *shimast.CallExpression, roots map[string]nestiaTypiaImportRoot) bool {
208
- root, parts, ok := nestiaTypiaCallSegments(call)
209
- if ok == false {
210
- return false
211
- }
212
- info, ok := roots[root]
213
- if ok == false || len(parts) == 0 {
214
- return false
215
- }
216
- if info.module != "" {
217
- return true
218
- }
219
- if len(parts) == 1 {
220
- return true
221
- }
222
- return nestiaTypiaKnownModule(parts[0])
223
- }
224
-
225
- func nestiaTypiaCallSegments(call *shimast.CallExpression) (string, []string, bool) {
226
- if call == nil {
227
- return "", nil, false
228
- }
229
- expression := call.Expression
230
- parts := []string{}
231
- for expression != nil && expression.Kind == shimast.KindPropertyAccessExpression {
232
- property := expression.AsPropertyAccessExpression()
233
- if property == nil {
234
- return "", nil, false
235
- }
236
- name := property.Name()
237
- if name == nil || name.Kind != shimast.KindIdentifier {
238
- return "", nil, false
239
- }
240
- id := name.AsIdentifier()
241
- if id == nil || id.Text == "" {
242
- return "", nil, false
243
- }
244
- parts = append([]string{id.Text}, parts...)
245
- expression = property.Expression
246
- }
247
- if expression == nil || expression.Kind != shimast.KindIdentifier {
248
- return "", nil, false
249
- }
250
- root := expression.AsIdentifier()
251
- if root == nil || root.Text == "" {
252
- return "", nil, false
253
- }
254
- return root.Text, parts, true
255
- }
256
-
257
- func tryNestiaTypiaCallSite(file *shimast.SourceFile, checker *shimchecker.Checker, node *shimast.Node) (typiaadapter.CallSite, bool) {
258
- if checker == nil {
259
- return typiaadapter.CallSite{}, false
260
- }
261
- call := node.AsCallExpression()
262
- if call == nil {
263
- return typiaadapter.CallSite{}, false
264
- }
265
- signature := checker.GetResolvedSignature(node)
266
- if signature == nil {
267
- return typiaadapter.CallSite{}, false
268
- }
269
- declaration := signature.Declaration()
270
- if declaration == nil {
271
- return typiaadapter.CallSite{}, false
272
- }
273
- sourceFile := shimast.GetSourceFileOfNode(declaration)
274
- if sourceFile == nil {
275
- return typiaadapter.CallSite{}, false
276
- }
277
- module, ok := nestiaTypiaMatchModule(sourceFile.FileName())
278
- if !ok {
279
- return typiaadapter.CallSite{}, false
280
- }
281
- method := nestiaTypiaCallSiteMethodName(checker, declaration, call)
282
- if method == "" {
283
- return typiaadapter.CallSite{}, false
284
- }
285
- root, namespaces, ok := nestiaTypiaExtractRootAndNamespaces(call, method)
286
- if !ok {
287
- return typiaadapter.CallSite{}, false
288
- }
289
- return typiaadapter.CallSite{
290
- File: file,
291
- FilePath: file.FileName(),
292
- Module: module,
293
- Method: method,
294
- Call: call,
295
- RootName: root,
296
- Namespaces: namespaces,
297
- }, true
298
- }
299
-
300
- func nestiaTypiaMatchModule(location string) (string, bool) {
301
- location = filepath.ToSlash(location)
302
- for _, suffix := range []string{".d.ts", ".ts"} {
303
- for _, middle := range []string{"typia/lib/", "typia/src/", "packages/typia/src/"} {
304
- index := strings.LastIndex(location, middle)
305
- if index < 0 {
306
- continue
307
- }
308
- name := location[index+len(middle):]
309
- if !strings.HasSuffix(name, suffix) {
310
- continue
311
- }
312
- name = strings.TrimSuffix(name, suffix)
313
- if strings.Contains(name, "/") {
314
- continue
315
- }
316
- return name, true
317
- }
318
- }
319
- return "", false
320
- }
321
-
322
- func nestiaTypiaCallSiteMethodName(checker *shimchecker.Checker, declaration *shimast.Node, call *shimast.CallExpression) string {
323
- if name := declaration.Name(); name != nil {
324
- if symbol := checker.GetSymbolAtLocation(name); symbol != nil && symbol.Name != "" {
325
- return symbol.Name
326
- }
327
- if name.Kind == shimast.KindIdentifier {
328
- if id := name.AsIdentifier(); id != nil {
329
- return id.Text
330
- }
331
- }
332
- }
333
- if call.Expression != nil && call.Expression.Kind == shimast.KindPropertyAccessExpression {
334
- if property := call.Expression.AsPropertyAccessExpression(); property != nil {
335
- if name := property.Name(); name != nil && name.Kind == shimast.KindIdentifier {
336
- if id := name.AsIdentifier(); id != nil {
337
- return id.Text
338
- }
339
- }
340
- }
341
- }
342
- return ""
343
- }
344
-
345
- func nestiaTypiaExtractRootAndNamespaces(call *shimast.CallExpression, method string) (string, []string, bool) {
346
- expression := call.Expression
347
- segments := []string{}
348
- for expression != nil && expression.Kind == shimast.KindPropertyAccessExpression {
349
- property := expression.AsPropertyAccessExpression()
350
- if property == nil {
351
- break
352
- }
353
- name := property.Name()
354
- if name == nil || name.Kind != shimast.KindIdentifier {
355
- return "", nil, false
356
- }
357
- id := name.AsIdentifier()
358
- if id == nil || id.Text == "" {
359
- return "", nil, false
360
- }
361
- segments = append([]string{id.Text}, segments...)
362
- expression = property.Expression
363
- }
364
- if expression == nil || expression.Kind != shimast.KindIdentifier {
365
- return "", nil, false
366
- }
367
- root := expression.AsIdentifier()
368
- if root == nil || root.Text == "" || len(segments) == 0 {
369
- return "", nil, false
370
- }
371
- if segments[len(segments)-1] != method {
372
- return "", nil, false
373
- }
374
- return root.Text, segments[:len(segments)-1], true
375
- }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nestia/core",
3
- "version": "12.0.0",
3
+ "version": "12.1.0",
4
4
  "description": "Super-fast validation decorators of NestJS",
5
5
  "main": "lib/index.js",
6
6
  "exports": {
@@ -45,8 +45,8 @@
45
45
  },
46
46
  "homepage": "https://nestia.io",
47
47
  "dependencies": {
48
- "@typia/interface": "^13.0.2",
49
- "@typia/utils": "^13.0.2",
48
+ "@typia/interface": "^13.2.0",
49
+ "@typia/utils": "^13.2.0",
50
50
  "get-function-location": "^2.0.0",
51
51
  "glob": "^11.0.3",
52
52
  "path-parser": "^6.1.0",
@@ -54,9 +54,9 @@
54
54
  "reflect-metadata": ">=0.1.12",
55
55
  "rxjs": ">=6.0.3",
56
56
  "tgrid": "^1.1.0",
57
- "typia": "^13.0.2",
57
+ "typia": "^13.2.0",
58
58
  "ws": "^7.5.3",
59
- "@nestia/fetcher": "^12.0.0"
59
+ "@nestia/fetcher": "^12.1.0"
60
60
  },
61
61
  "peerDependencies": {
62
62
  "@modelcontextprotocol/sdk": "^1.18.0",
@@ -64,8 +64,8 @@
64
64
  "@nestjs/core": ">=7.0.1",
65
65
  "reflect-metadata": ">=0.1.12",
66
66
  "rxjs": ">=6.0.3",
67
- "typia": "^13.0.2",
68
- "@nestia/fetcher": "^12.0.0"
67
+ "typia": "^13.2.0",
68
+ "@nestia/fetcher": "^12.1.0"
69
69
  },
70
70
  "peerDependenciesMeta": {
71
71
  "@modelcontextprotocol/sdk": {
@@ -82,7 +82,7 @@
82
82
  "@types/ws": "^8.5.10",
83
83
  "fastify": "^4.28.1",
84
84
  "rimraf": "^6.1.3",
85
- "ttsc": "^0.18.4",
85
+ "ttsc": "^0.20.0",
86
86
  "tstl": "^3.0.0",
87
87
  "typescript": "^7.0.2"
88
88
  },
@@ -73,30 +73,38 @@ export class McpAdaptor {
73
73
  for (const wrapper of module.controllers.values()) {
74
74
  const instance = wrapper.instance;
75
75
  if (!instance) continue;
76
- const proto = Object.getPrototypeOf(instance);
77
- for (const key of Object.getOwnPropertyNames(proto)) {
78
- if (key === "constructor") continue;
79
- const method = proto[key];
80
- if (typeof method !== "function") continue;
76
+ const visited: Set<string> = new Set();
77
+ for (
78
+ let proto: any = Object.getPrototypeOf(instance);
79
+ proto !== null && proto !== Object.prototype;
80
+ proto = Object.getPrototypeOf(proto)
81
+ ) {
82
+ for (const key of Object.getOwnPropertyNames(proto)) {
83
+ if (key === "constructor" || visited.has(key)) continue;
84
+ visited.add(key);
85
+ const method = proto[key];
86
+ if (typeof method !== "function") continue;
81
87
 
82
- const meta: IMcpRouteReflect | undefined = Reflect.getMetadata(
83
- "nestia/McpRoute",
84
- method,
85
- );
86
- if (!meta) continue;
88
+ const meta: IMcpRouteReflect | undefined = Reflect.getMetadata(
89
+ "nestia/McpRoute",
90
+ method,
91
+ );
92
+ if (!meta) continue;
87
93
 
88
- const params: IMcpRouteReflect.IArgument[] =
89
- Reflect.getMetadata("nestia/McpRoute/Parameters", proto, key) ?? [];
90
- const paramValidator = params.find(
91
- (p) => p.category === "params",
92
- )?.validate;
94
+ const params: IMcpRouteReflect.IArgument[] =
95
+ Reflect.getMetadata("nestia/McpRoute/Parameters", proto, key) ??
96
+ [];
97
+ const paramValidator = params.find(
98
+ (p) => p.category === "params",
99
+ )?.validate;
93
100
 
94
- tools.push({
95
- meta,
96
- source: `${wrapper.metatype?.name ?? proto.constructor?.name ?? "UnknownController"}.${String(key)}`,
97
- validateArgs: paramValidator,
98
- handler: async (args) => method.call(instance, args),
99
- });
101
+ tools.push({
102
+ meta,
103
+ source: `${wrapper.metatype?.name ?? proto.constructor?.name ?? "UnknownController"}.${String(key)}`,
104
+ validateArgs: paramValidator,
105
+ handler: async (args) => method.call(instance, args),
106
+ });
107
+ }
100
108
  }
101
109
  }
102
110
  }
@@ -13,6 +13,7 @@ import { Singleton } from "../utils/Singleton";
13
13
  import { ENCRYPTION_METADATA_KEY } from "./internal/EncryptedConstant";
14
14
  import { get_text_body } from "./internal/get_text_body";
15
15
  import { headers_to_object } from "./internal/headers_to_object";
16
+ import { is_media_type } from "./internal/is_media_type";
16
17
  import { validate_request_body } from "./internal/validate_request_body";
17
18
 
18
19
  /**
@@ -47,7 +48,7 @@ export function EncryptedBody<T>(
47
48
  const request: express.Request | FastifyRequest = context
48
49
  .switchToHttp()
49
50
  .getRequest();
50
- if (isTextPlain(request.headers["content-type"]) === false)
51
+ if (is_media_type(request.headers["content-type"], "text/plain") === false)
51
52
  throw new BadRequestException(`Request body type is not "text/plain".`);
52
53
 
53
54
  const param: IEncryptionPassword | IEncryptionPassword.Closure | undefined =
@@ -87,11 +88,3 @@ const decrypt = (body: string, key: string, iv: string): string => {
87
88
  else throw exp;
88
89
  }
89
90
  };
90
-
91
- /** @internal */
92
- const isTextPlain = (text?: string): boolean =>
93
- text !== undefined &&
94
- text
95
- .split(";")
96
- .map((str) => str.trim())
97
- .some((str) => str === "text/plain");
@@ -173,7 +173,7 @@ class EncryptedRouteInterceptor implements NestInterceptor {
173
173
  context.getClass(),
174
174
  );
175
175
  if (!param)
176
- return Error(
176
+ throw new Error(
177
177
  `Error on EncryptedRoute.${this.method}(): no password found.`,
178
178
  );
179
179
 
@@ -137,11 +137,12 @@ export namespace McpRoute {
137
137
  propertyKey: string | symbol,
138
138
  value: IMcpRouteReflect.IArgument,
139
139
  ) => {
140
- const array: IMcpRouteReflect.IArgument[] | undefined = Reflect.getMetadata(
141
- "nestia/McpRoute/Parameters",
142
- target,
143
- propertyKey,
144
- );
140
+ const array: IMcpRouteReflect.IArgument[] | undefined =
141
+ Reflect.getOwnMetadata(
142
+ "nestia/McpRoute/Parameters",
143
+ target,
144
+ propertyKey,
145
+ );
145
146
  if (array !== undefined) array.push(value);
146
147
  else
147
148
  Reflect.defineMetadata(
@@ -24,8 +24,8 @@ export namespace NoTransformConfigurationError {
24
24
  *
25
25
  * Even if the transform did not run, the error will not be thrown and the
26
26
  * program will be continued. Instead, every validation and assertion will be
27
- * skipped and the value
28
- * will be returned as it is. Furthermore, unexpected behaviors may occur.
27
+ * skipped and the value will be returned as it is. Furthermore, unexpected
28
+ * behaviors may occur.
29
29
  *
30
30
  * Therefore, it is not recommended to set this value to `false` in production
31
31
  * environment. Configure this value to be `false` only when you're debugging
@@ -7,6 +7,7 @@ import type express from "express";
7
7
  import type { FastifyRequest } from "fastify";
8
8
 
9
9
  import { get_text_body } from "./internal/get_text_body";
10
+ import { is_media_type } from "./internal/is_media_type";
10
11
  import { is_request_body_undefined } from "./internal/is_request_body_undefined";
11
12
  import { validate_request_body } from "./internal/validate_request_body";
12
13
 
@@ -56,7 +57,7 @@ export function PlainBody(
56
57
  (checker ?? (() => null))(undefined as any) === null
57
58
  )
58
59
  return undefined;
59
- else if (!isTextPlain(request.headers["content-type"]))
60
+ else if (!is_media_type(request.headers["content-type"], "text/plain"))
60
61
  throw new BadRequestException(`Request body type is not "text/plain".`);
61
62
  const value: string = await get_text_body(request);
62
63
  if (checker) {
@@ -66,11 +67,3 @@ export function PlainBody(
66
67
  return value;
67
68
  })();
68
69
  }
69
-
70
- /** @internal */
71
- const isTextPlain = (text?: string): boolean =>
72
- text !== undefined &&
73
- text
74
- .split(";")
75
- .map((str) => str.trim())
76
- .some((str) => str === "text/plain");
@@ -23,8 +23,14 @@ export function SwaggerCustomizer(
23
23
  descriptor: TypedPropertyDescriptor<any>,
24
24
  ) {
25
25
  const array: Array<(props: SwaggerCustomizer.IProps) => unknown> = (() => {
26
- if (Reflect.hasMetadata("nestia/SwaggerCustomizer", target, propertyKey))
27
- return Reflect.getMetadata(
26
+ if (
27
+ Reflect.hasOwnMetadata(
28
+ "nestia/SwaggerCustomizer",
29
+ target,
30
+ propertyKey,
31
+ )
32
+ )
33
+ return Reflect.getOwnMetadata(
28
34
  "nestia/SwaggerCustomizer",
29
35
  target,
30
36
  propertyKey,